I have a fixed top navbar with dropdowns. I want to slide the dropdown menus in on hover. I want that the menu is behind the navbar while sliding in. So I've simply tried to set the z-index
of both elements which unfortunately did not work for me.
Here a simplified example (codepen)
html
<div class="fixed-top">
<span class="trigger">hover me</span>
<div class="menu"></div>
</div>
css
.fixed-top {
background: #3b5999;
height: 50px;
width: 100%;
padding: 0;
top: 0;
position: fixed;
z-index: 2;
}
.trigger {
z-index: 2;
font-size: 33px;
color: white;
margin-left: 50%;
}
.trigger:hover + .menu {
margin-top: 0;
}
.menu {
z-index: 1;
height: 300px;
background-color: #1c7754;
width: 400px;
margin: auto;
margin-top: -400px;
transition: all 0.75s ease-out;
}
In case it's not clear what I want to do here a simple mspaint sketch ;)
So remember: z-index is indeed one of the properties you can apply a transition to, but the transition has to happen in full steps, not necessarily as gradually as you might imagine it in your head.
Yes, you can animate z-index ! It's not visually apparent in this demo, but seeing the interpolated values go from 1 to 5 confirms it.
In CSS code bases, you'll often see z-index values of 999, 9999 or 99999. This is a perhaps lazy way to ensure that the element is always on top. It can lead to problems down the road when multiple elements need to be on top. Most of the time you'll find that a z-index of 1 or 2 will suffice for your needs.
The z-index property in CSS controls the vertical stacking order of elements that overlap. As in, which one appears as if it is physically closer to you. z-index only affects elements that have a position value other than static (the default).
This is an extremely common error when beginning to work with stacking contexts in CSS. Basically, you just have to remember that a child cannot exist in a different stacking context from a parent.
So if I have a non-static element (meaning an element with position: anything-but-static [fixed, relative, absolute]
), and if that element has no non-static parent element, then it will be at stacking context level 1, no matter where it is in the DOM. Now if that element has a non-static child element, that child will be at stacking context level 2. It cannot be on the same level (level 1) as its parent element. z-index
can only affect elements on the same stacking context level, it has nothing to do with elements on different stacking context levels.
The solution is to restructure your HTML, or just use a :before
or :after
pseudo-element, thus:
.fixed-top {
height: 50px;
width: 100%;
padding: 0;
top: 0;
position: fixed; /* The parent: stacking context level 1 */
}
.fixed-top:before {
background: #3b5999;
content:'';
position: absolute; /* stacking context level 2 */
top: 0; right: 0; bottom: 0; left: 0;
z-index: 1;
}
.trigger {
color: white;
font-size: 33px;
margin-left: 50%;
position: relative; /* also stacking context level 2 */
z-index: 2;
}
.trigger:hover + .menu {
margin-top: 0;
}
.menu { /* bottom layer -- no stacking context necessary */
z-index: 0;
height: 300px;
background-color: #1c7754;
width: 400px;
margin: auto;
margin-top: -400px;
transition: all 0.75s ease-out;
}
Note the comments denoting the stacking context levels.
And here's a JSFiddle for an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With