Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

661
Visualizações
Why getComputedStyle() is not getting actual width and height is there any callback or event exists

I'm in such a situation where i need to wait till the image gets loaded once the image gets loaded i need to gets its computed height so that i can set the yellow color selector accordingly.

Question: based on computed height of image i'm setting yellow color selector. it works with setTimeout() randomly but i don't want such approach.

let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];

let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`


document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;

//actual code

let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');

let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');

console.log('height',height,'width',imageWidth);

wrapImage = `<div style="width:calc(${imageWidth} + 10px);height:calc(${height} + 10px);position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;

document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage);
.box{
   width:100%;
   height:auto;
   border:1px solid red;
   position:relative;
}
<div id="content">

</div>

with setTimeout it works but i don't want such approach,i want callback or some event once element is ready

let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];

let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`


document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;

//actual code

setTimeout(() => {
   let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');

let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');

console.log('height',height,'width',imageWidth);

wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;

document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage);

document.querySelector('.select').height = document.querySelector('.select').height + 10;

console.log('after computed height and added 10px',window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'));

},700);
.box{
   width:100%;
   height:auto;
   border:1px solid red;
   position:relative;
}
<div id="content">

</div>

Please help me thanks in advance !!!

over 4 years ago · Santiago Trujillo
6 Respostas
Responde à pergunta

0

The image hasn't finished loading when you retrieved the height and width. To solve this, you'll need to wait for the images to load first, then get their height and width.

Listen for the window load event, which will fire when all resources (including images) have loaded completely:

let images = ['https://via.placeholder.com/150', 'https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com', 'https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];

let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`


document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;

//actual code

window.addEventListener('load', function() {
  let height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');

  let imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');

  console.log('height', height, 'width', imageWidth);

  wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;

  document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage);

  document.querySelector('.select').height = document.querySelector('.select').height + 10;

  console.log('after computed height and added 10px', window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'));

});
.box {
  width: 100%;
  height: auto;
  border: 1px solid red;
  position: relative;
}
<div id="content">

</div>

over 4 years ago · Santiago Trujillo Relatório

0

To indicate selection you can use CSS outline property. That way you won't have to manage selection dimensions yourself.
Following is demo code. As you want to do it over multiple images, I've added 3 images. And you can select multiple images.

function changeImages() {
  var images = document.getElementsByTagName('img');
  for (var i = 0; i < images.length; i++) {
    images[i].src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 50).toString() + "/0a0a0a/ffffff";
  }
}

function setClickEvents() {
  var images = document.getElementsByTagName('img');
  for (var i = 0; i < images.length; i++) {

    images[i].addEventListener("click", function(event) {
      event.target.classList.toggle("selected");
    });;

  }
}

function init() {
  document.getElementById('content').innerHTML = `<div id="box"></div>`;

  var box = document.getElementById('box');
  var img = document.createElement("img");
  img.classList.add("selected");
  box.appendChild(img);
  box.appendChild(document.createElement("img"));
  box.appendChild(document.createElement("img"));

  setClickEvents();
  changeImages();
}
#content {
  padding: 15px;
  margin: 10px;
}

#box {
  width: 100%;
  height: 120px;
  border: 1px dotted red;
  position: relative;
}

img {
  margin: 15px;
}


/* use this class for marking selected elements */
.selected {
  outline: thick double #f7d205;
  outline-offset: 7px;
}
<!DOCTYPE html>
<html lang="en">

<body onload="init()">
  <button onclick="changeImages()">Change Images</button>

  <div id="content"></div>
</body>

</html>

Click on image to toggle selection.

over 4 years ago · Santiago Trujillo Relatório

0

If you want more flexibility then you can use Resize Observer. With this when you change src attribute of image tag you'll able to change selection size.

const imageObserver = new ResizeObserver(function(entries) {
  for (let entry of entries) {
    var img = entry.target;
    let height = img.height + 10;
    let width = img.width + 10;

    console.log('Added 10px. height:', height, ' width:', width);

    wrapImage = `<div class="select" style="width:${width}px;height:${height}px;position:absolute;left:0;top:0;border:1px solid #f7d205;"></div>`;
    document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage);
  }
});

function init() {
  document.getElementById('content').innerHTML = `<div id="box" class="box"></div>`;

  var box = document.getElementById('box');
  var img = document.createElement("img");
  img.src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 80).toString() + "/0a0a0a/ffffff";
  box.appendChild(img);
  imageObserver.observe(img);
}
<!DOCTYPE html>
<html lang="en">
<style>
  #box {
    width: 100%;
    border: 1px dotted red;
    position: relative;
  }
</style>

<body onload="init()">
  <div id="content"></div>
</body>

</html>


Note: Using same ResizeObserver you can observe multiple images:

var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
  imageObserver.observe(images[i]);
}

