Google Chrome Not Respecting Z-Index

Google Chrome not respecting z-index

Usually when you have set the z-index property, but things aren't working as you might expect, it is related to the position attribute.

In order for z-index to work properly, the element needs to be "positioned". This means that it must have the position attribute set to one of absolute, relative, or fixed.

Note that your element will also be positioned relative to the first ancestor that is positioned if you use position: absolute and top, left, right, bottom, etc.

z-index chrome bug

one800higgins's answer is along the right lines. The real answer is that on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is auto. So the stacking context hierarchy looks like this:

  • document root (z-index 0)
    • #mask (z-index 9998)
    • #box (z-index 0)
      • .above-mask (z-index 9999)
      • .below-mask (z-index 9997)

That means that 9998 is never compared with 9999 or 9997 to determine stacking order. Instead, 9999 is compared with 9997 to determine which of .above-mask and .below-mask is further in front, and then once everything inside #box is stacked in that context, it's treated as a single layer at z-index 0 which gets stacked behind #mask at z-index 9998.

This also explains why @TheNextBillGates's answer of moving #mask inside #box works - because then #mask is in the same stacking context as .above-mask and .below-mask. I highly recommend the above link for more comprehensive details, and you should also see the announcement for the stacking change for fixed elements in Chrome.

Google chrome not obeying z-index when inside a fixed element.

The problem is that Chrome creates a new stacking context for elements that don't have a z-index set (default is auto). So your sidebar has a z-index of 0 which makes it (and all of its childrens) disappear since you've specified a higher z-index for your #top container.

To solve the problem, give the sidebar a z-index higher than the one from #top:

#sidebar{
width:inherit;
position: fixed;
display: block;
z-index: 501;
}

DEMO

Chrome on Android not respecting z-index for link clicks

Chrome, in this case is kind of triggering the mouseOUT before the click!

Here is another fiddle that shows HOVER events on DIVs as well as click events on LINKS:

http://fiddle.jshell.net/gnv9n/18/ <-- this should work on all browser. Only webkit transition is used because your issue happens on Chrome only.

If you add a css3 transition, the click is triggered correctly! This is kind of an ugly fix but it works.

Try to remove the css transition and look at the events if you want to see Chrome failling to click before "hovering"

Thanks Kinlan for submitting the issue to Chrome's team!

z-index behaviour is different in chrome to firefox

Both Chrome and Firefox are working as intended

From version 22 onwards, this is the way Chrome intentionally handles the stacking of fixed elements. As stated in an article by Google themselves:

In Chrome 22 the layout behavior of position:fixed elements is slightly different than previous versions. All position:fixed elements now form new stacking contexts. This will change the stacking order of some pages, which has the potential to break page layouts.

(https://developers.google.com/web/updates/2012/09/Stacking-Changes-Coming-to-position-fixed-elements?hl=en)

Firefox is working as it intends too. The Mozilla docs state that this behaviour is localised to mobile WebKit and Chrome 22 onwards:

on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is "auto"

(https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context)

Why this happens

The result of this change means that Chrome will always create a new stacking context even if the z-index of the parent container is set to auto (the default). This differs from position: absolute; and position: relative; as they only form their own stacking context when z-index is not set to auto.

Most elements on a page are in a single, root stacking context, but absolutely or relatively positioned elements with non-auto z-index values form their own stacking contexts (that is, all of their children will be z-ordered within the parent and not be interleaved with content from outside the parent). As of Chrome 22, position:fixed elements will also create their own stacking contexts.

(https://developers.google.com/web/updates/2012/09/Stacking-Changes-Coming-to-position-fixed-elements?hl=en)

The effect of this means that in your example .el's z-index is computed relatively to its parent, .parent. It is displayed under .bodycontent because:

  • .bodycontent's z-index is relative to the root
  • .el's z-index is relative to .parent
  • .parent's z-index is relative to the root
  • .parent's z-index is not specified so it is set to the default auto (in effect, 0)
  • .parent has a lower z-index than .bodycontent and is therefore displayed under it. Because .el belongs to it, it too is displayed under .bodycontent.

Example of expected results

body {
margin: 0;
}
div {
height: 100px;
width: 100px;
}
.parent {
background-color: red;
position: fixed;
top: 0;
}
.el {
background-color: blue;
left: 25px;
position: fixed;
top: 25px;
z-index: 100;
}
.bodycontent {
background-color: green;
left: 50px;
position: relative;
top: 50px;
z-index: 1;
}
<div class="parent">
<div class="el"></div>
</div>
<div class="bodycontent"></div>


Related Topics



Leave a reply



Submit