众所周知,transform 是 CSS3 中最强大的属性之一,它有这么三个函数属性值:scale、translate 和 rotate,它们分别是缩放、位移和旋转,但是你有没有想过有这么一天它们三个独立成为三个属性呢?
先来看效果,如果下面的元素不生效,那就证明浏览器该升级了:
代码片段
transform
说这三个属性之前,还是需要从transform
说起,因为它们三个最开始就是作为transform
的属性值,而不是属性。
这里我之前有写一篇关于transform
的实现原理的文章,对transform
的实现原理感兴趣的可以去看看卷一卷CSS的transform实现原理,头发又掉了10根!!!
当然这里的起因还是要从transform
的实现原理说起,当然原理上面的文章已经讲的很清楚了,这里就不再赘述了,直接说问题。
文章中写道这样一个案例,就是tanslate
和rotate
的组合,如果将他们书写顺序颠倒,那么就会出现不同的效果。
div {
transform: translate(100px, 100px) rotate(45deg);
}
/** or **/
div {
transform: rotate(45deg) translate(100px, 100px);
}
上面两个案例,如果将他们书写顺序颠倒,那么就会出现不同的效果。
其实这也不是什么大问题,我们记住规则就好了,但是有一个新的问题就是,transform
就一个属性,但是它的属性值却有很多;
例如我本来就将摸个元素平移了,现在我鼠标移上去又想旋转,那么我们写hover
的样式就会变成这样:
div {
transform: translate(100px, 100px);
}
div:hover {
transform: translate(100px, 100px) rotate(45deg);
}
这无疑增加了代码量,如果我还想缩放呢?如果这个代码之前不是我写的,是别人写的,我不知道他使用了transform
,那么我还得花时间去找,这样的代码是不是很不优雅?
现在这个问题就被scale
、translate
和rotate
解决了,它们三个都是独立的属性,现在我就来带你认识它们。
scale
scale
属性允许你独立的设置元素的缩放比例,同tranform: scale()
一样,它有两个值,一个是scaleX
,一个是scaleY
,分别是水平方向和垂直方向的缩放比例。
div {
transform: scale(2, 2);
}
/** 等同于 **/
div {
scale: 2 2;
}
它和tranform: scale()
在使用方式上和效果上是一样的,但是它是独立的属性,它的语法如下:
scale = none | [ <number> | <percentage> ]{1,3}
取值:
- none:表示不缩放
- 单一数值:表示水平和垂直方向的缩放比例,例如
scale: 2
,表示水平和垂直方向都缩放2倍 - 两个数值:表示水平和垂直方向的缩放比例,例如
scale: 2 3
,表示水平方向缩放2倍,垂直方向缩放3倍 - 三个数值:表示水平、垂直和深度方向的缩放比例,例如
scale: 2 3 4
,表示水平方向缩放2倍,垂直方向缩放3倍,深度方向缩放4倍,相当于tranform: scale3d(2, 3, 4)
translate
translate
属性允许你独立的设置元素的平移距离,同tranform: translate()
相同。
div {
transform: translate(100px, 100px);
}
/** 等同于 **/
div {
translate: 100px 100px;
}
它和tranform: translate()
在使用方式上和效果上是一样的,它的语法如下:
translate = none | <length-percentage> [ <length-percentage> <length>? ]?
<length-percentage> = <length> | <percentage>
取值:
- none:表示不平移
- 单个长度/百分比:表示水平方向的平移距离,例如
translate: 100px
,表示水平方向平移100px
,等同于tranform: translateX(100px)
,这里省略了垂直方向的值,所以垂直方向的值默认为0 - 两个长度/百分比:表示水平和垂直方向的平移距离,例如
translate: 100px 200px
,表示水平方向平移100px
,垂直方向平移200px
,等同于tranform: translate(100px, 200px)
- 三个长度/百分比:表示水平、垂直和深度方向的平移距离,例如
translate: 100px 200px 300px
,表示水平方向平移100px
,垂直方向平移200px
,深度方向平移300px
,相当于tranform: translate3d(100px, 200px, 300px)
rotate
rotate
属性允许你独立的设置元素的旋转角度,同tranform: rotate()
相同。
div {
transform: rotate(45deg);
}
/** 等同于 **/
div {
rotate: 45deg;
}
它和tranform: rotate()
在使用方式上和效果上是一样的,它的语法如下:
rotate = none | <angle> | [ x | y | z | <number>{3} ] && <angle>
取值:
- none:表示不旋转
- 单个角度:表示绕Z轴旋转的角度,例如
rotate: 45deg
,表示绕Z轴旋转45度,等同于tranform: rotateZ(45deg)
- 两个值:表示绕X轴、Y轴、Z轴旋转的角度,例如
rotate: 45deg 60deg
,表示绕X轴旋转45度,绕Y轴旋转60度,等同于tranform: rotate3d(1, 1, 0, 45deg)
,这里省略了Z轴的值,所以Z轴的值默认为0 - 三个值:表示加上向量的旋转角度,例如
rotate: 45deg 60deg 90deg
,表示绕X轴旋转45度,绕Y轴旋转60度,绕Z轴旋转90度,相当于tranform: rotate3d(1, 1, 1, 45deg)
使用示例
通常情况下我们难免会遇到同时使用transform
的多个属性值的情况,例如:
div {
transform: translate(100px, 100px) rotate(45deg);
}
现在有一个需求就是要让这个元素在鼠标悬浮的时候,开始旋转,并且还要有呼吸效果,这个时候我们只有两种解决方案:
- 方案1:将这几个属性聚合起来,使用
matrix
属性;好处就是只需要写一个属性,但是缺点就是这个属性的值非常复杂,而且不够直观,不利于维护。 - 方案2:还是使用多个属性值,一个一个的慢慢加;好处就是直观,但是缺点就是需要写多个属性,而且还要考虑属性值的顺序。
先来实现一下吧,这里使用方案2:
div:hover {
animation: animation 3s infinite alternate;
}
@keyframes animation {
0% {
transform: translate(100px, 100px) rotate(45deg) scale(0.8);
}
20% {
transform: translate(100px, 100px) rotate(90deg) scale(1.2);
}
40% {
transform: translate(100px, 100px) rotate(135deg) scale(0.8);
}
60% {
transform: translate(100px, 100px) rotate(180deg) scale(1.2);
}
80% {
transform: translate(100px, 100px) rotate(225deg) scale(0.8);
}
100% {
transform: translate(100px, 100px) rotate(270deg) scale(1.2);
}
}
可以看到上面的代码,我们需要写6个属性值,而且还要考虑属性值的顺序,这样的代码可读性和维护性都不是很好。
而且translate(100px, 100px)
这个值是不变的,但是我们还是每次都需要写,这样的代码也不够优雅。
现在我们就可以通过我上面讲到的scale
、rotate
、translate
这三个属性来优化一下:
div {
translate: 100px 100px;
rotate: 45deg;
}
div:hover {
animation: animation 3s infinite alternate;
}
@keyframes animation {
0% {
scale: 0.8;
}
20% {
rotate: 90deg;
scale: 1.2;
}
40% {
rotate: 135deg;
scale: 0.8;
}
60% {
rotate: 180deg;
scale: 1.2;
}
80% {
rotate: 225deg;
scale: 0.8;
}
100% {
rotate: 270deg;
scale: 1.2;
}
}
来看看上面的代码,我们只需要写3个属性值,而且还不需要考虑属性值的顺序,这样的代码可读性和维护性都会好很多。
兼容性
兼容性目前应该是我们最应该关注的问题,因为我们不可能只考虑最新的浏览器,而且兼容性也是我们最容易忽略的问题。
目前transform
属性的兼容性还是比较好的,但是translate
、rotate
、scale
这三个属性的兼容性就不是很好了,下面贴出caniuse
的兼容性表格:
scale
rotate
translate
可以看到,scale
、rotate
、translate
这三个属性的兼容性都不是很好,所以还是不要用在生产环境中,任重道远。