css z-index lost after webkit transform translate3d
This might be related to: https://bugs.webkit.org/show_bug.cgi?id=61824
Basically when you apply a 3D transform on the z-axis, the z-index can't be accounted for anymore (you're now in a 3 dimensional rendering plane, use different z-values). If you want to switch back to 2D rendering for child elements, use transform-style: flat;
.
z-index is canceled by setting transform(rotate)
Let's walk through what is occurring. To start, note that z-index
on positioned elements and transform
by itself create new "stacking contexts" on elements. Here's what's going on:
Your .test
element has transform
set to something other than none, which gives it its own stacking context.
You then add a .test:after
pseudo-element, which is a child of .test
. This child has z-index: -1
, setting the stack level of .test:after
within the stacking context of .test
Setting z-index: -1
on .test:after
does not place it behind .test
because z-index
only has meaning within a given stacking context.
When you remove -webkit-transform
from .test
it removes its stacking context, causing .test
and .test:after
to share a stacking context (that of <html>
) and making .test:after
go behind .test
. Note that after removing .test
's -webkit-transform
rule you can, once again, give it its own stacking context by setting a new z-index
rule (any value) on .test
(again, because it is positioned)!
So how do we solve your problem?
To get z-index working the way you expect, make sure that .test
and .test:after
share the same stacking context. The problem is that you want .test
rotated with transform, but to do so means creating its own stacking context. Fortunately, placing .test
in a wrapping container and rotating that will still allow its children to share a stacking context while also rotating both.
Here's what you started with: http://jsfiddle.net/fH64Q/
And here's a way you can get around the stacking-contexts and keep
the rotation (note that the shadow gets a bit cut off because of.test
's white background):
.wrapper { -webkit-transform: rotate(10deg);}.test { width: 150px; height: 40px; margin: 30px; line-height: 40px; position: relative; background: white;}.test:after { width: 100px; height: 35px; content: ""; position: absolute; top: 0; right: 2px; -webkit-box-shadow: 0 5px 5px #999; /* Safari and Chrome */ -webkit-transform: rotate(3deg); /* Safari and Chrome */ transform: rotate(3deg); z-index: -1;}
<div class="wrapper"> <div class="test">z-index is canceled.</div></div>
z-index lost until end of transition
This behavior is logical, it's a bit difficult to explain but it's due to the direction of the rotation. If you look closely you will see that the right part turn by going to the top (considering the Z axis) but the the left part turn by going to the bottom that why it's hidden while rotating.
In order to correct this, you need to inverse the rotation of the left part to make it behave like the right one. Instead of 0deg
you need to use 360deg
.
var button = $('.button');var open = true;
button.click(() => { var right = $('.triangle.topright'); var left = $('.triangle.topleft');
if (open) { right.addClass('r-close'); left.addClass('l-close'); } else { right.removeClass('r-close'); left.removeClass('l-close'); }
open = !open;});
.container { box-sizing: border-box; display: flex; padding: 50px; position: relative; width: 100%;}
.fold.r-close { transform-origin: left; transform: rotate3d(0, 1, 0, 90deg);}
.fold { box-sizing: border-box; display: inline-block; height: 100px; width: 100px; position: relative; transition: all 1.5s; transform-style: preserve-3d;}
.fold.outer { width: 150px;}
.fold.left { margin-left: 50px;}
.triangle { height: 0; position: absolute; transition: all 1.5s; width: 0;}
/* middle */.triangle.middle { top: 0; z-index: -1 !important;}
.triangle.middle.left { border-bottom: 100px solid pink; border-left: 100px solid transparent; right: 0;}
.triangle.middle.right { border-bottom: 100px solid pink; border-right: 100px solid transparent; left: 0;}
/* right fold */.triangle.topright.front { border-bottom: 100px solid red; border-right: 100px solid transparent; backface-visibility: hidden; transform: rotate3d(1, 1, 0, 180deg);}
.triangle.topright.back { backface-visibility: hidden; border-left: 100px solid transparent; border-top: 100px solid pink; left: -0.6px;}
/* left fold */.triangle.topleft.front { border-bottom: 100px solid red; border-left: 100px solid transparent; backface-visibility: hidden; transform: rotate3d(-1, 1, 0, 180deg);}
.triangle.topleft.back { backface-visibility: hidden; border-top: 100px solid pink; border-right: 100px solid transparent; right: -0.6px;}
/* folds */.r-close.back { transform: rotate3d(1, 1, 0, 180deg);}
.triangle.r-close.front { transform: rotate3d(1, 1, 0, 0deg);}
.l-close.back { transform: rotate3d(-1, 1, 0, 180deg);}
.triangle.l-close.front { transform: rotate3d(-1, 1, 0, 360deg); /*Updated this*/}
.button { bottom: 0; position: absolute;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="container"> <div class="fold outer"> <div class="triangle middle left"></div> <div class="fold left"> <div class="triangle topleft front"></div> <div class="triangle topleft back"></div> </div> </div> <div class="fold outer"> <div class="triangle middle right"></div> <div class="fold right"> <div class="triangle topright front"></div> <div class="triangle topright back"></div> </div> </div> <button class="button">Click</button></div>
transform:scale() breaking my z-index order
This is a known issue:
- css z-index lost after webkit transform translate3d
- webkit-transform breaks z-index on Safari
- webkit-transform overwrites z-index ordering in Chrome 13
You can read more about it here as it offers in depth explanation.
In addition to opacity, several newer CSS properties also create stacking contexts. These include: transforms, filters, css-regions, paged media, and possibly others. As a general rule, it seems that if a CSS property requires rendering in an offscreen context, it must create a new stacking context.
You could avoid this issue by moving the transform properties from #blocks-both to #block-main and #block-sidebar like this:
#block-main, #block-sidebar {
transform: scale(0.9);
}
#block-main {
transform-origin: 100% 0;
}
#block-sidebar {
transform-origin: 0 0;
}
I've also edited your example.
webkit-transform overwrites z-index ordering in Chrome 13
Solved it myself through trial and error. Thought I'd report back if someone else stumbles upon this problem. It shall still be noted that this problem did not occur before Chrome updated itself to Chrome 13 (13.0.782.107m).
The trick here seems to be to add a translate3d
operation to the underlying <div>
(sq2
) element upon declaration (or atleast before animating sq1
).
Otherwise, the translate3d
operation on the overlying <div>
(sq1
) will cause rendering to ignore the z-index
and place sq1
below sq2
. I'm guessing that this is because sq1
is defined before sq2
in the DOM, therefore sq2
will be rendered above it.
So, the solution seems to be to put translate3d
in the definition of the <div>
:s (add it to both just to be clear):
HTML:
<div id="sq1" style="z-index:10; -webkit-transform: translate3d(0px, 0px, 0px);">
<div id="sq2" style="z-index:5; -webkit-transform: translate3d(0px, 0px, 0px);">
Layering using z-index with translate3d
This has nothing to do with transforms - just add a z-index of greater than your header to #wrapper
But I feel like I'm missing something from your question...
header{ position: fixed; top: 0; left: 0; right: 0; height: 40px; background: #000; color: #fff; z-index: 100;}
#wrapper{ position: relative; z-index:101;}
.wrapper-scroll{ transform: translate3d(0,0,0); position: relative; z-index: 101;}
.child-above{ position: absolute; top: 0; left: 0; display: block; width: 200px; height: 200px; background: #555; z-index: 9999; padding: 16px 10px; color: red;}
<header>HEADER</header><div id="wrapper"> <div class="wrapper-scroll"> <div class="child-above">CHILD TO BE ABOVE HEADER</div> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facilis recusandae, tenetur assumenda sequi quos voluptates voluptatum voluptas. Officia quisquam eveniet totam reprehenderit vel neque est dolorem assumenda in voluptatem. Ab accusantium provident, ut, obcaecati sapiente vitae officia. Distinctio assumenda ex deserunt iusto tempore optio, mollitia amet quas! Aut, magni, repellendus.</p> </div></div>
CSS3 transform: translate3d doesn't affect the z-axis?
Got it. Forgot to add -webkit-transform-style: preserve-3d;
CSS: Absolutely positioned pseudo element loses z-index?
I found this on w3.org, which I think explains it: http://www.w3.org/TR/css3-transforms/#effects
Any value other than ‘none’ for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.
As I understand it, your li:after
pseudo-element is inside the stacking context of the li.active
element, and therefore cannot appear behind it.
Related Topics
Stopping a Css3 Animation on Last Frame
Is There a CSS Hack to Affect Safari Only Not Chrome
Detect If an Input Has Text in It Using CSS - on a Page I Am Visiting and Do Not Control
Understanding Z-Index Stacking Order
Css3 Nth of Type Restricted to Class
How to Reference Jsf Image Resource as CSS Background Image Url
Remove Ie10'S "Clear Field" X Button on Certain Inputs
How to Change the Cursor into a Hand When a User Hovers Over a List Item
Customizing Bootstrap CSS Template
Why Isn't It Possible to Combine Vendor-Specific Pseudo-Elements/Classes into One Rule Set
What's the Difference Between Align-Content and Align-Items
Z-Index Is Canceled by Setting Transform(Rotate)
Remove Blue Border from CSS Custom-Styled Button in Chrome
Why Can't an Element With a Z-Index Value Cover Its Child
Use Css3 Transitions With Gradient Backgrounds
Make Nested Div Stretch to 100% of Remaining Container Div Height