Css 3D Transform Doesn't Work If Perspective Is Set in the End of Property

CSS 3d transform doesn't work if perspective is set in the end of property

You should make the perspective first in both cases. If you add it at the end the translation will be first made without considering the perspective.

If we refer to the specification we can see how the transformation matrix is computed:

The transformation matrix is computed from the transform and
transform-origin properties as follows:

  1. Start with the identity matrix.

  2. Translate by the computed X and Y of transform-origin

  3. Multiply by each of the transform functions in transform property from
    left to right

  4. Translate by the negated computed X and Y values of transform-origin

As you can see in the step (3), it's from left to right (here is another question where you can get more information and see why order is important: Simulating transform-origin using translate)

It also useless to use the perspective property within the element you want to transform.

box:nth-child(1):hover {  transform: perspective(1000px) translate3d(0, 0, -100px);}
box:nth-child(2):hover { transform: perspective(1000px) translate3d(0, 0, 100px);}
box { padding: 20px; display: inline-flex; align-items: center; justify-content: center; font-family: monospace; transition: transform .4s; background: rgba(255, 0, 0, 0.3); margin: 20px; /*perspective: 1000px;*/ font-size: 12px; cursor: pointer;}
box:nth-child(2) { background: rgba(0, 0, 255, 0.3);}
<box>  transform: perspective(1000px) translate3d(0,0,100px);</box><box>  transform:  perspective(1000px) translate3d(0,0,100px);</box>

Why perspective isn't giving the same result when some styles are updated?

Each have almost the same values, one perspective looks fine,

No they don't have the same values. One is using position:absolute and the the other one position:relative and this make a big difference. If you inspect the god element you will notice that its height is 0 when using the position:absolute (the first case) which is creating the issue.

Here is a simplified code to better show your issue:

.box {
display: inline-block;
vertical-align:top;
width: 100px;
perspective: 200px;
position: relative;
margin: 20px;
background:blue;
}

.box>div {
position: relative;
padding: 10px;
background: red;
color: #fff;
transition: 1s all linear;
transform-origin: top left;
}

body:hover .box > div {
transform: rotateY(-40deg);
}
<div class="box">
<div>Some text here</div>
</div>
<div class="box">
<div style="position:absolute;">Some text here</div>
</div>

Why changing the position changes the effect of 3D transform?

although both of them has the same perspective view why changing their position changed the effect of 3D transform ?

They have the same perspective, yes but the trick is in the perspective-origin which is set to be the center of the parent element (not the elements). Your Red element is already in center so it will only comes close to your while the yellow element isn't in the center so its movement will be different.

To better illustrate here is another example using a rotate transformation.

.container {
border:2px solid red;
perspective:300px;
perspective-origin:50% 50%;
padding:20px;
display:flex;
justify-content:space-around;
}

.container > div {
width:50px;
height:50px;
background:blue;
transform:rotateY(20deg);
}
<div class="container">
<div></div>
<div></div>
<div></div>
</div>

<div class="container" style="perspective-origin:10% 50%">
<div></div>
<div></div>
<div></div>
</div>

<div class="container" style="perspective-origin:70% 50%">
<div></div>
<div></div>
<div></div>
</div>

Why CSS translateZ is ignored if parent element has a transform of its own?

From the specification:

By default, transformed elements do not create a 3D rendering context and create a flattened representation of their content. However, since it is useful to construct hierarchies of transformed objects that share a common 3-dimensional space, this flattening behavior may be overridden by specifying a value of preserve-3d for the transform-style property. This allows descendants of the transformed element to share the same 3D rendering context.

So simply add transform-style:preserve-3d to the subcontainer element and the perspective of the grand-parent will be respected:

.container{
background: #f4f7be;
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
perspective: 1000px;
}

.subcontainer{
background: #baf7f6;
width: 70%;
height: 70%;
display: flex;
justify-content: center;
align-items: center;
transform: scale(1.001);
transform-style:preserve-3d;
}

.shape{
background: #555;
width: 40%;
height: 50%;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
transform: translateZ(300px);
}
<html>
<div class="container">
<div class="subcontainer">
<div class="shape"></div>
</div>
</div>
</html>

css 3d perspective not showing up correctly in certain browsers

Chrome will only render 3D css in true perspective 3D if GPU acceleration is enabled. If it isn't, it will instead use a kind of quasi-3d isometric projection.

To see if your chrome has GPU acceleration enabled, type about:GPU into the address bar and see what it says.

translate3d() & rotateY() working, but perspective-origin not working... why?

The order in the transform functions is important

They are applied from right to left, so this

transform:  translate3d(0px,0px,0px) rotateY(45deg) perspective(100px);

applies the perspective when the element isn't rotated, so it doesn't show.

It should be

transform:  perspective(100px) translate3d(0px,-50px,0px) rotateY(45deg);

first rotate, then translate and then apply the perspective

fiddle

This applies the perspective (or, better say, the perspective applied is noticeable). But since it applies it to the translated element, it is not centered.

If you want it centered, apply the perspective before the translatiion. Notice that the transform is evaluated right to left, so before means afterwards in the list

transform: translate3d(0px,-50px,0px) perspective(600px) rotateY(80deg);

Notice that perspective-origin is useless when applying perspective as a function instead of a property.

fiddle

CSS Translate Z transition with perspective causes elements to skew and distort

The trick is that you are also applying a transition to perspecitve since it's a part of the transformation creating this bad effect. Perspective need to remain the same even on the non hover state:

body {
margin: 0;
height: 100vh;
}

.cards-container {
padding: 100px;
margin: auto;
margin-top: 100px;
transform-style: preserve-3d;
}

.cards-container,
.cards-container * {
height: 400px;
width: 400px;
box-sizing: border-box;
background-color: lightgray;
transition: all ease 1.6s;
/* perspective: 1200px; */
}

.card {
width: 200px;
height: 200px;
padding: 50px;
background-color: lime;
transform-style: preserve-3d;
}

.card-child {
width: 100px;
height: 100px;
background-color: rgb(255, 230, 0);
}

.cards-container {
transform: perspective(1200px) rotateX(0deg) rotateY(0deg) rotateZ(0deg) translateZ(0px);
}

.cards-container:hover {
transform: perspective(1200px) rotateX(50deg) rotateY(20deg) rotateZ(-35deg) translateZ(40px);
}

.cards-container .card {
transform: perspective(1200px) translateZ(0px);
}

.cards-container:hover .card {
transform: perspective(1200px) translateZ(80px);
}

.cards-container .card .card-child {
transform: perspective(1200px) translateZ(0px);
}

.cards-container:hover .card .card-child {
transform: perspective(1200px) translateZ(60px);
}
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo</title>
<link rel="stylesheet" href="css/main.css">
</head>

<body>
<script src="index.js"></script>
<div class="cards-container">
<div class="card">
<div class="card-child"></div>
</div>
</div>
</body>

</html>

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;.



Related Topics



Leave a reply



Submit