in case it's unclear what the problem is
when i close the menu, if it's the first time i've clicked the header since refreshing, it snaps shut even though i'm trying to make it animate
if i place a javascript breakpoint after some of the work i do on the click, but before adding the class to the div that starts the animation, nothing should be different but suddenly it works
what i'm trying to do
i have a div with overflow: hidden. i want to set its height to either 0, or whatever it would have been if it was set to auto. but you can't animate with auto, so i'm trying to work around that
the only child of that div is another div. the only reason i have this one is so that i can read its height. since there's no padding or margins or anything, this div's height will always be the same as what the outer div's height would be if it had height: auto
then i put a style attribute directly on the div setting its height to the height of the child. when i want to hide the div, i give it a class with height: 0 !important;. this overrides the height in the style attribute and closes the div. when i want to show the div again, i remove that class, the height in the style attribute is no longer overridden, and it opens again
BUT. at the time i'm creating all these elements, the browser hasn't rendered them yet. if i try to read the height of the child i just get 0. so what i'm trying to do is get the height of the child in the click handler and set the style attribute there, just before adding or removing the class
javascript inside
breaks:
const optionsDiv = this.nextSibling;
optionsDiv.style.height = `${optionsDiv.children[0].clientHeight}px`;
if (hidden) {
optionsDiv.classList.add("_hidden");
} else {
optionsDiv.classList.remove("_hidden");
}
works:
const optionsDiv = this.nextSibling;
optionsDiv.style.height = `${optionsDiv.children[0].clientHeight}px`;
setTimeout(() => {
if (hidden) {
optionsDiv.classList.add("_hidden");
} else {
optionsDiv.classList.remove("_hidden");
}
}, 1000);
like i was hesitant to call it a race condition but
this is supposed to work, right? i'm setting the height attribute to something equivalent to auto but numerical (i've confirmed that this is working btw) and then immediately giving it a class that overrides that attribute with a height of 0. but it seems that if i don't wait long enough after setting that height attribute, it doesn't go through in the DOM fast enough for the transition to kick in
i have discovered something extremely cursed
i can fix it by inserting the following line of code between where i set the style attribute and where i set the class:
offsetDiv.clientHeight;
i don't need to do anything with the value, just accessing it fixes the problem somehow. offsetDiv.offsetHeight also works. but offsetDiv.style.height, for example, does not
re: minor remark re: the comment
@Lady idk why
re: minor remark re: the comment
@monorail oof, i wonder if you need two requestAnimationFrames (because you want the frame after the current one), in which case yeah probably what you have now is less cursed if it works
re: minor remark re: the comment
@Lady what i could have done was just, before messing with the class, added this line:
outer.clientHeight;
does nothing, but forces a reflow
vy said that was worse practice than just letting it happen though
re: minor remark re: the comment
@Lady i actually tried
requestAnimationFrameand it didn't work