Why does z-index not work?
Asked Answered
S

13

325

So if I understand z-index correctly, it would be perfect in this situation:

enter image description here

I want to place the bottom image (the tag/card) below the div above it. So you can't see the sharp edges. How do I do this?

z-index:-1 // on the image tag/card

or

z-index:100 // on the div above

doesn't work either. Neither does a combination of anything like this. How come?

Scurf answered 8/2, 2012 at 10:47 Comment(2)
Sometime we make mistake of appying position value other than static only to one element. We should ensure that we're applying the position property to all the elements being stacked on the basis of z-index else it doesn't work.Exhibitor
Some useful hints on this linked other question, which could be of use. You would have to share the elements and all their actual styles for somebody to advice about if this is the case more specifically than RBT did #33217907Siberia
W
680

The z-index property only works on elements with a position value other than static (e.g. position: absolute;, position: relative;, position: fixed or position: sticky).

Note that position: sticky; is prefixed in Safari 7.1-12 and not available on many browsers before 2016.

Wafer answered 8/2, 2012 at 10:50 Comment(6)
It is also depending on other factors to create Stacking Context.Bifoliolate
adding to this answer, chrome and likely other browsers as of this writing require that you explicitly state position: relative for z-index to work, despite elements behaving in other relative ways by defaultUnyoke
static elements are static and can't move around in x, y or z planes. They can't move in x plane (left or right) or y plane (top or bottom) like when we work with position: absolute. And nor can they move in the z plane i.e. with z-index.Fluoridation
are you aware of any issues with using z-index in a grid element??Prickly
sticky is now supported by all modern browsers: caniuse.com/css-stickyChemisorb
In my case, it was due to the fixed element not having a background color, it seemed like it was not overlaying, but in reality it was, but only with the foreground colors.Greywacke
I
148

If you set position to other value than static but your element's z-index still doesn't seem to work, it may be that some parent element has z-index set.

The stacking contexts have hierarchy, and each stacking context is considered in the stacking order of the parent's stacking context.

So with following html

