Can someone shed a tiny bit of light on what is happening here?
Looking at the console I see three apparently incompatible numbers: on the same element temp0 (the highlighted one in the console, location pointed by the arrow, it's an asterisk), if I check style.top I get a value, inspecting the inline CSS a second one, and through getBoundingClientRect.top a third. What am I missing, or what could be the cause of something like this?
The structure of the html from top to bottom is: a couple of navbars, a div that takes up 30% of the viewport height, a second div that uses the remaining ~70%, organized in three columns through bootstrap 4.5 (size 1-10-1).
The background is: I lost count of how many questions and articles have been reading trying to solve what looks like a silly alignment bug that keeps popping out in my code.
Tonight I thought I had found something definitive in this function and detailed article, yet another two hours disappeared to no avail. When I saw the results of these three commands in the console I realized I needed help :P I would really appreciate any hint on what I am missing.
I'm not sure what you else you have going on in your page, but it looks like you tried to set the element's style.top to 320.75px and although the console prints it out it doesn't look like the inline style was actually affected.
style.top is the equivalent of the inline style (and not anything defined in CSS). See the example below. style.top may not accurately represent where an element actually is on-screen. The first inner element has the default position: static so even tough it has a top set both inline and CSS, neither affects the element, yet style.top still shows 100px.
getBoundingClientRect() is always relative to the window. The first inner element is actually 8px from the top of the page, which rect.top shows. The second inner element has position: absolute, so it is being affected by style.top and it actually is 250px from the top of the page.
console.log('inner1 rect.top: ' +inner1.getBoundingClientRect().top);
console.log('inner1 style.top: ' +inner1.style.top);
console.log('inner2 rect.top: ' +inner2.getBoundingClientRect().top);
console.log('inner2 style.top: ' +inner2.style.top);
#outer {
background: red;
display: block;
height: 400px;
width: 400px;
}
#inner1 {
background: yellow;
display: block;
height: 100px;
top: 5px;
width: 100px;
}
#inner2 {
background: blue;
display: block;
height: 100px;
top: 5px;
width: 100px;
}
<div id="outer">
<div id="inner1" style="top:100px;"></div>
<div id="inner2" style="position:absolute; top:250px;"></div>
</div>
So the solution was (ehm) simple:
Now how does the position absolute work? The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to its closest positioned ancestor, if any; otherwise, it is placed relative to the initial containing block. Its final position is determined by the values of top, right, bottom, and left. (from Mozilla WDN)
(bold & italic mine)
So as far as I understand: Because the container had position: absolute; the child was positioned relative to the container rather than the document itself. So no matter how hard I was trying, the top information of the two elements was never in sync, nor setting style.top based on that information could work.
Sometimes I feel hopeless in the face of CSS's subtleties, but hey maybe I got this one right.
Thank you @skyline3000 and @Kaiido for your clues.