转换
基本概念
使用 transform 属性可以让一个元素在坐标系统中进行移动、旋转、缩放、倾斜,并且这个坐标系可以是二维,也可以是三维。
transform: none | [<transform-function>]*
默认值为 none,也可以加上 一个或者多个 transform-function,这里的 transform-function 就是形变函数,支持 2D 和 3D 形变。
2D 形变函数
平移
坐标轴的原点是元素的中心。

需要注意的是这种方式并不会让元素脱离文档流,并且会保留元素原来的占位空间,可以类比于 position: relative。
transform: translateX(<length> | <percentage>);
让元素沿 x 轴方向移动,i 的取值类型如下:
<length>,可以是任意带有长度单位的数字,比如20px、10rem<percentage>,百分比是相当于当前元素的宽度决定
并且 i 可以取负数,表示沿 x 轴反方向移动。
transform: translateY(<length> | <percentage>);
用法和 translateX 一样,该函数可以让元素沿 y 轴方向移动,当参数取值是百分数时,计算值由该元素的高度决定。 
transform: translate(x, y);
相当于 translateX 和 translateY 的简写,第一个参数决定 x 轴方向的位移,第二个参数决定 y 轴方向的位移。
旋转
transform: rotate(<angle>);
参数类型为 <angle>,默认情况下旋转点为元素的中心,可以使用 transform-origin 来修改旋转中心。
缩放
transform: scaleX(<number>);
设置元素沿 x 轴方向的缩放倍数。
transform: scaleY(<number>);
设置元素沿 y 轴方向的缩放倍数。
transform: scale(<number>, <number>);
第一个参数表示元素沿 x 轴进行缩放的倍数,第二个参数表示元素沿着 y 轴进行缩放的倍数,取值范围可以是任意实数,需要注意对元素进行缩放时,整个盒子 mar gin 及以内的数据都会被影响,不过实际占位还是保持和原来一样,看下面这个例子。
.container {
  border: 1px solid;
  
  .elem {
    width: 100px;
    height: 100px;
    background: skyblue;
    transform: scale(2, 2); // 整个元素扩大两倍  
  }
}
整个元素看起来虽然扩大了两倍,但是它在文档流中的实际占位是没有改变的。

如果两个参数的取值不一值,那么就会导致元素失真,常见于 img 的缩放。

为了防止出现这个问题,你可以只传入一个参数,默认情况下第二个参数会和第一个参数保持一致。
最后,你还需要知道,取值是可以取负数的,效果就是让元素在对应方向进行镜面翻转,比如:
transform: scale(-2, 2);
会让元素在水平方向进行镜面翻转,等价于 transform: rotateY(180deg) scale(2)。

倾斜
transform: skewX(<angle>);
让元素沿 x 轴方向倾斜,参数即为倾斜角度,取正值时元素沿逆时针方向倾斜。
transform: skewY(<angle>);
让元素沿 y 轴方向倾斜,参数即为倾斜角度,取正值时元素沿顺时针方向倾斜。
transform: skew(<angle>, <angle>);
相当于 skewX 和 skewY 的简写,第一个参数表示元素 x 轴方向的倾斜角度,第二个参数表示元素 y 轴方向的倾斜角度,也可以只传入一个参数,默认第二个参数和第一个参数一致。
3D 形变函数
平移
transform: translateZ(<length>);
表示让元素沿着 z 轴方向平移,需要注意的是取值类型只能是 <length>,常用于遮照。
transform: translate3d(<length> | <percentage>, <length> | <percentage>, <length>);
相当于 translateX、translateY 和 translateZ 的简写。
旋转
transform: rotateX(<angle>);
让元素沿着 x 轴为旋转轴进行旋转。
transform: rotateY(<angle>);
让元素沿 y 轴为旋转轴进行旋转。
transform: rotateZ(<angle>);
让元素沿 z 轴为旋转轴进行旋转,行为和 rotate 函数一致。
transform: rotate3d(<number>, <number>, <number>, <angle>);
前三个参数表示旋转矢量 [x, y, z],每一项的取值范围是 [-1, 1] 之间的所有实数,如果是小数则最多两位小数的值有效,如果超过两位小数则视为 0,比如 0.001 则等价于 0,现在知道取值规则后,来看下旋转矢量的具体作用。
当旋转矢量中只存在一项非 0 取值,比如 [0, 0, 1]、[0, 1, 0] 和 [1, 0, 0]。
transform: rotate3d(0, 0, 1, 30deg); /* 等价于 rotateZ(30deg) */
transform: rotate3d(0, 1, 0, 30deg); /* 等价于 rotateY(30deg) */
transform: rotate3d(1, 0, 0, 30deg); /* 等价于 rotateX(30deg) */
当然,你也可以取负数,比如 [-1, 0, 0]。
transform: rotate3d(-1, 0, 0, 30deg); /* 等价于 rotateX(-30deg) */
需要注意,当旋转矢量中只存在一项非 0 取值,如果这一项的值为小数或者绝对值大于 1,并没有实际作用,效果等价于取 1 或者 -1。
transform: rotate3d(-0.1, 0, 0, 30deg); /* 等价于 rotateX(-30deg) */
transform: rotate3d(-100, 0, 0, 30deg); /* 等价于 rotateX(-30deg) */
当旋转矢量存在两项及以上的非 0 取值,比如 [1, 0, 0.1]、[1, 1, 1] 和 [-1, 0.5, 1],如果某一项是小数则沿该轴的旋转角度就会由该小数乘上第四个参数。
transform: rotate3d(1, 0, 0.1, 60deg); /* 等价于 rotateX(60deg) rotateZ(6deg) */
transform: rotate3d(1, 1, 1, 60deg); /* 等价于 rotateX(60deg) rotateY(60deg) rotateZ(60deg) */
transform: rotate3d(-1, 0.5, 1, 60deg); /* 等价于 rotateX(-60deg) rotateY(30deg) rotateZ(60deg) */
缩放
transform: scaleZ(<length>);
让元素沿 z 轴方向缩放指定倍数,实际上看不出啥效果。
transform: scale3d(<length>, <length>, <length>);
相当于 scaleX、scaleY 和 scaleZ 的简写。
转换相关的扩展属性
transform-origin
在前文中提到了使用 transform-origin 属性可以调整元素平面旋转中心点,实际上它的作用是设置形变的原点位置,默认值为 center,即形变原点位置处于元素中心,它的取值如下。
取一值
transform-origin: <length> | <percentage> | left | top | right | bottom | center;
对于 <length> 和 <percentage> 类型的取值,表示原点从元素左侧(可视区域的左边缘)的偏移量,其中百分比的计算值由元素宽度决定。

