# CSS3教程 - 14 变形
CSS3 中的变形 (Transforms))允许对元素进行各种图形上的转换,例如旋转、缩放、倾斜和位移,而不会更改元素在文档流中的位置。变形通常用于创建动画效果或在页面上实现交互式效果。
CSS3 中的 transform
属性支持四种基本的变形:平移 (Translation)、旋转 (Rotation)、缩放 (Scaling)、和倾斜 (Skewing),这些变形可以单独使用,也可以组合使用。
# 14.1 平移
# 1 平移的使用
语法:
transform: translateX(y); /* 沿着 x 轴方向平移元素 */
/* 或者 */
transform: translateY(x); /* 沿着 y 轴方向平移元素 */
/* 或者 */
transform: translate(x, y); /* 同时沿着 x 轴和 y 轴平移元素 */
2
3
4
5
举个栗子:
<!DOCTYPE html>
<html>
<head>
<style>
.box1 {
transform: translateX(100px); /* 右移100px */
width: 100px;
height: 100px;
background-color: skyblue;
}
.box2 {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 上面对 box1 右移 100px;
- 变形不会改变元素在文档流中的位置,所以对 box2 没有影响;
显示如下,蓝色的 box1 右移了:
下面看一下 y 轴的平移:
<!DOCTYPE html>
<html>
<head>
<style>
.box1 {
transform: translateX(50px) translateY(50px); /* 右移、下移100px */
width: 100px;
height: 100px;
background-color: skyblue;
}
.box2 {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 上面让 box1 右移和下移了 50px;
- 也可以写为
transform: translate(50px, 50px);
。
显示如下:
可以看到对 box2 没有任何影响。
# 2 水平垂直居中
在前面让子元素在父元素中水平垂直居中有如下方式:
绝对定位的方式
/* 这种居中方式,只适用于子元素的大小确定的情况,子元素尺寸为auto时候是不行的,会拉伸元素尺寸 */ position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin: auto;
1
2
3
4
5
6
7table-cell
的方式/* table-cell的方式具有一定局限性,块元素是不行的 */ display: table-cell; vertical-align: middle; text-align: center;
1
2
3
4
下面介绍一种新的水平垂直居中方式。
平移的距离可以使用百分比,表示是相对于元素自身的尺寸,X轴方向的平移相对于元素的宽度,Y轴方向上的平移相对于元素的高度。
通过这个特性,可以实现元素水平和垂直方向的居中。如下:
<!DOCTYPE html>
<html>
<head>
<style>
.outer {
width: 300px;
height: 300px;
position: relative; /* 父相子绝,父元素相对定位 */
background-color: skyblue;
}
.inner {
position: absolute; /* 父相子绝,子元素绝对定位 */
left: 50%; /* 让子元素在包含块中右移父元素的宽度的一半 */
top: 50%; /* 让子元素在包含块中下移父元素的高度的一半 */
transform: translateX(-50%) translateY(-50%); /* 上面的操作会让子元素的左上角移动到了父元素的中心点,这里将子元素拉回自身元素一半的尺寸 */
background-color: lightpink;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">foooor</div>
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- 首先父相子绝,父元素开启相对定位,子元素开启绝对定位,然后将子元素
left
和top
设置为50%
,那么子元素会右移和下移到父元素(包含块)的中心点位置,也就是子元素的左上角(起点)在父元素的中心点,所以需要将子元素水平和垂直方向上拉回子元素一半的距离,所以这里使用平移50%
,也就是子元素向左、向上平移子元素50%
的距离。 - 这种居中方式,子元素的尺寸为
auto
,也能实现居中。
显示如下:
# 3 浮出效果
我们经常会在网页中看到,将鼠标悬浮到指定的模块上,模块有浮出的效果,该如何实现呢?
实现思路:鼠标悬浮的时候,添加背景,并将元素向上移动。
实现如下:
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 200px;
height: 200px;
background-color: silver;
margin: 30px auto;
transition: all 0.3s; /* 添加动画效果 */
}
div:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); /* 添加阴影 */
transform: translateY(-5px); /* 在Y轴上向上移动 */
}
</style>
</head>
<body>
<div class="box1"></div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 在鼠标悬浮的时候,添加阴影,并将元素向上平移,然后添加一个动画即可。
# 4 Z轴平移
Z轴是垂直于屏幕的,在Z轴平移,调整的是元素和人眼之间的距离,平移距离越大,元素离人越近,元素显示也会变大(近大远小)。
它是属于3D的立体效果,默认情况下网页是不支持透视的(近大远小),如果需要看见效果必须要设置网页的视距。
举个栗子:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px; /* 设置视距 */
}
.box1 {
width: 100px;
height: 100px;
background-color: lightgray;
margin: 100px auto;
transition: all 0.3s;
}
.box1:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
transform: translateZ(400px); /* 沿着Z轴移动400像素 */
}
</style>
</head>
<body>
<div class="box1"></div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- 首先通过
perspective: 800px;
设置视距为800像素,然后通过transform: translateZ(400px);
沿着 Z 轴方向平移400元素;也就是说一开始没平移的时候,相当于人眼距离元素800像素,然后沿着Z轴移动400像素,此时人眼距离元素为 800 - 400 = 400 像素,所以看元素应该是平移前的两倍大了。如果设置为translateZ(800px)
,视距又是800像素,那么相当于把元素贴你脸上了,就无线大了。 perspective
推荐为 600 ~ 1200 像素,根据实际需要设置。
显示如下:
# 14.2 旋转
旋转主要使用 rotate()
函数来对元素进行旋转。旋转操作可以让元素围绕一个中心点进行旋转,旋转角度可以是正值或负值,表示顺时针或逆时针旋转。
# 1 旋转的使用
语法:
transform: rotateX(angle); /* 绕 X 轴旋转,表现为元素上下翻转 */
/* 或者 */
transform: rotateY(angle); /* 绕 Y 轴旋转,表现为元素左右翻转 */
/* 或者 */
transform: rotateZ(angle); /* 绕 Z 轴旋转,表现为元素在平面内的旋转 */
/* 或者 */
transform: rotate(angle); /* 绕 Z 轴旋转,表现为元素在平面内的旋转 */
2
3
4
5
6
7
angle
:指定旋转的角度,通常使用度数(deg
)、弧度(rad
)、圈数(turn
)等单位。常用的单位是deg
(度)。例如rotate(90deg)
表示顺时针旋转 90 度;rotate(-45deg)
:表示逆时针旋转 45 度。rotate(π / 2)
:表示顺时针旋转 90 度(π / 2 弧度)。rotate(1turn)
表示顺时针旋转一圈,等于 360 度;rotate(-0.5turn)
表示逆时针旋转半圈,等于 -180 度。
举个栗子:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px; /* 设置视距 */
}
.box1 {
width: 100px;
height: 100px;
background-color: lightgray;
margin: 100px auto;
transform: rotateZ(20deg); /* 沿着Z轴旋转20度 */
}
</style>
</head>
<body>
<div class="box1">foooor</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- 上面将 box1 沿着 Z 轴旋转了 20 度。
显示如下:
再举个栗子:沿着 X 轴旋转 45 度:
transform: rotateX(45deg); /* 沿着Z轴旋转45度 */
显示如下:
上面是设置了 perspective
,所以沿着 X 或 Y 轴旋转的时候,有透视效果(近大远小),如果不设置视距,就没有近大远小的透视效果了,那么上图的元素上边缘和下边缘将是一样宽的。
再举个栗子:当鼠标悬浮的时候,沿着 Y 轴旋转 180 度,并添加过渡动画:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px; /* 设置视距 */
}
.box1 {
width: 150px;
height: 150px;
background-color: lightgray;
margin: 100px auto;
transition: all 0.3s; /* 设置动画,0.3秒完成 */
}
.box1:hover {
transform: rotateY(180deg); /* 沿着Y轴旋转180度 */
}
</style>
</head>
<body>
<div class="box1">foooor</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 上面设置鼠标悬浮的时候沿着 Y 轴旋转180度;并设置了 0.3 秒的过渡;
显示如下:
# 2 变形中心
默认情况下,旋转是围绕元素的 中心点 进行的。如果需要改变旋转中心点,可以使用 transform-origin
属性。
transform-origin
属性定义了旋转的中心点(即元素围绕哪个点旋转)。它的值可以是像素、百分比或者关键字。
语法:
transform-origin: x-axis y-axis; /* 2D旋转,围绕Z轴旋转 */
/* 或者 */
transform-origin: x-axis y-axis z-axis; /* 3D旋转,可以围绕X轴和Y轴旋转 */
2
3
x-axis
:水平位置,可以是像素值、百分比值或关键字(left
,center
,right
)。y-axis
:垂直位置,可以是像素值、百分比值或关键字(top
,center
,bottom
)。z-axis
:深度位置,可以是像素值或百分比(通常不使用关键字)。
举个栗子:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px; /* 设置视距 */
}
.box1 {
width: 100px;
height: 100px;
background-color: lightgray;
margin: 100px auto;
transition: all 0.3s; /* 设置动画,0.3秒完成 */
transform-origin: 0px 0px; /* 旋转的中心点在左上角 */
}
.box1:hover {
transform: rotate(45deg); /* 沿着Z轴顺时针旋转45度 */
}
</style>
</head>
<body>
<div class="box1">foooor</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- 上面设置旋转中心点为
(0,0)
,也就是左上角;当鼠标悬浮在 box1 的时候,就在Z轴围绕着左上角旋转。
显示如下:
# 14.3 缩放
对元素进行缩放,主要使用的函数是 scale()
。
# 1 缩放的使用
语法:
transform: scaleX(x); /* 对X轴方向上进行缩放 */
transform: scaleY(y); /* 对Y轴方向上进行缩放 */
transform: scale(x, y); /* 对X轴和Y轴双方向进行缩放 */
transform: scaleZ(y); /* 对Z轴方向上进行缩放 */
transform: scale3d(x, y, z); /* 对X、Y、Z轴三个方向进行缩放 */
2
3
4
5
- 在没有进行缩放的时候,x、y、z的值是 1。如果要放大,则设置值为大于 1 的数即可;如果要缩小,设置值为小于 1 的小数即可。
举个栗子:
<!DOCTYPE html>
<html>
<head>
<style>
.box1 {
height: 200px;
width: 200px;
background-color: skyblue;
margin: 200px auto;
transition: all 0.3s; /* 添加过渡效果 */
}
.box1:hover {
transform: scaleX(2);
}
</style>
</head>
<body>
<div class="box1">foooor</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 上面在鼠标悬浮 box1 的时候,对 box1 进行 X 轴的 2 倍缩放。
显示如下:
Y 轴的缩放也是类似的,如果是 X 轴 Y 轴同时缩放,使用 scale(x, y)
即可。
但是此时对 Z 轴缩放是没有效果的,因为 Z 轴方向上,元素没有尺寸,Z 轴的缩放用的不多。
# 2 变形中心
在旋转的时候,通过 transform-origin
属性指定旋转中心,同样可以通过 transform-origin
属性可以指定缩放中心, transform-origin
就是用来指定变形原点的。
举个栗子,基于上面的代码,指定缩放中心:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px;
}
.box1 {
height: 100px;
width: 100px;
background-color: skyblue;
margin: 200px auto;
transition: all 0.3s; /* 过渡效果 */
transform-origin: 0 0; /* 变形的原点 */
}
.box1:hover {
transform: scale(2, 2); /* x、y轴缩放 */
}
</style>
</head>
<body>
<div class="box1">foooor</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- 上面指定了 box1 的缩放原点为
0,0
,也就是左上角,然后鼠标悬浮的时候,对 X 轴和 Y 轴进行两倍的放大。
显示如下:
# 14.4 变形组合使用
平移、旋转、缩放的变换是可以一起使用的。变换是按顺序进行的,因此后面的变换会影响前面的变换。
举个栗子:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px;
}
.box1 {
height: 100px;
width: 100px;
background-color: skyblue;
margin: 200px auto;
transition: all 0.5s; /* 过渡效果 */
}
.box1:hover {
transform: translateX(200px) rotate(180deg) scale(2, 2); /* 同时变形 */
}
</style>
</head>
<body>
<div class="box1">foooor</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- 在上面的代码中,鼠标悬浮的时候,会同时进行平移、旋转和缩放。
显示如下:
需要注意变换的顺序,变换是按顺序进行的,因此后面的变换会影响前面的变换,所以上面的平移是放到最前面的,如果放到最后面,那么元素被旋转后,自身坐标系也被旋转了,会发现元素向左平移了,
# 14.5 练习-立方体
下面通过变形实现一个立方体,立方体的每个面使用不同的图片。
最终效果:
实现思路:首先定义一个外部的元素,在外部的元素中放六个子 div 元素,并给每个子 div 设置不同的背景,充当立方体的六个面。然后父相子绝,父元素采用相对定位,子元素采用绝对定位,那么六个子元素就重叠了。旋转和平移各个div,分别作为左右、上下、前后的面,这样就实现了。
这里父元素需要用到一个属性 transform-style: preserve-3d;
让元素的 子元素 能够 保留三维变换,即它们也会在三维空间中进行变换。默认情况下,子元素的变换会被应用到其父元素的平面上,也就是说,子元素将被 “拉平”,不受父元素三维变换的影响。通过使用 preserve-3d
,可以确保子元素保持其在 3D 空间中的位置。
代码如下:
<!DOCTYPE html>
<html>
<head>
<style>
body {
perspective: 800px;
}
.cube {
height: 200px;
width: 200px;
margin: 200px auto;
position: relative; /* 父相子绝 */
transform-style: preserve-3d; /* 设置3d变形效果 */
animation: cube-rotate 12s infinite linear; /* 设置动画效果 */
}
.cube div {
height: 200px;
width: 200px;
background-size: cover;
background-position: center;
position: absolute; /* 父相子绝 */
opacity: 0.9; /* 设置透明效果 */
}
.surface1 {
background-image: url("/image/css3.webp");
transform: translateX(-100px) rotateY(90deg); /* 左边的面 */
}
.surface2 {
background-image: url("/image/html5.webp");
transform: translateX(100px) rotateY(90deg); /* 右边的面 */
}
.surface3 {
background-image: url("/image/javascript.webp");
transform: translateY(-100px) rotateX(90deg); /* 上边的面 */
}
.surface4 {
background-image: url("/image/git.webp");
transform: translateY(100px) rotateX(90deg); /* 下边的面 */
}
.surface5 {
background-image: url("/image/java.webp");
transform: translateZ(100px); /* 前边的面 */
}
.surface6 {
background-image: url("/image/vue3.webp");
transform: rotateX(180deg) translateZ(100px); /* 后边的面 */
}
@keyframes cube-rotate {
from {
transform: rotateX(0) rotateY(0) rotateZ(0);
}
to {
transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg);
}
}
</style>
</head>
<body>
<div class="cube">
<div class="surface1"></div>
<div class="surface2"></div>
<div class="surface3"></div>
<div class="surface4"></div>
<div class="surface5"></div>
<div class="surface6"></div>
</div>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79