CSS 使用透视转换 Z 过渡会导致元素倾斜和扭曲
CSS Translate Z transition with perspective causes elements to skew and distort
我不确定我对 translateZ
和 perspective
的理解是否遗漏了什么,但我已经添加了一个 CodePen。
这是我的代码:
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:hover {
transform: perspective(1200px) rotateX(50deg) rotateY(20deg) rotateZ(-35deg) translateZ(40px);
}
.cards-container:hover .card {
transform: perspective(1200px) translateZ(80px);
}
.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>
我面临的问题是我无法持续重现的问题。如果您将鼠标悬停在我的示例中的卡片上,您会注意到过渡很流畅。预期的过渡是让 3 张卡片在悬停时从平面布局变为 3D 布局,其中每张卡片都在其父级之上。但有时当我将鼠标悬停在它们上方时,过渡变得不稳定,整个卡片本身变得 skewed/distorted,超出 z 轴的范围。要重现这一点,只需尝试在卡片上悬停几次,您会发现它是随机发生的。
在我看来,这似乎与观点有关,但考虑到我什至不确定如何始终如一地重现它,我在这里超出了我的深度。
对这个问题的任何理解表示赞赏。
诀窍在于您还对透视应用了过渡,因为它是造成这种不良效果的转换的一部分。即使在非悬停状态下也需要保持相同的视角:
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>
在这种情况下,最好考虑 perspective
属性 而不是 perspective()
转换函数
我不确定我对 translateZ
和 perspective
的理解是否遗漏了什么,但我已经添加了一个 CodePen。
这是我的代码:
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:hover {
transform: perspective(1200px) rotateX(50deg) rotateY(20deg) rotateZ(-35deg) translateZ(40px);
}
.cards-container:hover .card {
transform: perspective(1200px) translateZ(80px);
}
.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>
我面临的问题是我无法持续重现的问题。如果您将鼠标悬停在我的示例中的卡片上,您会注意到过渡很流畅。预期的过渡是让 3 张卡片在悬停时从平面布局变为 3D 布局,其中每张卡片都在其父级之上。但有时当我将鼠标悬停在它们上方时,过渡变得不稳定,整个卡片本身变得 skewed/distorted,超出 z 轴的范围。要重现这一点,只需尝试在卡片上悬停几次,您会发现它是随机发生的。
在我看来,这似乎与观点有关,但考虑到我什至不确定如何始终如一地重现它,我在这里超出了我的深度。
对这个问题的任何理解表示赞赏。
诀窍在于您还对透视应用了过渡,因为它是造成这种不良效果的转换的一部分。即使在非悬停状态下也需要保持相同的视角:
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>
在这种情况下,最好考虑 perspective
属性 而不是 perspective()
转换函数