Both Chrome and Firefox work as intended
Starting with version 22 , Chrome specifically intends to handle fixed elements. As stated in the google article itself:
In Chrome 22, the layout position:fixed layout behavior is slightly different from previous versions. All position:fixed elements now form new stacking contexts. This will change the stacking order of some pages, which may disrupt page layouts.
( https://developers.google.com/web/updates/2012/09/Stacking-Changes-Coming-to-position-fixed-elements?hl=en )
Firefox works as it intends. Mozilla docs point out that this behavior is localized to WebKit Mobile and Chrome 22 onwards:
on mobile WebKit and in Chrome 22+, position: fixed always creates a new stacking context, even when the z-index is โautoโ
( https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context )
Why is this happening
The result of this change means that Chrome will always create a new stacking context, even if the z-index parent container set to auto (default). This is different from position: absolute; and position: relative; in that they create their own stacking context when the z-index not set to auto .
Most of the elements on the page are in the same root context of the stack, but absolutely or relatively positioned elements with non-automatic z-index values โโform their own stacking contexts (that is, all their children will be z-ordered within the parent element and will not alternate with content from outside the parent) . Starting with 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 z-index calculated relative to its parent, .parent . It displays under .bodycontent because:
.bodycontent z-index refers to the root.el z-index refers to .parent.parent z-index refers to the root.parent z-index not specified, so it is set to auto by default (essentially 0 ).parent has a lower z-index than .bodycontent and therefore appears below it. Since .el belongs to him, it is also displayed under .bodycontent .
Expected Results Example
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>
In the above code, the following results will appear in Chrome and Firefox:

What is right?
It seems that Chrome does not follow the W3C specification and that this change was made to make the implementation on the desktop consistent with the implementation of mobile devices:
Mobile browsers (Mobile Safari, Android browser, Qt-based browsers) place positions: fixed elements in their own stack contexts and have some time (starting from iOS5, Android Gingerbread, etc.), because this allows certain optimizations Scrolling, making web pages much more sensitive to touch. Changes are brought to the desktop for three reasons:
1 - Different rendering behavior on mobile and desktop browsers is a stumbling block for web authors; CSS should work wherever possible.
2 - With tablets, it is not clear which of the "mobile" or "desktop" stack context algorithms is more appropriate.
3 - Optimization of scroll performance from mobile to desktop is good for both users and authors.
Firefox handles stacking correctly.
How to get the desired result
The only way to avoid this behavior is to move the .el from .parent and instead make it a brother:
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> <div class="el"></div> <div class="bodycontent"></div>