对于 left、top、right、bottom 和 center 关键字,原点分别位于元素的左边缘、上边缘、右边缘、下边缘和中心。

important
当原点处于元素边缘时,一定位于 可视区域的边缘(border 及以内),不会考虑 margin。
取两值
transform-origin: [<x-offset> | offset-keyword] [<x-offset> | offset-keyword]
第一个取值表示原点水平定位,对于偏移量关键字只能取水平方向的,即 left、center 和 right;
第二个取值表示原点垂直定位,对于偏移量关键字只能取垂直方向的,即 top、center 和 bottom。

下面看几个例子:
transform-origin: left top; /* 原点位于元素左上角 */
transform-origin: right bottom; /* 原点位于右下角 */
transform-origin: 50% top; /* 等价于 transform-origin: top */
取三值
transform-origin: [<x-offset> | offset-keyword] [<x-offset> | offset-keyword] [z-offset]
前两值的作用分别表示水平、垂直偏移,第三个值表示在 z 轴方向上的偏移,取值类型必须为 <length>。
应用
下面来看一下,修改了形变原点后,再使用形变函数,它们的行为有什么区别。默认情况下形变原点位于元素中心,即取值 center,现在我们令 transform-origin: left top,形变原点位于元素左上角。
平面旋转时元素就会绕着左上角进行旋转了。

3d 旋转时会绕着元素的左边缘和上边缘为轴线进行旋转。


元素进行缩放时,也会以左上角为原点进行缩放。

transform-style
transform-style: flat | preserve-3d;
该属性的作用是设置元素的 子元素 是位于 3D 空间 中还是 平面 中,默认值为 flat。
假如有如下这个结构的父子元素嵌套关系:
<div class="container">
  <span>container</span>
  <div class="child">child</div>
</div>
现在我们对内部对 child 进行 3d 旋转,因为默认情况下其父元素的 transform-style 为 flat,因此子元素旋转时并没有处于 3D 空间的旋转效果。

但是当我们给父元素设置了 transform-style: preserve-3d 后,其内部的子元素就位于 3D 空间中了,此时我们再对其进行 3d 旋转。

perspective
该属性用于开启元素使用 3d 形变函数时的透视效果,它有两种使用方式:
perspective: none | <length>,默认值为none,即使用 3d 形变函数时,不会开启元素的透视效果,如果取值为<length>时,则会开启透视效果,并且数值大小决定了观察者离z = 0时的距离;transform: perspective(<length>),它也可以作为形变函数来使用
perspective 与 perspecitve() 的区别
- 前者用于设置后代元素的透视效果
 - 后者是一个形变函数,需要配合 
transform属性一起使用,用于设置当前元素的透视效果,请注意如果想让透视效果生效,那么perspective()形变函数一定要放在第一个参数位置 
下面简单体会一下,透视效果对 3d 旋转的影响。
当没有开启透视效果时,进行 3d 旋转:

开启透视效果后,进行 3d 旋转:

important
另外还提供了 perspective-origin 属性用于指定观察者的位置,使用 perspective 和 perspective-origin 实际上就可以模拟一个 three.js 中的 camera 效果了。
backface-visibility
backface-visibility: visible | hidden;
该属性的作用就是用来设置一个元素背面是否可见,默认值为 visible,常用于 3d 旋转。
当取值为 visible 时,我们进行 3d 旋转,是可以看见一个元素的背面的。

但是设置为 hidden 后,就无法看见元素背面了。
