Salil Naik
Posted on June 5, 2021
TL;DR
An element with
position:fixed
is positioned relative to the document (the viewport) which acts as its containing block.But, it will NOT always be relative to the document. When any element has
transform
,filter
orperspective
property, it acts as a containing block for all its descendants, including the elements whose position is set to fixed.
Now, the long story...
While I was working on enhancing the navigation bar of the
Polygon Wallet, I found myself stuck with a strange error. I spent almost a day trying to figure out the issue, consulted with the senior frontend engineers and also thought of making a separate Vue component as a workaround.
When I finally found the bug, I wouldn't shy away to say that my ego went crashing down, as it was a CSS bug, and my CSS skills are something I take pride in.
I was doing some changes to the code to align the dropdown menus to the cente of the navigation item (as shown in the picture below) for which I had to move the dropdown component inside the <li>
. Doing this would allow me to use the CSS position and transform properties to align the dropdown exactly at the bottom-center of the navigation item.
Till now, everything was working fine and nothing was unusual and unexpected.
Inside the dropdown menu, there were a bunch of notification items, which when clicked would open the modal component.
The components were nested something like this
<li>
<span>Notifications</span>
<dropdown-menu>
<item>
<modal />
</item>
<item>
<modal />
</item>
</dropdown-menu>
</li>
The modal component, which was supposed to open at the center of the screen when clicked on the item, would just behave weirdly and open inside the dropdown menu itself. I was sure that, any element with a fixed position would ignore all its ancestors and position itself relative to the document (the viewport or the root element). But that just didn't happen. The ancestor element, in this case, the dropdown menu was acting as a containing block for the modal component.
And as you might have guessed, it was due to the transform property. Any element with transform
, filter
or perspective
property will act as a containing block to all its descendants, including the elements whose position is set to fixed. Hence the modal, instead of positioning itself with respect to the document, positioned itself relative to the dropdown-menu component where I had used the transform property to align it exactly at the bottom-center of the navigation item. See CSS Transform Spec
How did I fix it?
Well, there is no fix for that, I just removed the transform property, gave a fixed width to all the dropdown components and achieved the same result with the help of the margin and position properties. But this uncanny relationship between position and transform property reminded me why CSS takes the crown as my favorite language even when I have a multi-paradigm language like JavaScript in my stack. ❤
Thank you!
If you want to learn about CSS positions, refer to
CSS Tricks
MDN Web Docs
Posted on June 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.