跳到主要内容

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 有什么区别?

  1. 缩放源:

    • zoom: 相对于左上角

    • scale: 默认居中缩放

  2. 缩放后占据空间大小:

    • zoom: zoom 改变了元素占据的空间大小

    • scale: scale 的缩放占据的原始尺寸不变,页面布局不会发生变化

  3. 字体大小:

    • zoom: zoom 缩放受限于最小 12 像素中文大小限制

    • scale: scale 就是纯粹的对图形进行比例控制

5.2 为什么有时候⽤ transform 来改变位置⽽不是定位?

translatetransform 属性的⼀个值。改变 transformopacity 不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)。⽽改变绝对定位会触发重新布局,进⽽触发重绘和复合。transform使浏览器为元素创建⼀个 GPU 图层,但改变绝对定位会使⽤到 CPU。 因此 translate() 更⾼效,可以缩短平滑动画的绘制时间。 ⽽ translate 改变位置时,元素依然会占据其原始空间,绝对定位就不会发⽣这种情况。

5.3 为什么有时候用 transform 会导致子元素文本模糊呢?

原因: 在 Google 上,其实我们能搜到非常多类似的案例,总结而言:

  1. 当文本元素的某个祖先容器存在 transform: translate() 或者 transform: scale()transform 操作时,容易出现这种问题。当然,这只是必要条件,不是充分条件。继续深入探究,会发现,必须还得同时满足一些其它条件

  2. 元素作用了 transform: translate() 或者 transform: scale() 后的计算值产生了非整数

  3. 文本内容是否模糊还与屏幕有关,高清屏(dpr > 2)下不容易触发,更多发生在普通屏幕下(dpr = 1

  4. 并非所有浏览器都是这个表现,基本发生在 chromium 内核

那么,为何会发生这种现象?针对这个问题,没有找到特别官方的回答,普遍的认为是因为: 由于浏览器将图层拆分到 GPU 以进行 3D 转换,而非整数的像素偏移,使得 Chrome 在字体渲染的时候,不是那么的精确。

解决方案:

  1. 保证运用了 transform: translate() 或者 transform: scale() 的元素的宽高为偶数, 最有效的一种方式。如果你赋予给元素的 transform 的值非常明确,譬如我上文例子中的利用其来对元素进行水平垂直居中 -- transform: translate(-50%, -50%)``,让元素的高宽为偶数这个方法是可行的,但如果当你无法确定transform 的值,譬如 transform: translateX(-31.24%) 或者是 transform: scale(1.05),那这个方法依旧无法奏效。

  2. 弃用 transform: 如果这个问题对你的页面非常致命,那么只能弃用 transform,寻找替代方案。大部分的时候,我们还是可以找到不使用 transform 的替代方案的。