outerHeight() and height() give 0, after element is shown with "display: block" within an event

Viewed 88

I am working on a part of page, where I have 4 main divs, one of the divs has its height calculated depending on the heights of the other divs, and one of these other divs can disappear.

<div header></div>
<div divWithCalculatedHeight></div>
<div checkout></div>
<div disappearingDiv></div>

The way I am calculating the height of the 2nd div is pretty simple totalHeight - $header.outerHeight() - $checkout.outerHeight() - $disappearingDiv.outerHeight() and while all divs are visible this is working just fine. However I have buttons with events attached to them, that can make the 4th div disappear and appear back again. And this is my issue:

$buttonHide.trigger("hideFourthDiv")

$disappearingDiv.on("hideFourthDiv", () => { 
    $disappearingDiv.css({ display: "none" }); 
    calculateNew2ndDivHeightAndSetIt();
});

And this works just fine, but the reappearing:

$buttonShow.trigger("showFourthDiv")

$disappearingDiv.on("showFourthDiv", () => { 
    $disappearingDiv.css({ display: "block" }); // i have also tried with "initial"

    console.log($disappearingDiv.outerHeight()); // this here gives 0, so height of 2nd div cant be calculated properly

    calculateNew2ndDivHeightAndSetIt();
});

This here is my issue, when I make the div re-appear, while still inside the event, the outerHeight() returns 0, I have also tried with height() it too returns 0. Now it is important to note here that, if I click the button twice, on the second click it will work, which in a way coincides with my further thoughts:

Now, if click the buttonShow to trigger the showign event (just once!), and then I go into my browser console and manually type $disappearingDiv.outerHeight(), it does give me the correct height and not a 0!

So I thought that maybe, since I am still within the event, at that point in time, the DOM maybe is not yet updated, and jQuery doesnt see the "shown" element, so with that in mind I searched for a way to trigger my function outside of the event, once the div is shown and I found out about MutationObserver

So I tried implementing it:

const target = $disappearingDiv;
const config = { childList: true, subtree: true};
const callback = () => {console.log($disappearingDiv.height())};
const observer = new MutationObserver(callback);

observer.observe(target, config);

That code is not placed within any of the 2 events, it is inside the "DOMContentLoaded" event.

It does get triggered, when I hide/show, but it still gives me a 0 the first time I click the button.

So my question I am guessing is, how to manage to get the height of the disappearingDiv once it has reappered, from the first call of the events, so that I dont have to click the button two times.

Edit: I figured out what is the issue, but I can't find solution, when css is applied, it applies it inline, but the browser is not repainting immediatelly or whatever, that is why when I immediatelly check for height it is not yet available. I need to wait for the css of the element to be updated and then get the height. If I place the updating function within a timeout it will work with a timeout of as low as 1 ms. I have opened a new question after these new findings: Wait for css of element to be updated when it is dynamically changed with JS/Jquery

1 Answers

You could use requestAnimationFrame() to wait for a render to happen before checking the height of the div. This would be doing something like using setTimeout but with waiting for the next render instead of waiting or n amount of milliseconds.

$disappearingDiv.on("showFourthDiv", () => { 
  $disappearingDiv.css({ display: "block" }); // i have also tried with "initial"
  
  requestAnimationFrame(() => {
    console.log($disappearingDiv.outerHeight()); // this here gives 0, so height of 2nd div cant be calculated properly.
    calculateNew2ndDivHeightAndSetIt();
  });
});
Related