Edit: As requested, demonstrating observing img resize from parent div element. Here the image is wrapped in div #box. On resize img dispatches a custom event and parent handles it.

function handleChildResize(event) {
  console.log('parent: got it! handling it.. ')
  var img = event.data;
  let height = img.offsetHeight + 10;
  let width = img.offsetWidth + 10;

  console.log('Added 10px. height:', height, ' width:', width);

  wrapImage = `<div class="select" style="width:${width}px;height:${height}px;position:absolute;left:0;top:0;border:2px solid #f7d205;"></div>`;
  if (document.querySelector('.box > .select')) {
    document.querySelector('.box > .select').remove();
  }
  document.querySelector('.box').insertAdjacentHTML('beforeend', wrapImage);
  event.stopPropagation();
}

const imgObserver = new ResizeObserver(function(entries) {
  for (let entry of entries) {
    var img = entry.target;
    var event = new Event('childResized');
    event.data = img;
    console.log("img: i am resized. Raising an event.");
    img.dispatchEvent(event);
  }
});

function init() {
  var box = document.getElementById('box');
  box.addEventListener('load', (event) => {
    console.log('The page has fully loaded');
  });
  var img = document.createElement("img");
  img.src = "https://via.placeholder.com/" + Math.floor(Math.random() * 50 + 80).toString() + "/0a0a0a/ffffff";
  box.appendChild(img);
  imgObserver.observe(img);
  box.addEventListener('childResized', handleChildResize, true);
}
<!DOCTYPE html>
<html>
<head>
  <style>
    #box {
      width: 100%;
      padding: 10px;
      border: 1px solid red;
      position: relative;
    }
  </style>
</head>

<body onload="init()">
  <div id="content">
    <div id="box" class="box"></div>
  </div>
</body>

</html>

over 4 years ago · Santiago Trujillo Relatório

0

I see that you are creating your imgNode on a fly using ternary which means you do not have it pre-created in your HTML. So for that, you can use the solution as below by creating an Image constructor.

const images = [
  "https://via.placeholder.com/150",
  "https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com",
  "https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com"
];

const img = new Image();

img.addEventListener("load", (ev) => {
  console.log(ev);

  document.getElementById(
    "content"
  ).innerHTML = `<div class="box">${ev.target}</div>`;

  const height = window
    .getComputedStyle(document.querySelector(".box"), null)
    .getPropertyValue("height");

  const imageWidth = window
    .getComputedStyle(document.querySelector(".box img"), null)
    .getPropertyValue("width");

  console.log("height", height, "width", imageWidth);

  const wrapImage = `<div style="width:calc(${imageWidth} + 10px);height:calc(${height} + 10px);position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;

  document.querySelector(".box").insertAdjacentHTML("beforeend", wrapImage);
});

img.src = `${images[Math.floor(Math.random() * images.length)]}`;
over 4 years ago · Santiago Trujillo Relatório

0

You could consider adding the 'load' event listener as a callback for image loading. Please check the example:

const image = document.getElementById('image');
const handler = () => {
  alert(image.height);
};

image.addEventListener('load', handler);
<img src="https://image.shutterstock.com/z/stock-vector-sample-stamp-grunge-texture-vector-illustration-1389188336.jpg" id="image" />

over 4 years ago · Santiago Trujillo Relatório

0

I see that you want to compute the final value of the get computed style you see. The thing is that the getComputedStyle doesn't get updated. So just make a function to do it!

let images = ['https://via.placeholder.com/150','https://via.placeholder.com/110/0000FF/808080%20?Text=Digital.com','https://via.placeholder.com/80/0000FF/808080%20?Text=Digital.com'];'

let image = `<img src="${images[Math.floor(Math.random()*images.length)]}"/>`


document.getElementById('content').innerHTML = `<div class="box">${image}</div>`;

//actual code

setTimeout(() => {
   let height;
   let imageWidth;
   function calculateHeightAndWidth() {
        
height = window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height');

imageWidth = window.getComputedStyle(document.querySelector('.box img'), null).getPropertyValue('width');

   }
   calculateHeightAndWidth()


console.log('height',height,'width',imageWidth);

wrapImage = `<div class="select" style="width:calc(${imageWidth} + 10px);height:${height};position:absolute;left:0;top:0;border:1px solid yellow;"></div>`;

document.querySelector('.box').insertAdjacentHTML('beforeend',wrapImage);

document.querySelector('.select').height = document.querySelector('.select').height + 10;

calculateHeightAndWidth()
console.log('after computed height and added 10px',window.getComputedStyle(document.querySelector('.box'), null).getPropertyValue('height'));

},700);
.box{
   width:100%;
   height:auto;
   border:1px solid red;
   position:relative;
}
<div id="content">

</div>

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda