transform
一、认识
transform
属性允许你旋转,缩放,倾斜或平移给定元素。这是通过修改 CSS 视觉格式化模型的坐标空间来实现的。 transform
属性可以指定为关键字值 none
或一个或多个 <transform-function>
值。
二、语法
transform =
none |
<transform-list>
<transform-list> =
<transform-function>+
/* Keyword values */
transform: none;
/* Function values */
transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
transform: translate(12px, 50%);
transform: translateX(2em);
transform: translateY(3in);
transform: scale(2, 0.5);
transform: scaleX(2);
transform: scaleY(0.5);
transform: rotate(0.5turn);
transform: skew(30deg, 20deg);
transform: skewX(30deg);
transform: skewY(1.07rad);
transform: matrix3d(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0);
transform: translate3d(12px, 50%, 3em);
transform: translateZ(2px);
transform: scale3d(2.5, 1.2, 0.3);
transform: scaleZ(0.3);
transform: rotate3d(1, 2.0, 3.0, 10deg);
transform: rotateX(10deg);
transform: rotateY(10deg);
transform: rotateZ(10deg);
transform: perspective(17px);
/* Multiple function values */
transform: translateX(10px) rotate(10deg) translateY(5px);
/* Global values */
transform: inherit;
transform: initial;
transform: unset;
三、取值
3.1 none
transform: none
: 不应用任何变换。
3.2 <transform-function>
transform: <transform-function>
要应用的一个或多个 CSS
变换函数。变换函数按从左到右的顺序相乘,这意味着复合变换按从右到左的顺序有效地应用。
四、函数
4.1 scale()
scale
: scale
允许你可以分别且独立地指定 CSS
属性 transform
缩放的比例。这更好地映射到典型的 UI(用户界面)用法中,并免去了在指定变换值时必须记住变换函数的精确顺序的麻烦。
语法
scale =
none |
[ <number> | <percentage> ]{1,3}
/* 关键值 */
scale: none;
/* 单个值 */
/* 设定比 1 大的数值使该元素变大 */
scale: 2;
/* 设定比 1 小的数值使该元素缩小 */
scale: 0.5;
/* 两个值 */
scale: 2 0.5;
/* 三个值 */
scale: 2 0.5 2;
取值:
-
none: 指定不进行缩放。
-
单一数值: 单一的数值即指定了一个缩放系数,同时作用于
X
轴和Y
轴让该元素进行缩放,相当于指定了单个值的scale()
(2D 缩放) 函数。 -
两个长度/百分比值: 两个数值即分别指定了
2D
比例的X
轴和Y
轴的缩放系数,相当于指定了两个值的scale()
(2D 缩放)函数。 -
三个长度/百分比值: 三个数值即分别指定了
3D
比例的X
轴、Y
轴和Z
轴的缩放系数。相当于一个scale3d()
函数。
4.2 skew()
skew()
: skew()
函数定义了一个元素在二维平面上的倾斜转换。它的结果是一个<transform-function>
数据类型。这种转换是一种剪切映射 (横切),它在水平和垂直方向上将单元内的每个点扭曲一定的角度。每个点的坐标根据指定的角度以及到原点的距离,进行成比例的值调整;因此,一个点离原点越远,其增加的值就越大。
语法:
skew(ax)
skew(ax, ay)
参数值:
-
ax
:ax
是一个<angle>
,表示用于沿横坐标扭曲元素的角度。 -
ay
:ay
是一个<angle>
,表示用于沿纵坐标扭曲元素的角度。如果未定义,则其默认值为0
,导致纯水平倾斜。
4.3 rotate()
rotate
: rotate
属性允许你单独设置 transform
的旋转属性。这种映射方式可以让我们更方便的设置我们想要的效果,并且避免了简写形式需要记忆属性顺序的不方便之处。
语法
rotate =
none |
<angle> |
[ x | y | z | <number>{3} ] && <angle>
/* Keyword values */
scale: none;
/* Angle value */
rotate: 90deg;
rotate: 0.25turn;
rotate: 1.57rad;
/* x, y, or z axis name plus angle */
rotate: x 90deg;
rotate: y 0.25turn;
rotate: z 1.57rad;
/* Vector plus angle value */
rotate: 1 1 1 90deg;
取值:
-
none
: 指定不应用旋转 -
角度值:
-
x
,y
或者z
轴名称加上角度值: -
向量加上角度值:
4.4 matrix()
matrix()
: 指定了一个由指定的 6
个值组成的 2D
变换矩阵。这种矩阵的常量值是隐含的,而不是由参数传递的;其他的参数是以列优先的顺序描述的。
语法
matrix(a, b, c, d, tx, ty)
matrix( scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY() )
参数值:
-
a b c d
: 描述线性变换的<number>
-
tx ty
: 描述如何应用这个变换的<number>
。
4.5 translate()
translate()
: translate
允许你单独声明平移变换,并独立于 transform
属性。这在一些典型的用户界面上更好用,而且这样就无需在 transform
中声明该函数并记住转换函数的确切顺序了。
语法
translate =
none |
<length-percentage> [ <length-percentage> <length>? ]?
<length-percentage> =
<length> |
<percentage>
/* Keyword values */
translate: none;
/* Single values */
translate: 100px;
translate: 50%;
/* Two values */
translate: 100px 200px;
translate: 50% 105px;
/* Three values */
translate: 50% 105px 5rem;
Copy to Clipboard
取值
-
none
: 表示不应用平移效果。 -
单个长度/百分比值: 一个长度值或百分比,表示二维平移,与声明了
X
轴和Y
轴的平移一样(此时省略的第二个值默认为0
)。等同于在translate()
函数(2D
平移)中指定单个值。 -
两个长度/百分比值: 两个长度值或百分比表示在二维上分别按照指定
X
轴和Y
轴的值进行的平移。等同于在translate()
函数(2D
平移)中函数指定两个值。 -
三个长度/百分比值: 三个长度值或百分比,表示分别指定
X
轴、Y
轴、Z
轴的值进行三维平移。等同于translate3d()
函数(3D
平移)。
4.6 perspective()
perspective()
: 属性 perspective
指定了观察者与 z=0
平面的距离,使具有三维位置变换的元素产生透视效果。z>0
的三维元素比正常大,而 z<0
时则比正常小,大小程度由该属性的值决定。
语法
perspective =
none |
<length [0,∞]>
/* Keyword value */
perspective: none;
/* <length> values */
perspective: 20px;
perspective: 3.5em;
/* Global values */
perspective: inherit;
perspective: initial;
perspective: unset;
取值
-
none: 没有应用
perspective
样式时的默认值。 -
<length>
:<length>
指定观察者距离z=0
平面的距离,为元素及其内容应用透视变换。当值为0
或负值时,无透视变换。
五、问题
5.1 zoom 和 transform: scale 有什么区别?
-
缩放源:
-
zoom: 相对于左上角
-
scale: 默认居中缩放
-
-
缩放后占据空间大小:
-
zoom: zoom 改变了元素占据的空间大小
-
scale: scale 的缩放占据的原始尺寸不变,页面布局不会发生变化
-
-
字体大小:
-
zoom: zoom 缩放受限于最小 12 像素中文大小限制
-
scale: scale 就是纯粹的对图形进行比例控制
-
5.2 为什么有时候⽤ transform 来改变位置⽽不是定位?
translate
是 transform
属性的⼀个值。改变 transform
或 opacity
不会触发浏览器重新布局(reflow
)或重绘(repaint
),只会触发复合(compositions
)。⽽改变绝对定位会触发重新布局,进⽽触发重绘和复合。transform
使浏览器为元素创建⼀个 GPU
图层,但改变绝对定位会使⽤到 CPU
。 因此 translate()
更⾼效,可以缩短平滑动画的绘制时间。 ⽽ translate
改变位置时,元素依然会占据其原始空间,绝对定位就不会发⽣这种情况。
5.3 为什么有时候用 transform 会导致子元素文本模糊呢?
原因: 在 Google
上,其实我们能搜到非常多类似的案例,总结而言:
-
当文本元素的某个祖先容器存在
transform: translate()
或者transform: scale()
等transform
操作时,容易出现这种问题。当然,这只是必要条件,不是充分条件。继续深入探究,会发现,必须还得同时满足一些其它条件 -
元素作用了
transform: translate()
或者transform: scale()
后的计算值产生了非整数 -
文本内容是否模糊还与屏幕有关,高清屏(
dpr > 2
)下不容易触发,更多发生在普通屏幕下(dpr = 1
) -
并非所有浏览器都是这个表现,基本发生在
chromium
内核
那么,为何会发生这种现象?针对这个问题,没有找到特别官方的回答,普遍的认为是因为: 由于浏览器将图层拆分到 GPU
以进行 3D
转换,而非整数的像素偏移,使得 Chrome
在字体渲染的时候,不是那么的精确。
解决方案:
-
保证运用了
transform: translate()
或者transform: scale()
的元素的宽高为偶数, 最有效的一种方式。如果你赋予给元素的transform
的值非常明确,譬如我上文例子中的利用其来对元素进行水平垂直居中 --transform: translate(-50%, -50%)``,让元素的高宽为偶数这个方法是可行的,但如果当你无法确定transform
的值,譬如transform: translateX(-31.24%)
或者是transform: scale(1.05)
,那这个方法依旧无法奏效。 -
弃用
transform
: 如果这个问题对你的页面非常致命,那么只能弃用transform
,寻找替代方案。大部分的时候,我们还是可以找到不使用transform
的替代方案的。