CSS变形动画
前言
在开始介绍CSS变形动画之前,可以先了解一下学习了它之后能做什么,有什么用,这样你看这篇文章可能会有一些动力。
学习了CSS变形动画后,你可以为你的页面做出很多炫酷的效果,如一个3D的魔方,一个很酷的旋转菜单等等。
在本章节中将会采用大量的实例进行演示,相信你如果看完这篇文章后写出的页面会更加的吸引眼球。
基础知识
坐标系统
首先我们要学习的变形动画,想达到在上图中出现的3D效果单纯的X与Y两个轴是实现不了的,还需要加入一条纵深轴,即Y轴的参与才有一个3D的视觉感受。
那么如何来理解X,Y,Z这三条轴的关系呢?可以看一下下面这张图。
X轴代表水平轴
Y轴代表垂直轴
Z轴代表纵深轴
X和Y轴都非常好理解,怎么理解这个Z轴呢?
CSS的中文名称叫做层叠样式表,那么它肯定是一层一层的。之前学习过z-index
就是用来设置层的优先级,优先级越高越在上面,也可以理解为离我们肉眼越近,它把优先级低的层给盖住了,所以Z轴可以理解为我们观察的视角与被观察物体之间的一条轴。
Z轴数值越大,说明观测距离越远。
Z轴的数值可以无限大,所以设置的时候一定要小心。
变形操作
可以使用transform
规则控制元素的变形操作,包括元素移动、旋转、倾斜、3D转换等等。
下表中是CSS提供的变形动作,在接下来的学习中将会对一个变形动作进行详解。
选项 | 说明 |
---|---|
none | 定义不进行转换。 |
translate(x,y) | 定义 2D 转换。 |
translate3d(x,y,z) | 定义 3D 转换。 |
translateX(x) | 定义转换,只是用 X 轴的值。 |
translateY(y) | 定义转换,只是用 Y 轴的值。 |
translateZ(z) | 定义 3D 转换,只是用 Z 轴的值。 |
scale(x,y) | 定义 2D 缩放转换。 |
scale3d(x,y,z) | 定义 3D 缩放转换。 |
scaleX(x) | 通过设置 X 轴的值来定义缩放转换。 |
scaleY(y) | 通过设置 Y 轴的值来定义缩放转换。 |
scaleZ(z) | 通过设置 Z 轴的值来定义 3D 缩放转换。 |
rotate(angle) | 定义 2D 旋转,在参数中规定角度。 |
rotate3d(x,y,z,angle) | 定义 3D 旋转。 |
rotateX(angle) | 定义沿着 X 轴的 3D 旋转。 |
rotateY(angle) | 定义沿着 Y 轴的 3D 旋转。 |
rotateZ(angle) | 定义沿着 Z 轴的 3D 旋转。 |
skew(x-angle,y-angle) | 定义沿着 X 和 Y 轴的 2D 倾斜转换。 |
skewX(angle) | 定义沿着 X 轴的 2D 倾斜转换。 |
skewY(angle) | 定义沿着 Y 轴的 2D 倾斜转换。 |
perspective(n) | 为 3D 转换元素定义透视视图。 |
变形叠加
这其实是一个坑点,在使用变形中一定要注意,重复对元素设置变形操作时只在元素的原形态上操作。
我们可以先看一下下面的案例,不懂代码没关系,懂这个意思就行了。
默认处理
下面设置了两次移动,并不会移动550px
而是只移动50px
。
我们在元素中先设置了右移500px
,鼠标放上去时再往右移动50px
,可是下面却出现了向左移动的场景,这是因为对div
进行了位置居中处理,它必须要按照之前居中的位置进行50px
的移动。而不是按照居中后设置的500px
的地方再进行向右移动50px
。
上面这句话有点绕,总之。上面设置了,位置改变了,下面再设置,不会按照已改变的位置进行变化,而是按照原位置。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; box-sizing: border-box; list-style: none; } body { height: 100vh; width: 100vw; background-color: aliceblue; display: flex; justify-content: center; align-items: center; } div{ width: 200px; height: 200px; background-color: blueviolet; /* 意思就是说按x轴移动500px */ transform: translateX(500px); /* 过渡时间2s */ transition: 2s; } div:hover{ /* 意思就是说按x轴移动50px */ transform: translateX(50px); } </style> </head> <body> <div></div> </body> </html>
伪类叠加
还是设置两次移动,如果移动的方向都一样,且伪类设置的移动比原本的移动多一点,就在原本的基础上直接进行变形,而不用再找开始位置了。
我们还是拿上面的案例,只不过伪类移动的数值将50px
改为600px
,比第一次设置大100px
,那么此时他就不会再往左走,而是直接在原有基础上进行叠加,向右移动100px
。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; box-sizing: border-box; list-style: none; } body { height: 100vh; width: 100vw; background-color: aliceblue; display: flex; justify-content: center; align-items: center; } div{ width: 200px; height: 200px; background-color: blueviolet; /* 意思就是说按x轴移动500px */ transform: translateX(500px); /* 过渡时间2s */ transition: 2s; } div:hover{ /* 意思就是说按x轴移动600px */ transform: translateX(600px); } </style> </head> <body> <div></div> </body> </html>
内联元素
内联元素即行级元素,inline
元素是不能参与变形的,将其转为 inline-block
或 block
以及弹性元素时才可以产生变化效果。
:hover伪类
鼠标移动到某一元素上发生的用户行为。
当该行为出现时,我们可以为它指定一些参数的改变。
如下,改变颜色。
:target伪类
意思就是说你点击一个<a>
,该<a>
标签中的href
指向的锚点标签会发生变化。
点击第一个<a>
元素,与之相对的锚点元素发生变化。
点击第二个<a>
元素,与第一个<a>
元素相对的锚点变化停止,与第二个<a>
元素相对的锚点发生变化。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; flex-flow: column; justify-content: center; align-items: center; } div{ width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 2em; } div:nth-child(1) { background:red; } div:nth-child(2) { background:blue; } #div-1:target{ background-color: green; } #div-2:target{ background-color: black; } </style> </head> <body> <div id="div-1">原本颜色:红</div> <div id="div-2">原本颜色:蓝</div> <a href="#div-1">让div-1变绿</a> <a href="#div-2">让div-2变黑</a> </body> </html>
最后注意一点
事件元素上放过渡时间,:hover
上放具体的事件,如移动,旋转,倾斜等操作。
如果你设置了移动却将过渡时间放在了:hover
里面,那么就会出现下面这种情况。
可以看见,直勾勾的就回来了,这种效果显然不是我们想要的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ /* transition: 1s; */ } div:last-child:hover { transform: translateX(100px); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
移动元素
-
沿X轴移动时正值向右移动、负值向左移动
-
沿Y轴移动时正值向下移动、负值向上移动
-
如果使用百分数将控制元素的原尺寸计算百分比然后移动
-
可同时设置多个值,解析器会从左向右依次执行
-
变形是在原基础上更改,即第二次设置值时不是在第一次值上变化
translateX
控制元素在X轴上的移动,正值向右、负值向左。
如,我们下面设置translateX(100px)
,过渡时间为1s
。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: translateX(100px); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
translateY
控制元素在X轴上的移动,正值向下、负值向上。
如,我们下面设置translateY(100px)
,过渡时间为1s
。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 400px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: translateY(100px); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
translate
translate
是translateX
以及translateY
的简写模式,第一个值控制X移动,第二个值控制Y移动。
一句话,设置X与Y轴的移动,注意,这个方法中不包含Z轴,因为一旦有Z轴参与就会变为3D效果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 400px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { /* 先设置X轴,再设置Y轴 */ transform: translate(100px,100px); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
百分比移动
当要移动的元素宽高为100px
时,如果使用50%
进行移动,则代表移动50px
。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 400px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { /* 先设置X轴,再设置Y轴 */ transform: translate(50%,50%); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
元素居中
我们之前介绍过很多元素居中的方法,如定位操作,弹性盒模型,其实使用移动也可以达到元素居中的效果。
给你丢一套模板。
/* 让子元素脱离文档流并参照副父级元素偏移。这是定位+margin的居中方法 */
position: absolute;
left: 50%;
top: 50%;
/* left和top设置子元素宽高的负的50%就行 */
margin-left: -3px;
margin-top: -3px;
/* 这是弹性盒模型控制元素居中的方法 */
display: flex;
justify-content: center;
align-items: center;
/* 让子元素脱离文档流并参照副父级元素偏移。这是定位+移动的居中方法 */
position: absolute;
left: 50%;
top: 50%;
/* X和Y设置子元素宽高的负的50%就行 */
transform: translate(-50%, -50%);
translateZ
控制Z轴移动,正数向外(距离我们近)、负数向里移动(距离我们远)。因为Z轴是透视轴没有像X/Y一样的固定尺寸,所以不能使用百分数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; border: 1px solid #ccc; /* 如果将Z轴移动的:hover放在div上,我们不方便一直将鼠标放在div上面,故我们设置成放在main上面让div进行Z轴移动 */ /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照Y轴旋转60度,按Z轴放大5倍*/ transform: perspective(900px) rotateY(60deg) scaleZ(5); /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; } main:hover div:nth-child(2) { transform: translateZ(-100px); } div { height: 100px; width: 100px; background-color: blueviolet; /* 让子元素脱离文档流并参照副父级元素偏移。这是定位+移动的居中方法 */ position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } div:nth-child(1) { background-color: yellow; } div:nth-child(2) { background-color: blueviolet; /* 过渡时间1s */ transition: 1s; } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
translate3d
用于同时控制X/Y/Z轴的移动,三个值必须输入如果某个轴不需要移动时设置为零。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; border: 1px solid #ccc; /* 如果将Z轴移动的:hover放在div上,我们不方便一直将鼠标放在div上面,故我们设置成放在main上面让div进行Z轴移动 */ /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照Y轴旋转60度,按Z轴放大5倍*/ transform: perspective(900px) rotateY(60deg) scaleZ(5); /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; } main:hover div:nth-child(2) { /* 由于Z轴可以无限远,所以不能用百分比 */ transform: translate3d(50%, 50%, 100px); } div { height: 100px; width: 100px; background-color: blueviolet; /* 让子元素脱离文档流并参照副父级元素偏移。这是定位+移动的居中方法 */ position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } div:nth-child(1) { background-color: yellow; } div:nth-child(2) { background-color: blueviolet; /* 过渡时间1s */ transition: 1s; } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
渐变输入框
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; background: #34495e; } #form-style-gradient { width: 200px; height: 200px; display: flex; flex-flow: column; justify-content: center; align-items: center; border: 1px solid #ccc; } #form-style-gradient label input { padding: 10px; outline: none; border: none; background-color: #ecf0f1; } #form-style-gradient label { width: 80%; position: relative; overflow: hidden; margin-bottom: 20px; display: flex; flex-flow: column; justify-content: center; align-self: center; } #form-style-gradient label::before { content: ''; position: absolute; /* 移动到最下面 */ left: 0; bottom: 0; height: 2px; width: 100%; background: linear-gradient(to right, white, #1abc9c, #f1c40f, #e74c3c, white); /* 移动到label标签外,然后会被隐藏掉 */ transform: translateX(-100%); transition: 2s; } #form-style-gradient label:hover::before { /* 移动回来 */ transform: translateX(100%); } </style> </head> <body> <form id="form-style-gradient" action=""> <label> <input type="text" name="username" placeholder="请输入用户名"> </label> <label> <input type="text" name="pwd" placeholder="请输入密码"> </label> </form> </body> </html>
页面切换
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> * { padding: 0; margin: 0; } a { text-decoration: none; } body { display: flex; width: 100vw; height: 100vh; flex-direction: column; } main { position: relative; background: #f3f3f3; flex: 1; overflow: hidden; } nav { display: flex; justify-content: space-around; align-items: center; height: 8vh; text-align: center; background: #34495e; } nav a { flex: 1; font-size: 1.3em; text-transform: uppercase; font-weight: bold; opacity: .8; color: white; } nav a:nth-child(2) { border-right: solid 1px #aaa; border-left: solid 1px #aaa; } main>div { position: absolute; left: 0; top: 0; width: 100%; height: 100%; transition: all 1s; z-index: 1; background: #f3f3f3; opacity: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; transform: translate(0, -100%); color: white; font-size: 2em; } main>div:target { opacity: 1; transform: translate(0%, 0%); } main>div:nth-of-type(1):target { background: #3498db; } main>div:nth-of-type(2):target { background: #9b59b6; } main>div:nth-of-type(3):target { background: #16a085; } div i[class^="fa"] { font-size: 100px; color: white; } </style> </head> <body> <main> <div id="home"> <i class="fa fa-home" aria-hidden="true"></i> houdunren.com </div> <div id="video"> <i class="fa fa-vimeo" aria-hidden="true"></i> </div> <div id="live"> <i class="fa fa-viadeo" aria-hidden="true"></i> </div> </main> <nav> <a href="#home">home</a> <a href="#video">video</a> <a href="#live">live</a> </nav> </body> </html>
缩放元素
比如数值为2时表示为原尺寸的两倍。
数值为.5时为原尺寸的一半。
scaleX
按X轴缩放一半。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: scaleX(.5); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
scaleY
按Y轴缩放一半。
scale
使用 scale
可同时设置 X/Y
轴的缩放,如果只设置一个值时表示两轴缩放相同。
使用数值定义缩放,如 .5 表示缩小一半,2 表示放大两倍。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 400px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: scale(.5,2); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
scaleZ
沿Z轴缩放元素,需要有3D透视才可以查看到效果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; border: 1px solid #ccc; /* 如果将Z轴移动的:hover放在div上,我们不方便一直将鼠标放在div上面,故我们设置成放在main上面让div进行Z轴移动 */ /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照Y轴旋转60度,按Z轴放大5倍*/ transform: perspective(900px) rotateY(45deg) scaleZ(5); /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; } main:hover div:nth-child(2) { /* 放大5倍 */ transform: scaleZ(5); } div { height: 100px; width: 100px; background-color: blueviolet; /* 让子元素脱离文档流并参照副父级元素偏移。这是定位+移动的居中方法 */ position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } div:nth-child(1) { background-color: yellow; } div:nth-child(2) { background-color: blueviolet; /* 过渡时间1s */ transition: 1s; transform: translateZ(100px); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
scale3d
沿X/Y/Z三个轴缩放元素。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; border: 1px solid #ccc; /* 如果将Z轴移动的:hover放在div上,我们不方便一直将鼠标放在div上面,故我们设置成放在main上面让div进行Z轴移动 */ /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照Y轴旋转60度,按Z轴放大5倍*/ transform: perspective(900px) rotateY(45deg) scaleZ(5); /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; } main:hover div:nth-child(2) { /* 放大5倍 */ transform: scale3d(.5,.5,.5); } div { height: 100px; width: 100px; background-color: blueviolet; /* 让子元素脱离文档流并参照副父级元素偏移。这是定位+移动的居中方法 */ position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } div:nth-child(1) { background-color: yellow; } div:nth-child(2) { background-color: blueviolet; /* 过渡时间1s */ transition: 1s; transform: translateZ(100px); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
菜单缩放
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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="//at.alicdn.com/t/font_1953712_v8yodek5od.css"> <style> *{ margin: 0; padding: 0; list-style: none; box-sizing: border-box; text-decoration: none; } body{ height: 100vh; width: 100vw; display: flex; flex-flow: column; justify-content: center; align-items: center; } main{ width: 100px; } div i{ display: inline-block; background: darkgray; font-size: 30px !important; display: flex; justify-content: center; align-items: center; } ul{ display: flex; flex-flow: column; justify-content: center; align-items: center; border: 1px solid #ddd; text-transform: uppercase; /* 基点设置为左上 */ transform-origin: left top; /* 鼠标放上去有个小手 */ cursor: pointer; /* 透明度 */ opacity: .6; transform: scale(0); transition: 1s; } ul>*{ margin: 3px; } main:hover ul{ transform: scale(1); } </style> </head> <body> <main> <div> <i class="iconfont icon-dingbudaohang-zhangh"></i> </div> <ul> <li><a href=""></a>我的资料</li> <li><a href=""></a>我的关注</li> <li><a href=""></a>我的收藏</li> </ul> </main> </body> </html>
相册放大
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; list-style: none; box-sizing: border-box; text-decoration: none; } body { height: 100vh; width: 100vw; display: flex; justify-content: center; align-items: center; background-color: deepskyblue; } img{ height: 100px; /* 高斯模糊 */ filter: blur(10px); transform: scale(.6); transition: .5s; /* 鼠标小手 */ cursor: pointer; border: 3px double black; } img:hover{ filter: none; transform: scale(1.3); } </style> </head> <body> <img src="./22.jpg" alt=""> <img src="./33.jpg" alt=""> <img src="./初音.jpg" alt=""> </body> </html>
旋转元素
使用CSS可以控制元素按照不同坐标轴进行旋转。
rotateX
控制元素按照X轴进行旋转操作。单位为deg
,即°
度的意思。
按水平轴发生旋转,如果旋转90deg
将不可见。
正数向上翻,负数向下翻。
如何让他可见呢?我们只需要将父级容器也旋转一下,并加上透视3D效果即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 150px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:hover { transform: rotateX(90deg); } </style> </head> <body> <main> <div>将按照X轴旋转90deg</div> </main> </body> </html>
rotateY
按垂直轴发生旋转,如果旋转90deg
将不可见。
正数向右翻,负数向左翻。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 150px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:hover { transform: rotateY(90deg); } </style> </head> <body> <main> <div>将按照Y轴旋转90deg</div> </main> </body> </html>
rotateZ
按Z轴旋转元素,效果就是沿X/Y轴的平面旋转。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 150px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:hover { transform: rotateZ(90deg); } </style> </head> <body> <main> <div>将按照Z轴旋转90deg</div> </main> </body> </html>
rotate
在X与Y轴平面旋转,效果与使用 rotateZ
相同。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 150px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:hover { transform: rotate(90deg); } </style> </head> <body> <main> <div>将按照Z轴旋转90deg</div> </main> </body> </html>
rotate3d
同时设置X/Y/Z轴的旋转向量值来控制元素的旋转。
需要同时设置如下四个参数。
这个是按照向量进行旋转的,比如第四个参数是90deg
,那么前三个参数填1
就代表各转90°
。
rotate3d(tx,ty,tz,angle)
只转X/Y轴
只转Y/Z轴
X/Y/Z都转
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 150px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:hover { /* X/Y/Z */ transform: rotate3d(1,1,1,180deg); } </style> </head> <body> <main> <div>X/Y/Z 180°</div> </main> </body> </html>
参数顺序
可以同时设置多个旋转规则,顺序不同结果也会不同。
如下,先按X轴转90,再按Y轴转60
div:hover {
transform: rotateX(90deg) rotate(60deg);
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 150px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:hover { transform: rotateX(90deg) rotate(60deg); } </style> </head> <body> <main> <div>X 90° Y 60°</div> </main> </body> </html>
旋转文字
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; list-style: none; box-sizing: border-box; } body{ height: 100vh; width: 100vw; display: flex; justify-content: center; align-items: center; } main{ width: 100px; height: 100px; display: flex; flex-flow: column; justify-content: center; align-items: center; background-color: blueviolet; } main p{ display: flex; justify-content: center; align-items: center; color: white; } main p span{ width: 50%; height: 50%; padding: 5px; font-size: 1em; box-shadow: 0 2px 10px rgba(0, 0, 0, .3); border-radius: 50%; /* 过渡时间 */ transition: 1s; display: flex; justify-content: center; align-items: center; } main p span:first-of-type{ color: green; background-color: yellow; } main p span:nth-of-type(2){ color: yellow; background-color: green; } main p span:nth-of-type(3){ color: white; background-color: deeppink; } main p span:last-of-type{ color: red; background-color: rgb(140, 173, 155); } main:hover p span:nth-of-type(odd){ transform: rotate(360deg); } main:hover p span:nth-of-type(even){ transform: rotate(-360deg); } </style> </head> <body> <main> <p><span>C</span><span>S</span><span>S</span> <span>3</span></p> <p>动画</p> </main> </body> </html>
电子时钟
这个层级有点多,每个刻度都是一个元素,每个刻度之间距离都是30°
,然后再加上3根针就好了。
其实应该分四层,一层做事件驱动,一层做最下面的黑色背景,一层做红色下面的指针,一层做红色。
我就做了三层,所以事件驱动就只能放在<body>
上了。
样式有点丑,别介意...
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; list-style: none; } body { height: 100vh; width: 100vw; display: flex; justify-content: center; align-items: center; } main { height: 400px; width: 400px; background-color: #000; border-radius: 50%; position: relative; } main div{ height: 5%; width: 5%; background-color: green; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 3; } main ul:nth-of-type(1) { height: 80%; width: 80%; background-color: red; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 2; } main ul:nth-of-type(1) li{ background-color: #fff; position: absolute; top: 50%; left: 50%; /* 全部按照上方开始转 */ transform-origin: top; transition: 10s; } body:hover main ul:nth-of-type(1) li:nth-child(1){ transform:rotate(360deg) } main ul:nth-of-type(1) li:nth-child(1){ /* 秒针 */ width: 5px; height: 46%; } main ul:nth-of-type(1) li:nth-child(2){ /* 分针 */ width: 5px; height: 40%; transform:rotate(10deg); } main ul:nth-of-type(1) li:nth-child(3){ /* 分针 */ width: 10px; height: 30%; transform:rotate(60deg); } main ul:nth-of-type(2) { height: 95%; width: 90%; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1; } main ul:nth-of-type(2) li { width: 10px; height: 100%; background-color: #fff; position: absolute; top: 50%; left: 50%; } main ul:nth-of-type(2) li:nth-child(1) { /* 由于不会叠加,所以我们需要在每个元素中设置 */ transform: translate(-50%, -50%) rotate(0deg); } main ul:nth-of-type(2) li:nth-child(2) { transform: translate(-50%, -50%) rotate(30deg); } main ul:nth-of-type(2) li:nth-child(3) { transform: translate(-50%, -50%) rotate(60deg); } main ul:nth-of-type(2) li:nth-child(4) { transform: translate(-50%, -50%) rotate(90deg); } main ul:nth-of-type(2) li:nth-child(5) { transform: translate(-50%, -50%) rotate(120deg); } main ul:nth-of-type(2) li:nth-child(6) { transform: translate(-50%, -50%) rotate(150deg); } </style> </head> <body> <main> <!-- 中心点 --> <div></div> <!-- 红色表盘 --> <ul> <li></li> <li></li> <li></li> </ul> <!-- 刻度针 --> <ul> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> </main> </body> </html>
倾斜元素
倾斜元素的单位也是deg
,即为度数°
。
skewX
按X轴倾斜60deg
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: skewX(60deg); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
skewY
按Y轴倾斜60deg
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 200px; height: 400px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: skewY(60deg); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
skew
同时设置X/Y轴倾斜操作,不指定第二个参数时Y轴倾斜为零。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 400px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; } div:last-child:hover { transform: skew(60deg, 60deg); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
按钮特效
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } div { display: flex; justify-content: center; align-items: center; padding: 10px 50px; border: 5px double #ddd; box-shadow: 0 3px 8px rgba(0, 0, 0, .3); background: #fa7d09; color: #fff; cursor: pointer; position: relative; overflow: hidden; z-index: 0; } div::before { content: ""; background: #679b9b; height: 100%; position: absolute; /* 必须设置宽度,倾斜才会生效 */ width: 0; align-self: center; transform: skewX(-45deg); transition: all .8s; z-index: -1; } div:hover::before { width: 200%; } </style> </head> <body> <div>按钮</div> </body> </html>
立体按钮
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; text-decoration: none; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } a{ width: 100px; height: 30px; font-size: 12px; background: #900d0d; color: white; text-align: center; line-height: 30px; position: relative; transform: skew(25deg,0) rotate(-15deg); } a::after{ content: ""; background: #900d0d; height: 100%; width: 10px; position:absolute; left: -10px; transform: skew(0,-45deg) translate(0,5px); } a::before{ content: ""; background: #900d0d; height: 10px; width: 100%; position:absolute; bottom:-10px; left: 0; transform: skew(-45deg,0) translate(-5px,0); } </style> </head> <body> <a href="javascript:vido(0)">一砖下去可能要命</a> </body> </html>
变形基点
使用 transform-origin
设置元素的X/YZ操作的基点,用于控制旋转、倾斜等操作。
可以使用百分比,也可使用英文单词进行修改。
百分比是按照变形元素的宽高进行取值。
旋转默认以元素中心进行旋转,改变基点后可控制旋转点位置
元素移动不受变形基点所影响
平面旋转
transform-origin: bottom right;
将基点改在右下。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 220px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; /* 修改基点 */ transform-origin: bottom right; } main:hover div { transform: rotate(90deg); } </style> </head> <body> <main> <div>将按照Z轴旋转90deg 基点在右下</div> </main> </body> </html>
倾斜控制
我们依然按照右下进行倾斜。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div:first-child { height: 8px; width: 8px; background-color: black; z-index: 1; border-radius: 50%; /* 脱离文档流并居中 */ position: absolute; left: 50%; top: 50%; margin-left: -4px; margin-top: -4px; } div:last-child { height: 100px; width: 100px; background-color: blueviolet; /* 过渡时间1s,应该放这里,而不是:hover上面 */ transition: 1s; /* 基点改在右下 */ transform-origin: bottom right ; } div:last-child:hover { transform: skewX(60deg); } </style> </head> <body> <main> <div></div> <div></div> </main> </body> </html>
三维旋转
三维旋转需要新增Y轴的基点,还是老规矩,Y轴的基点不能使用百分比。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } main { width: 400px; height: 200px; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; /* 使用 transform-style 用于控制3d透视 */ transform-style: preserve-3d; /* 为了更好的视觉效果,我们给main容器做一个透视 ,并且让它按照X轴旋转-45度 */ transform: perspective(900px) rotateX(-45deg); /* 为了设置第一个div的中心点,所以这里设置一个定位,让子元素的绝对定位参照该元素进行偏移 */ position: relative; } div { height: 100px; width: 210px; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 14px; /* 过渡时间2s,应该放这里,而不是:hover上面 */ transition: 2s; /* 基点 */ transform-origin: right center 100px; } main:hover div { /* X/Y/Z */ transform: rotate3d(1,1,1,720deg); } </style> </head> <body> <main> <div>X right/Y center/Z 100px 720°</div> </main> </body> </html>
新年贺卡
使用变形基点,然后加上旋转元素即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; box-sizing: border-box; } body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } div { width: 200px; height: 150px; background: #fa7d09; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 25px; position: relative; transform-style: preserve-3d; transform: perspective(600px) rotateX(35deg) rotateY(15deg); } div:after { content: "新年"; height: 100%; width: 50%; position: absolute; background-color: #fa1616; left: 0; transition: 1s; transform-origin: center left; display: flex; justify-content: flex-end; align-items: center; } div:before { content: "快乐"; height: 100%; width: 50%; position: absolute; background-color: #fa1616; right: 0; transition: 1s; transform-origin: center right; display: flex; justify-content: flex-start; align-items: center; } div:hover::before{ transform: rotateY(180deg); } div:hover::after{ transform: rotateY(-180deg); } </style> </head> <body> <div>祝你年年有余</div> </body> </html>
动感菜单
这个应该是最难的一个了,那么首先我们要有一个大圆。
鼠标放上去之后所有的小圆跟随大圆的中心点旋转转出来,然后小圆也进行旋转,围绕自身的中心点。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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="//at.alicdn.com/t/font_1953712_b2p42vds2na.css"> <style> * { padding: 0; margin: 0; list-style: none; } body { display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; } nav { width: 400px; height: 400px; display: flex; justify-content: center; align-items: center; cursor: pointer; } nav::before{ content:""; background: #e74c3c; border-radius: 50%; width: 200px; height: 200px; position: absolute; box-shadow: 3px 3px 0px #34495e; } nav::after{ content:"点我"; background: #e74c3c; border-radius: 50%; width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; position: absolute; font-size: 3em; color: #fff; } nav:hover ul{ transform: scale(1); } ul { transition: .5s; transform: scale(0); width: 300px; height: 300px; border-radius: 50%; } ul li { width: 80px; height: 80px; background: #e49; border-radius: 50%; position: absolute; display: flex; justify-content: center; align-items: center; font-size: 2em; color: #fff; transition: 1s; transform-origin: 150px 150px; } ul li span{ display: flex; justify-content: center; align-items: center; transition: 1s; } ul li span i{ font-size: 1.6em !important; } nav:hover li:nth-of-type(1) { transform: rotate(60deg); } nav:hover li:nth-of-type(2) { transform: rotate(120deg); } nav:hover li:nth-of-type(3) { transform: rotate(180deg); } nav:hover li:nth-of-type(4) { transform: rotate(240deg); } nav:hover li:nth-of-type(5) { transform: rotate(300deg); } nav:hover li:nth-of-type(6) { transform: rotate(360deg); } /* 解决小图标倾斜 */ nav:hover li:nth-of-type(1) span { transform: rotate(300deg); } nav:hover li:nth-of-type(2) span { transform: rotate(600deg); } nav:hover li:nth-of-type(3) span { transform: rotate(900deg); } nav:hover li:nth-of-type(4) span { transform: rotate(1200deg); } nav:hover li:nth-of-type(5) span { transform: rotate(1500deg); } nav:hover li:nth-of-type(6) span { transform: rotate(1800deg); } </style> </head> <body> <nav> <ul> <li><span><i class="iconfont icon-dianhua"></i></span></li> <li><span><i class="iconfont icon-dingbudaohang-zhangh"></i></span></li> <li><span><i class="iconfont icon-shezhi"></i></span></li> <li><span><i class="iconfont icon-lianxiren"></i></span></li> <li><span><i class="iconfont icon-shoucang"></i></span></li> <li><span><i class="iconfont icon-ziliao"></i></span></li> </ul> </nav> </body> </html>
透视景深
perspective
使用 perspective
来控制元素的透视景深
perspective
规则为舞台元素控制景深, perspective
属性为控制单个元素
舞台透视
perspective
规则用于将父级整个做为透视元素,会造成里面的每个子元素的透视是不一样的。就像现实中摆一排杯子,是使用统一透视的,每个杯子的透视不一样,造成有大有小。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; } body { display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; } main{ width: 400px; height: 200px; /* 给整个台子做透视 */ perspective:200px ; position: relative; border: solid 5px silver; display: flex; justify-content: center; align-items: center; } main div{ width: 50%; height: 50%; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; margin: 20px; transform: rotateY(60deg); } </style> </head> <body> <main> <div>车1</div> <div>车2</div> </main> </body> </html>
单独透视
perspective
函数用于为元素设置单独透视,下面是为元素单独设置透视参数,每个元素的透视效果是一样的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; list-style: none; } body { display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; } main { width: 400px; height: 200px; position: relative; border: solid 5px silver; display: flex; justify-content: center; align-items: center; } main div { width: 50%; height: 50%; background-color: blueviolet; display: flex; justify-content: center; align-items: center; color: #fff; margin: 20px; /* 给每个车做透视,现在每辆车都以相同的角度对着你 */ transform: perspective(100px) rotateY(60deg); } </style> </head> <body> <main> <div>车1</div> <div>车2</div> </main> </body> </html>
立方体
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; box-sizing: border-box; list-style: none; } body { background: #34495e; } main { position: absolute; left: 50%; top: 50%; width: 200px; height: 200px; transform-style: preserve-3d; transform-origin: 50% 50% 50px; transform: translate(-50%, -50%) rotateY(0deg); transition: 2s; } main:hover { transform: translate(-50%, -50%) rotate3d(1, 1, 0, 180deg); } div { position: absolute; width: 200px; height: 200px; background: #000; display: flex; justify-content: center; align-items: center; font-size: 4em; } div:nth-child(1) { transform-origin: right; background: #1abc9c; transform-origin: bottom; transform: translateY(-200px) rotateX(-90deg); opacity: .8; } div:nth-child(2) { transform-origin: right; background: #27ae60; transform-origin: top; transform: translateY(200px) rotateX(90deg); opacity: .8; } div:nth-child(3) { transform-origin: bottom; background: #e67e22; transform-origin: right; transform: translateX(-200px) rotateY(90deg); opacity: .8; } div:nth-child(4) { transform-origin: top; background: #8e44ad; transform-origin: left; transform: translateX(200px) rotateY(-90deg); opacity: .8; } div:nth-child(5) { transform-origin: left bottom; background: #ecf0f1; opacity: .8; } div:nth-child(6) { transform-origin: left bottom; background: #ecf0f1; opacity: .5; transform: translateZ(200px); } </style> </head> <body> <main> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> </main> </body> </html>
3D透视
transform-style
使用 transform-style
用于控制3d透视。
应用于舞台即变形元素的父级元素
设置
overflow:visible
时preserve-3d
才无效
选项 | 说明 |
---|---|
flat | 2D平面舞台 |
preserve-3d | 3D透视舞台 |
三维图集
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> body { background: #34495e; } main { position: absolute; width: 400px; height: 200px; left: 50%; top: 50%; transform-style: preserve-3d; transform-origin: center center -300px; transform: translate(-50%, -50%) rotateX(-45deg); transition: 2s; } body:hover main { transform: translate(-50%, -50%) rotateX(-45deg) rotateY(900deg); } div { position: absolute; width: 100%; height: 100%; transform-origin: center center -300px; overflow: hidden; background: content-box; padding: 10px; opacity: .5; } div:nth-child(1) { background-color: #ade498; transform: rotateY(60deg); } div:nth-child(2) { background-color: #d3de32; transform: rotateY(120deg); } div:nth-child(3) { background-color: #ffffdd; transform: rotateY(180deg); } div:nth-child(4) { background-color: #006a71; transform: rotateY(240deg); } div:nth-child(5) { background-color: #fe91ca; transform: rotateY(300deg); } div:nth-child(6) { background-color: #cffe0f; transform: rotateY(360deg); } </style> </head> <body> <main> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> </main> </body> </html>
观看视角
perspective-origin
perspective-origin
用于控制视线的落点,就像我们眼睛看物体时的聚焦点。可以理解眼镜看物体的位置,比如看一台汽车,是在看车头左边看还是车头右边看。
需要设置 perspective
透视后才可以看到效果。
一般设置在舞台元素上来控制子元素
取值 | 说明 |
---|---|
x-axis | 定义该视图在 x 轴上的位置。默认值:50%。可能的值:left、center、right、length、% |
y-axis | 定义该视图在 y 轴上的位置。默认值:50%。可能的值:top、center、bottom、length、% |
隐藏背面
backface-visibility
使用 backface-visibility
用于控制是否可以看到元素的背面。
一般设置在元素上而不是舞台元素上
需要舞台元素(父级元素)设置 transform-style: preserve-3d
选项 | 说明 |
---|---|
visible | 背面可见 |
hidden | 背面隐藏 |
翻转卡片
下面使用隐藏背面与透视技术制作的翻转卡片效果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src='https://code.jquery.com/jquery-3.3.1.slim.min.js'></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <style> * { padding: 0; margin: 0; box-sizing: border-box; } main { position: absolute; width: 100vw; height: 100vh; transition: 2s; transform-style: preserve-3d; } main.login { transform: perspective(900px) rotateY(0deg); } main.register { transform: perspective(900px) rotateY(180deg); } div { position: absolute; width: 100%; height: 100%; font-size: 5em; display: flex; flex-direction: column; justify-content: center; align-items: center; backface-visibility: hidden; transition: 2s; text-transform: uppercase; color: white; } div span { text-transform: lowercase; letter-spacing: .2em; font-size: .2em; color: #2c3e50; } div:nth-child(1) { background: #2ecc71; transform: rotateY(0deg); } div:nth-child(2) { background: #e74c3c; transform: rotateY(180deg); } nav { position: absolute; width: 100%; height: 100%; z-index: 99; text-align: center; display: flex; align-items: flex-end; justify-content: center; padding-bottom: 30px; } nav a { padding: 10px; text-decoration: none; font-size: 1em; background: #000; color: white; margin-right: 10px; cursor: pointer; left: 0; top: 0; } </style> </head> <body> <main> <div> <i class="fa fa-home" aria-hidden="true"></i> login <span>houdunren.com</span> </div> <div> <i class="fa fa-user" aria-hidden="true"></i> register <span>houdunren.com</span> </div> </main> <nav> <a href="javascript:;" onclick="change('login')">登录</a> <a href="javascript:;" onclick="change('register')">注册</a> </nav> </body> <script> function change(t) { switch (t) { case 'login': $("main").removeClass().addClass('login'); break; case 'register': $("main").removeClass().addClass('register'); break; } } </script> </html>