div { border: 2px solid #000; width: 100px; height: 30px; margin: 10px; position: relative; background-color: #FFF; }
#el3 { background-color: #F0F; width: 100px; height: 60px; top: -50px; }
<div id="el1" style="z-index: 5"></div>
<div id="el2" style="z-index: 3">
  <div id="el3" style="z-index: 8"></div>
</div>

no matter how big the z-index of el3 will be set, it will always be under el1 because it's parent has lower stacking context. You can imagine stacking order as levels where stacking order of el3 is actually 3.8 which is lower than 5.

If you want to check stacking contexts of parent elements, you can use this:

var el = document.getElementById("#yourElement"); // or use $0 in chrome;
do {
    var styles = window.getComputedStyle(el);
    console.log(styles.zIndex, el);
} while(el.parentElement && (el = el.parentElement));

There is a great article about stacking contexts on MDN

Immoderate answered 3/10, 2017 at 9:32 Comment(4)
how to fix that?Tate
set proper z-index of parent elements.Immoderate
Just for note: when your parent element has position: sticky and it does not have z-index then whatever z-index you set to its child elements it will not work, you have to set some z-index for parent element, maybe it's true for all position types: sticky, relative, absolute etc but it was sticky in my case.Palua
All around great answer. Snippet was perfect for identifying the problem or quickly ruling out this solution.Kaceykachina
F
46

Your elements need to have a position attribute. (e.g. absolute, relative, fixed) or z-index won't work.

Fuhrman answered 8/2, 2012 at 10:51 Comment(0)
S
31

In many cases an element must be positioned for z-index to work.

Indeed, applying position: relative to the elements in the question would likely solve the problem (but there's not enough code provided to know for sure).

Actually, position: fixed, position: absolute and position: sticky will also enable z-index, but those values also change the layout. With position: relative the layout isn't disturbed.

Essentially, as long as the element isn't position: static (the default setting) it is considered positioned and z-index will work.


Many answers to "Why isn't z-index working?" questions assert that z-index only works on positioned elements. As of CSS3, this is no longer true.

Elements that are flex items or grid items can use z-index even when position is static.

From the specs:

4.3. Flex Item Z-Ordering

Flex items paint exactly the same as inline blocks, except that order-modified document order is used in place of raw document order, and z-index values other than auto create a stacking context even if position is static.

5.4. Z-axis Ordering: the z-index property

The painting order of grid items is exactly the same as inline blocks, except that order-modified document order is used in place of raw document order, and z-index values other than auto create a stacking context even if position is static.

Here's a demonstration of z-index working on non-positioned flex items: https://jsfiddle.net/m0wddwxs/

Savonarola answered 18/5, 2016 at 21:14 Comment(3)
"Elements that are flex items or grid items can use z-index even when position is static." Yep, the spec essentially says to treat position: static the exact same as it would treat position: relative for flex and grid items due to the dynamic nature of those methods of layout. So I would perhaps say it's not that it's no longer true in CSS3 that an element needs to be positioned, but that CSS3 treats flex and grid items as if they were positioned, regardless. Just two ways of looking at the same thing, though, probably.Diversion
@Diversion we should pay attention to that part of the spec because we should treat static the same as relative only when dealing with z-index and not in general. You cannot for example shift a flex item using left/top/bottom/right unless you explicitely speficy position:relative. Descendants of flex items with absolute position will not consider the flex item as their containing block because the flex item is not positionned. (jsfiddle.net/0yo7utfL/2)Phenetidine
i found a wierd "bug" with css. for some reason overflow-y: scroll prevents overflow-x: visible from working... can you please take a look?Prickly
C
16

Make sure that this element you would like to control with z-index does not have a parent with z-index property, because element is in a lower stacking context due to its parent’s z-index level.

Here's an example:

<section class="content">            
    <div class="modal"></div>
</section>

<div class="side-tab"></div>

// CSS //
.content {
    position: relative;
    z-index: 1;
}

.modal {
    position: fixed;
    z-index: 100;
}

.side-tab {
    position: fixed;
    z-index: 5;
}

In the example above, the modal has a higher z-index than the content, although the content will appear on top of the modal because "content" is the parent with a z-index property.

Here's an article that explains 4 reasons why z-index might not work: https://coder-coder.com/z-index-isnt-working/

Cumulonimbus answered 27/10, 2020 at 12:29 Comment(0)
G
14

Z-index needs these to work:

  1. Position: relative, absolute, fixed, ..
  2. Make sure that the parent element hasn't overflow: hidden;
Glide answered 2/6, 2022 at 18:33 Comment(1)
Thank you very much for the overflow note! That was the issue in my caseRae
G
4

I had the same problem with z-index and fixed it by setting the background color like this:

 background-color: white;
Gamal answered 2/8, 2022 at 13:11 Comment(0)
B
0

I got my answer from codercoder.com: In my code I have set my Navbar's opacity to 0.9.

Once you remove the opacity property from the Navbar's CSS, the z-index works as expected.

Batholomew answered 27/9, 2021 at 4:12 Comment(1)
Thanks, in my case was the backdrop-filterIncoordinate
B
0

If all else fails, look for syntax errors in your HTML. It's not intuitive, but I've seen it be the reason why z-index doesn't work.

The following code has invalid HTML syntax:

<div class="over"/>
<div class="under"/>

...(it's is invalid syntax because a div isn't a self closing tag).

CSS properties that were applied to these rogue HTML elements, such as background-color: black, position: fixed, width: 150px, and top:150px, were all working as expected. However, the z-index: 2 property wasn't working under the exact same conditions.

Only when the invalid HTML was fixed did the z-index work correctly.

I'm not sure why z-index was pickier than the other CSS attributes, but maybe this answer can help someone.

Baca answered 9/8, 2022 at 21:49 Comment(0)
C
0

In addition to transform interfering with z-index working, I'd also like to add that using the 'perspective' property can also stop z-index from working correctly.

Curtsy answered 21/9, 2023 at 23:28 Comment(0)
H
0

Just in case if you have set legit z-index and position (absolute, relative, fixed, sticky), and it still doesn't work as expected, the problem might be with transform or opacity rules on one of the element's parents, that could make them behave as if they had zero z-index. A solution is to set z-index explicitly on the parent block with such rules (along with position).

Here's the specs for the reference:

https://www.w3.org/TR/css-transforms-1/#transform-rendering

3. The Transform Rendering Model

For elements whose layout is governed by the CSS box model, any value other than none for the transform property results in the creation of a stacking context. Implementations must paint the layer it creates, within its parent stacking context, at the same stacking order that would be used if it were a positioned element with z-index: 0. If an element with a transform is positioned, the z-index property applies as described in [CSS2], except that auto is treated as 0 since a new stacking context is always created.

https://www.w3.org/TR/css-color-3/#transparency

3.2. Transparency: the ‘opacity’ property

Since an element with opacity less than 1 is composited from a single offscreen image, content outside of it cannot be layered in z-order between pieces of content inside of it. For the same reason, implementations must create a new stacking context for any element with opacity less than 1. If an element with opacity less than 1 is not positioned, then it is painted on the same layer, within its parent stacking context, as positioned elements with stack level 0. If an element with opacity less than 1 is positioned, the 'z-index' property applies as described in [CSS21], except that if the used value is 'auto' then the element behaves exactly as if it were '0'. See section 9.9 and Appendix E of [CSS21] for more information on stacking contexts. The rules in this paragraph do not apply to SVG elements, since SVG has its own rendering model ([SVG11], Chapter 3).

Huberman answered 5/2, 2024 at 15:51 Comment(0)
H
0

I had a select element inside a "card"

My card had this class applied:

.card {
  border: 1px solid var(--gray-200);
  filter: drop-shadow(0 1px 1px rgb(0 0 0/0.05));
  box-shadow: rgba(0, 0, 0, 0.15) 0px 4px 5px;
  border-radius: 0.375rem;     
}

I removed the filter property and that fixed it.

Hashimoto answered 6/3, 2024 at 0:44 Comment(0)
T
-1

in my case the setting upper element to z-index: -1 helps.

Tate answered 15/4, 2023 at 6:41 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.