Can css3 translateZ() be used instead of z-index?
The answer now, 3 years after, is that you can.
You need to use transform-style: preserve-3d;
on the parent, but it's possible.
.container { transform-style: preserve-3d;}.test1 { width: 500px; height: 500px; background: red; transform: translate3d(0, 0, 1px);}.test2 { width: 500px; height: 500px; background: green; left: 250px; top: 250px; position: absolute; transform: translate3d(0, 0, 0);}
<div class="container"> <div class="test1"> test </div>
<div class="test2"> test #2 </div></div>
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);">
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>
CSS 3D Carousel Elements Don't Respect TranslateZ
perspective-3d
isn't a valid value for transform-style
; it should be preserve-3d
, and this should go on the container, in your case .carousel
Number.prototype.mod = function(n) { return ((this%n)+n)%n;};
setInterval(function() { var left = $('.one'), center = $('.two'), right = $('.three'); $(left).removeClass('one').addClass('two'); $(center).removeClass('two').addClass('three'); $(right).removeClass('three').addClass('one');}, 2000);
.carousel { display: block; position: relative; width: 100%; height: 200px; perspective: 800px; transform-style: preserve-3d; /* <---- need this on container for 3d */}
.item { height: 200px; width: 50%; display: block; position: absolute; /* transform-style: perspective-3d; <---- not valid value */ transition: all 500ms linear; backface-visibility: hidden;}
.item:nth-child(1) { background: red;
}.item:nth-child(2) { background: green;
}.item:nth-child(3) { background: blue;
}
.item.one { transform: translateX(0%) translateZ(-100px); }.item.two { transform: translateX(50%) translateZ(0px); }.item.three { transform: translateX(100%) translateZ(-100px); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="carousel"> <div class="item one">hello</div> <div class="item two">hello</div> <div class="item three">hello</div></div>
CSS performance relative to translateZ(0)
CSS transformations create a new stacking context and containing block, as described in the spec. In plain English, this means that fixed position elements with a transformation applied to them will act more like absolutely positioned elements, and z-index
values are likely to get screwed with.
If you take a look at this demo, you'll see what I mean. The second div has a transformation applied to it, meaning that it creates a new stacking context, and the pseudo elements are stacked on top rather than below.
So basically, don't do that. Apply a 3D transformation only when you need the optimization. -webkit-font-smoothing: antialiased;
is another way to tap into 3D acceleration without creating these problems, but it only works in Safari.
Why is translateZ not being applied to the direct parent or its parent?
You need to remove the filter
you are applying, it's the culprit. The one applied to navBar
elements = {};
document.getElementsByTagName("style")[0].innerHTML += `
.navButton {
color: white;
transition: filter 1.5, background-color 0.3s;
background-color: inherit;
border: 0px;
outline: none;
font-family: Cinzel;
filter: brightness(0%);
transform-style: preserve-3d;
}
.navButton:hover {
font-size: 35px;
background-color: rgb(110, 205, 255);
}
#child {
position: absolute;
top: 0px;
height: 50px;
transition: top 0.3s, height 0.3s;
transform-style: preserve-3d;
transform: translateZ(-2px);
}`;
//Navigation bar
elements.navBar = document.createElement("div");
elements.navBar.style.cssText = "position: absolute; left: 50%; transform: translate(-50%, 0%); display: flex; top: 15px; width: 800px; height: 60px; background-color: rgb(92, 199, 238); box-shadow: 0px 5px 5px -1px gray; font-family: Cinzel; font-size: 30px; color: white; transform-style: preserve-3d;";
document.body.append(elements.navBar);
// Parent in nav
elements.parent = document.createElement("button");
elements.parent.type = "button";
elements.parent.innerHTML = "Parent";
elements.parent.classList.add("navButton");
elements.parent.style.fontSize = "30px";
elements.parent.style.borderRight = "3px solid rgb(85, 190, 220)";
elements.parent.style.maxWidth = "250px";
elements.parent.style.minWidth = "150px";
elements.navBar.append(elements.parent);
// Uncle One in nav
elements.uncleOne = document.createElement("button");
elements.uncleOne.type = "button";
elements.uncleOne.innerHTML = "Uncle 1";
elements.uncleOne.classList.add("navButton");
elements.uncleOne.style.cssText = "font-size: 30px; border-right: 3px solid rgb(85, 190, 220);";
elements.navBar.append(elements.uncleOne);
elements.uncleOne.style.width = elements.uncleOne.offsetWidth * 1.3;
// Uncle Two in nav
elements.uncleTwo = document.createElement("button");
elements.uncleTwo.type = "button";
elements.uncleTwo.innerHTML = "Uncle Two";
elements.uncleTwo.classList.add("navButton");
elements.uncleTwo.style.fontSize = "30px";
elements.uncleTwo.style.borderRight = "3px solid rgb(85, 190, 220)";
elements.navBar.append(elements.uncleTwo);
elements.uncleTwo.style.width = elements.uncleTwo.offsetWidth * 1.3;
function lighten() {
elements.parent.style.filter = "brightness(100%)";
elements.uncleOne.style.filter = "brightness(100%)";
elements.uncleTwo.style.filter = "brightness(100%)";
elements.child = document.createElement("div");
elements.child.id = "child";
elements.child.innerHTML = "Child";
setTimeout(() => {
elements.child.style.cssText = "left: -3px; width: 200px; border: 3px solid rgb(85, 190, 220); background-color: rgb(92, 199, 238);";
elements.parent.append(elements.child);
elements.uncleOne.onmouseenter = () => {
setTimeout(() => {
elements.child.style.top = "60px";
elements.child.style.height = "80px";
}, 1);
}
elements.uncleOne.onmouseleave = () => {
elements.child.style.top = "0px";
elements.child.style.height = "50px";
}
}, 1600);
}
lighten();
Why is z-index affected by transform?
This is because the specification describes that a transform different than the value none should create a new stacking context.
On MDN:
If the property has a value different than none, a stacking context
will be created. In that case the object will act as a containing
block for position: fixed elements that it contains.
Related Topics
Iframe Horizontal Scrolling Not Rendering on iOS
Align Block Elements on Top When Using Line-Height
How to Set Responsive Image's Max Width (Bootstrap 4)
Export HTML Table to Excel and Keep CSS Styles
How to Animate an Element to Swing in CSS3
Line Height Default Value If Font Size Is 100%
Placeholder Attribute on Input Tags for Ie
Change Background from Bottom to Top on Hover
A:Visited Doesn't Work in Mozilla Firefox
Target First Element of Div Using CSS
How to Center the Center Circle
CSS Linear Gradient Transparency Misbehaving Only in Safari
Change Only One of Multiple Backgrounds on Hover
Why Is the # Selector of Lesser Specificity Than Anything
How to Load One Style Sheet for Mobile Devices and One for Desktops
How to Vertically Align Objects in CSS When Working with CSS Grids