Can CSS3 Translatez() Be Used Instead of Z-Index

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



Leave a reply



Submit