transform复合变换的坐标系变换详解
欢迎来到我的博客!
这是我的第 4 篇文章,使用 Markdown 格式编写。
今天学到了什么
- 今天来做一篇大文章,分享一个transform的知识点(搞了一晚上和两早上,终于搞明白了)
是在完成这个案例的时候,遇到的问题

这个案例需要将一个面设置为底面,这两个面需要设置position: absolute;
为什么这两个面需要设置position: absolute;?
因为很明显,这是一个动效案例,并且需要两个盒子,
其次,transform只是在视觉上调整元素的位置,但是它的本体(变换前的位置)还是要占空间的,这时候如果不脱离普通的文档流,就很难实现,尤其是需要多个盒子实现的效果,这个盒子的位置会影响另一个盒子的位置,很难调整,所以我们需要脱离普通的文档流,让两个盒子的位置互不影响,才能更好地实现案例
总结:什么时候用 position: absolute;?
- 需要脱离文档流 :不希望元素影响其他元素的布局。
- 需要相对于父元素定位 :比如居中、叠加、或者精确定位。
- 需要完全重叠 :比如实现遮罩、背景层、或者 3D 效果。
- 需要固定在某个位置 :比如右下角按钮、弹窗等。
- 需要动画或 3D 效果 :让元素在父元素内自由移动或变换。
接下来,我们就要分别设置两个面的位置,正面容易设置,关键是底面,当做底面的那个盒子,需要先旋转,然后再向下平移到合适的位置。
首先要理解以下知识点
translate() 的本质:始终是“相对初始位置的偏移量”
- translate(300px, 600px) 的意思是: 让元素从它的初始位置,整体偏移 300px(右)、600px(下) 。
- 它不是“累计”移动,也不是“每一步都在上一步的基础上再移动”,而是 直接跳到这个偏移量的位置 。
在做的过程中,有很多注意点容易让人产生疑惑
- 首先,先说明一个点,在CSS当中,利用坐标轴定位并不像数学中的那样,
- 在数学中的坐标轴,是用一个个准确的坐标点来定位的,所以坐标原点这个概念是很重要的,只有设置好坐标原点的位置,才能更好地确定图形的位置。
- 而在CSS当中,“坐标原点”其实并不重要 ,因为各种元素平移到合适位置,利用的是 元素目标位置相对元素初始位置,在当前坐标轴方向上移动指定的距离,简单来讲,相对于元素初始位置的偏移量 。才是CSS当中 元素定位的核心,
- 差别就很明显了,数学中的定位是目标点相对坐标原点的距离,而CSS当中的定位是元素目标位置相对元素初始位置的距离,区别就是是否强化了坐标原点在元素定位当中的重要性(或者是目标定位的参照位置不一样)
- 理解这些,才能理解CSS确定元素位置的方式
上述主要讨论了平移的核心逻辑,接下来讨论平移和旋转的区别
绕轴旋转和平移利用坐标轴的方式,本质上是一样的,坐标轴的方向才是关键,其他的,比如坐标原点之类的,并不重要

我一开始以为CSS中元素默认的坐标轴位置是这样的,那绕X轴旋转,不应该是向上转吗?实际上绕轴旋转的默认位置,这样设计是为了灵活性,不是bug——如果旋转轴默认在顶部,很多动画会不直观。
这再次说明了一个点,即坐标轴的位置并不重要,更重要的是坐标轴的方向
transform的复合变换规则

你看见了吗,中间那个蓝色的平面就是加了rotate的底部盒子,我现在就是要让它下移到白色平面的底部。
但是要注意一个点,旋转后,元素本地坐标系也旋转了,z轴是向下的,这时候我想让盒子从视觉上向下移动,不是应该写 translateZ 吗?
但是实际上并不是,这里就是关键点了
<style> ul li .bottom { background: #3b5999; color: #fff; transform: rotateX(-90deg) translateY(20px); /* 改变默认旋转轴 transform-origin: bottom; */ transform-origin: center; /* 改为以自身底部为旋转中心 */ transform-origin: bottom; }</style>transform-origin: bottom;这句话是改为以li的底部(也就是父元素的底部)为bottom的旋转中心,不是改为以它本身的底部为旋转中心
反正目前我的理解是,父元素设置了preserve-3d后 子元素的变换,是根据父元素的坐标系来进行变换的,而不是根据自己本地的这个坐标轴变化的。
之后有问题再说吧。
以上就是我总结的核心知识点,下面的就是代码展示了
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="http://at.alicdn.com/t/c/font_4096975_pswyqyk8tdo.css"> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
body { background-color: #ccc; }
ul { display: flex; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); gap: 5px; /* border: 1px solid #262626; background-color: #262626; */ perspective: 800px; }
ul li { width: 80px; height: 40px; position: relative; /* 初始化 去掉前面的点*/ list-style: none; /* 这里我虽然写在了li里面,但是由于span可以继承li的样式,所以图标仍然会居中显示 */ /* text-align: center; line-height: 40px; */ font-size: 20px; transition: all 0.5s ease-in-out; transform-style: preserve-3d; }
ul li span { position: absolute; top: 0; left: 0; width: 100%; height: 100%; /* position: absolute; */ /* 加了定位后自动变成块级元素了 */ display: block; text-align: center; line-height: 40px; }
ul li .front { background: #fff; color: #3b5999; transform: translateZ(20px);
}
ul li .bottom { background: #3b5999; color: #fff; transform: translateY(20px) rotateX(-90deg); }
ul li:hover { transform: rotateX(90deg); } </style></head>
<body> <ul> <li> <span class="front iconfont icon-QQ"></span> <span class="bottom iconfont icon-QQ"></span> </li> <li> <span class="front iconfont icon-weixin"></span> <span class="bottom iconfont icon-weixin"></span> </li> <li> <span class="front iconfont icon-douyin"></span> <span class="bottom iconfont icon-douyin"></span> </li> <li> <span class="front iconfont icon-xinlangweibo"></span> <span class="bottom iconfont icon-xinlangweibo"></span> </li> <li> <span class="front iconfont icon-shouji"></span> <span class="bottom iconfont icon-shouji"></span> </li> </ul></body>
</html>赞助支持
如果这篇文章对你有帮助,欢迎赞助支持!
部分内容可能已过时