全面學習CSS3 transform 變形

第一部分:變形介紹

自層疊樣式表誕生以來,元素始終是矩形的,並且只能沿着橫軸和縱軸放置。有些技巧能讓元素看起來是傾斜的,可是底層的座標方格並無變形。CSS變形功能改變了這一現狀,能以不一樣的方式改變對象的形態,並且還不僅限於二維。css

不論你想要旋轉照片,翻轉元素等功能使用CSS的變形功能都能作到,CSS變形功能分爲2D和3D變形。html

CSS變形功能包括:git

  • 移動(translate)
  • 縮放(scale)
  • 旋轉(rotate)
  • 傾斜(skew)

第二部分:座標系

學習變形以前,先須要瞭解一下變形中的座標系。在CSS中,笛卡爾座標系使用三個軸表示(以下圖):github

  • x軸(橫軸)
  • y軸(縱軸)
  • z軸(深度軸)

變形功能表示笛卡爾座標系的三個軸

2D變形只須要關注x軸和y軸。web

x軸的正值在右側,負值在左側。y軸的正值沿縱軸向下,負值沿縱軸向上。回想一下定位元素的top屬性:值爲正數時元素下移,值爲負數時元素上移。瀏覽器

若是想把元素向左下方移動,要把x值設爲負數,把y值設爲正數:bash

transform: translateX(-5em) translateY(50px);
複製代碼

上面這個變形是有效的。上面代碼的做用是把元素向左移動5em,向下移動50像素。ide

3D變形不只須要關注x軸和y軸,還要加上z軸。函數

z軸從顯示器上躍出,指向你的眼前。z軸上的正值離你較近,負值離你較遠。定位元素的z-index屬性是和它徹底同樣的。post

在上面的基礎上再加個z軸值:

transform: translateX(-5em) translateY(50px) translateZ(200px);
複製代碼

與未指定z值相比,元素離咱們的距離近了200像素。如今還看不到效果,等介紹到3D變形的時候就會感覺到變化了。

2.1 移動參照物

每一個元素都有本身的參照物,各軸都相對自身而動。若是旋轉了元素,軸也隨之旋轉。旋轉以後再變形,是相對旋轉後的軸計算的,而不是顯示器的軸。以下圖:

CSS變形功能中使用的另外一個座標系——球座標系。這個座標系用於描述3D空間中的角度。以下圖:

在2D變形中只須要關注全周360度座標系,即由x軸和y軸構成的屏幕。對旋轉來講,2D旋轉實際上是在繞z軸旋轉。相似的,若是繞x軸旋轉,元素將偏向咱們或遠離咱們,而繞y軸旋轉的話,元素將向兩側旋轉,以下圖(須要仔細理解):

  • 繞x軸旋轉

  • 繞y軸旋轉

  • 繞z軸旋轉

在2D旋轉中,假設咱們要在顯示器屏幕上(即繞z軸)順時針旋轉一個元素45度,使用的變形值能夠是下面這樣的:

transform: rotate(45deg);
複製代碼

若是把值改成-45deg,元素將繞z軸軸逆時針旋轉。換句話說,元素在xy平面上旋轉。以下圖:

第三部分:變形語法和注意事項

變形其實只有一個屬性,可是有幾個輔助屬性用於控制如何變形。Transform使用以下表格:

Transform
取值 <transform-list> | none
初始值 None
適用於 除 「基元行內」框以外的全部元素
百分數 相對範圍框計算
計算值 指定的值,不過相對長度值會計算爲絕對長度
繼承性
動畫性 變形
說明:
  1. 範圍框:元素邊框的外邊界。也就是說,計算範圍框時,輪廓和外邊距不算在內。

  2. 變形的元素有本身的堆疊上下文。通過縮放的元素可能比變形前小或大,不過元素在頁面上所佔的空間與變形前保持不變。對全部變形函數都成立。

  3. <transform-list> | none 表示一個或多個變形函數,中間以空格分隔。如:transform: rotate(30deg) skewX(-25deg) scaleY(2);

  4. 變形函數一次只處理一個,從最左邊第一個開始,一直到最後一個。從頭至尾的處理順序很重要。順序變了,獲得的結果就有可能會不一樣。

  5. 有多個變形函數時,每一個都要設置正確,要確保所有有效。若是有一個函數是無效的,整個值都將失效。

  6. 變形一般不疊加。若是改變了元素的形態,然後再想添加一種變形,那麼要在原變形基礎上修改。就像你在一個地方聲明瞭字號,又在另外一個地方爲元素聲明瞭不一樣的字號同樣,字號是不疊加的。只有其中一個字號起做用。不過動畫變形除外,無論使用過渡仍是真正的動畫,效果是疊加的。

  7. 變形如今還不能應用到基元行內框上。基元行內框指span,超連接等行內框。這些元素能夠隨着塊級父元素一塊兒變形,可是不能直接旋轉。除非把它們的顯示方式改成display:block,display:inline-block等。

transform: translateX(200px) rotate(45deg);
transform: rotate(45deg) translateX(200px);
複製代碼

不一樣順序,不一樣結果

div {transform: translateX(100px) scale(1.2)};
div:hover {transform:rotate(-45deg)};
複製代碼

即便不顯式使用過渡或動畫,也能經過用戶交互僞類(如:hover)實現疊加變形。這是由於懸停等效果就是一種過渡,只不過不是由過渡屬性觸發的。所以能夠向上面這樣聲明變形屬性進行效果疊加。

變形函數

變形函數目前一共有21個。不一樣的變形函數利用不一樣格式的值實現相應的變形。

  1. translate()
  2. translate3d()
  3. translateX()
  4. translateY()
  5. translateZ()
  6. scale()
  7. scale3d()
  8. scaleX()
  9. scaleY()
  10. scaleZ()
  11. rotate()
  12. rotate3d()
  13. rotateX()
  14. rotateY()
  15. rotateZ()
  16. skew()
  17. skewX()
  18. skewY()
  19. matrix()
  20. matrix3d()
  21. perspective()

具體語法能夠參考這篇文章。很是詳細的介紹了每一個函數的具體用法。

第四部分:平移函數 translate()

平移函數沿一個軸或多個軸移動。

  • translateX()沿元素自身的x軸移動元素。
  • translateY()沿元素自身的y軸移動元素。
  • translateZ()沿元素自身的z軸移動元素。
函數 可取值
translateX(),translateY() <length> | <percentage>
translateZ() <length>
translate() [<length> | <percentage>][,<length> | <percentage>]?
translate3d() [<length> | <percentage>][<length> | <percentage>],[<length>]
4.1 translateX(),translateY()

translateX(),translateY()這兩個一般成爲「2D」平移函數,由於它們能上下移動元素,也能左右移動元素。可是不能沿着z軸先後移動元素。這兩個函數的值都是一個距離值,能夠是長度,也能夠是百分比。

translateX(200px)  <!--元素向右移動200像素-->
translateY(200px)  <!--元素向下移動200像素-->
複製代碼

若是值是百分數,移動距離相對元素自身的尺寸計算。

translateX(50%)  <!--元素向右移動自身尺寸的一半-->
複製代碼
4.2 translate()

若是想同時沿x軸和y軸移動,使用 translate()更方便。第一個值表明x軸,第二個值表明y軸。translate()translateX(),translateY()結合在一塊兒的做用是同樣的。

translate(2em) 等於translate(2em,0) 等於 translateX(2em)

平移例子

4.3 translateZ()

translateZ()沿z軸平移元素,即在第三個維度中移動元素。translateZ()只接受長度值。其實任何有關z軸的值都不可使用百分數。

4.4 translate3d()

translate3d()這個簡寫屬性能同時指定x軸,y軸,z軸的平移量。3D平移過程以下圖:

3D平移過程
圖中箭頭表示沿相應軸的移動,最終達到3D空間中的一點。與 translate()不一樣,若是 translate3d()的值少於3個,沒有假定的默認值。所以相似 translate3d(1em,-50px)操做是無效的,而不能假定爲 translate3d(1em,-50px,0)

第五部分:縮放函數 scale()

縮放變形能夠把元素放大或縮小。縮放函數的值都是無單位的實數,並且始終爲正數。在2D平面中,能夠分別在x軸或者y軸上縮放,也能夠同時在兩個軸上縮放。

函數 可取值
scaleX(),scaleY(),scaleZ() <number>
scale() <number>[,<number>]?
scale3d() <number>,<number>,<number>

提供給縮放函數的數字是個乘數,所以,scaleX(2)將把元素的寬度變爲變形前的兩倍,而scaleY(0.5)將把元素的高度縮小一半。若是想在兩個軸上同時縮放,使用scale()。第一個值是x值,第二個是y值。所以scale(2,0.5)將把元素的寬度放大兩倍,將元素的高度縮小一半。若是隻提供一個值,將用做兩個軸的縮放值。所以,scale(2)將把元素的寬度和高度都放大兩倍。這與translate()是不一樣的,在translate()中,省略的第二個值始終被設爲0。下面圖片展現了使用scale()的例子:

5.1 三維空間縮放

能在二維空間縮放,也就能在三維空間縮放。css提供的scalez()函數僅在z軸上縮放,而scale3d()則能同時在三個軸上縮放。固然,僅當元素有深度時,這兩個函數纔有效果,而元素在默認狀況下沒有深度。若是讓元素有必定的深度,例如繞x軸或y軸旋轉,那麼深度就能夠縮放。使用scalez()或者scale3d()均可以。

translate()同樣,scale3d()的三個數都必須是有效的。否則將致使所屬的整個變形值都失效。

第六部分:旋轉函數 rotate()

旋轉函數繞某個旋轉軸元素,或者繞3D空間中的一個向量旋轉元素。旋轉變形有四個簡單的函數,以及一個有些複雜,專門用於3D旋轉的函數。

函數 可取值
rotate(),rotateX(),rotateY(),rotateZ() <angle>

上面四個簡單的函數都只接受一個值:角度。角度以一個數字(可正可負)和一個有效的角度單位(deg,grad,rad和turn)來表示。若是數字超出來相應單位的常規範圍,將化爲範圍內的值。也就是說,437deg和77deg的效果是相同的,與-283deg的效果也是相同的。

可是僅當沒有任何形式的動畫,這樣的換算纔算等效的。若是以動畫的形式旋轉-20deg,元素稍微向左傾斜,而不轉動。若是以動畫的形式旋轉340deg,元素將向右轉動幾乎一週。這兩次動畫的最終狀態是同樣的,可是每次旋轉的過程是有差別的。

rotate()函數實施的是2D旋轉,是咱們最經常使用的旋轉方式。它的效果等同於rotateZ(),由於都是繞z軸旋轉(從顯示器射出來,直指你的眼睛)旋轉的。相似的,rotateX()繞x軸旋轉,使元素向你傾斜或者遠離你傾斜。rotateY()繞y軸旋轉元素,像門的開合同樣。以下圖效果:

上圖中有的例子涉及到3D效果。與後面章節的transform-styleperspective屬性配和才能達到的效果。這篇文章涉及的3D變形都是如此。若是隻應用如今提到的變形函數是得不到圖中所展現的效果的。

6.1 rotate3d()
函數 可取值
rotate3d() <number>,<number>,<number>,<angle>

若是你瞭解向量,能夠把向量理解爲座標空間中的箭頭。以下圖分別表明2維座標和3維座標的向量:

2維座標的向量

3D座標的向量

想在3D空間中旋轉元素,使用rotate3d()。前三個值指定3D空間中向量x,y和z的份量,第四個值是角度值,指定繞向量旋轉的量。

看個簡單的例子:rotate(45deg)用3D旋轉表示是 rotate3d(0,0,1,45deg)。這個向量在x軸和y軸上的大小是0,在z軸上的大小是1。也就是說,旋轉中心是z軸。元素將繞指定的向量旋轉45度。以下圖(包括繞x軸和y軸旋轉45度時應該提供給rotate3d()的函數的值):

上圖中rotate(45deg)在3D空間中,等價於rotate3d(0,0,1,45deg)。前三個數設定向量的三個份量,這個向量在x軸和y軸上的大小爲0。在z軸上的大小爲1。所以,這個向量在z軸上,指向正方向,即指向觀察者。若是看向量的原點,元素是順時針旋轉的。

相似的,rotateX(45deg)等價於rotate3d(1,0,0,45deg)。這個向量在x軸上,指向正方向(右方)。若是站在向量的的終點看向原點,元素繞向量順時針旋轉45度,所以,站在常規的觀察者位置上,元素的頂部遠離觀察者,元素的底部靠近觀察者。

假如說旋轉函數是rotate3d(-0.95,0.5,1,45deg)描述的向量。假設有個邊長200像素的立方體,那麼這個向量在x軸上的大小爲190像素,指向左方。在y軸上的大小爲100像素,指向下方。在z軸上的大小爲200像素,指向觀察者。這個向量從原點(0,0,0)指向(-190px,100px,200px)。以下圖:

這個向量就像一根金屬棒,穿過旋轉的元素。若是沿着向量向回看,元素順時針旋轉了45度。可是,因爲向量指向左下前方,所以旋轉後的元素左上角靠近觀察着,而右下角遠離觀察者。

rotate3d(1,1,0,45deg)rotateX(45deg) rotateY(45deg) rotateZ(0deg)不等效。

第七部分:傾斜函數 skew()

函數 可取值
skewX(),skewY() <angle>
skew() <angle>,[,<angle>]?

傾斜函數沿x軸或y軸傾斜元素。元素不能沿z軸或3D空間中的向量傾斜。

skewX(),skewY()使元素傾斜指定的角度。以下圖:

skew(a,b)的效果是經過矩陣運算實施2D傾斜的。下圖展現了幾個矩陣傾斜的例子。

第八部分:視域函數 perspective()

在3D空間中改變元素的形態時,基本上都要賦予元素必定的視域。視域爲元素賦予先後深度,而這深度能夠根據須要設定。

函數 可取值
perspective() <length>

設置較小的值獲得較極端的視角,設置較大的值獲得較溫和的視角。以下圖:

小於300px的視域值獲得的效果特別失真,大於2000px的值失真「十分溫和」,而500px到1000px以前的值產生「適中的視域」。下圖展現了相同旋轉角度下不一樣視域值獲得的結果。

視域值必須是正數,並且不能爲零。其餘值都將致使 perspective()函數被忽略。 perspective()函數在變形函數列表中的位置十分重要。若是想在變形函數列表中設定視域值,必定要把 perspective()函數放在首位,只要也要放在以來視域的變形以前。

重要:transform函數的編寫順序十分重要。 perspective()函數與後面介紹的 perspective屬性十分類似,可是兩者的用法徹底不一樣。通常來講,最好使用 perspective屬性,不過也有須要使用 perspective()函數的例外狀況。

第九部分:修改視域

視域其實由兩個屬性定義:一個定義視域屬性距離,至關於前面討論過的perspective()函數。另外一個定義視域的原點。

9.1:定義視域 perspective 屬性

perspective 屬性的值是一個長度,定義視域錐體的深度。這麼看來,它與前面討論的 perspective()函數相似,不過二者之間有重要區別。

perspective
取值 none | <length>
初始值 none
適用於 任何可變形的元素
計算值 絕對長度或者none
繼承性
動畫性

若是想建立特別深的視域,仿照變焦鏡頭的效果,能夠聲明perspective: 2500px。若是想讓深度淺一些,能夠聲明perspective: 200px

9.2: perspective 屬性與perspective()函數的區別
  • perspective()函數只爲目標元素定義視域,好比聲明perspective(800px) rotateY(45deg)。那麼只有應用這個規則的元素才能使用設定的視域。

  • perspective 屬性定義的視域深度應用到目標元素的全部子元素上。

這就是二者的重要區別。perspective 屬性建立的3D空間爲全部子元素共有,而perspective()函數只對目標元素有效果,並且要放在變形函數列表的開頭或前面,多數時候,應該使用perspective屬性。

9.3:移動視域原點 perspective-origin 屬性
perspective-origin
取值 [left |center |right |top |bottom |<percentage> |<length> ] | [left |center |right |top |bottom |<percentage> |<length> ] && [left |center |right |top |bottom |<percentage> |<length> ]]<length>?
初始值 50% 50%
適用於 任何可變形的元素
百分數 相對範圍框計算
計算值 計算爲一個百分數。值爲長度值時,計算爲絕對長度
繼承性
動畫性 <percentage>,<length>

perspective-origin 定義視線匯聚於哪一點。

下圖表示不一樣視域原點下的「標尺」(視域原點生效的前提是必須聲明perspective屬性):

第十部分:矩陣函數 matrix()

matrix()
取值 <number>[,<number>]{5,5}

css變形規範對matrix()函數作了嚴格規定:以6個值a-f肯定變換矩陣指定2D平面中的變形。

matrix()函數的有效值是6個以逗號分隔的數字。不能多,也不能少。數字能夠爲正或負。matrix()函數的值所用的句法十分複雜,描述的是元素變形後的最終狀態,能夠涵蓋其餘全部變形類型(旋轉,傾斜等)。最後,不多有人使用這個句法。

10.1 3D變形矩陣函數
matrix3d()
取值 <number>[,<number>]{15,15}

css變形規範對matrix3d()函數作了嚴格規定:以列主序排列一個4X4的齊次矩陣,用這個16個值指定3D變形。matrix3d()函數的值必須是16個以逗號分隔的數字,不能多也不能少。這些數字按列排列成一個4X4矩陣,第一列由第一組四個數構成,第二列由第二組四個數構成,以此類推。

本章只對矩陣函數進行簡單介紹。

第十一部分:移動原點 transform-origin

目前所見的變形有個共同點,都以元素的絕對中心爲變形的原點。例如,旋轉元素時,是繞着中心旋轉的,而不是繞着某一角度旋轉的。這是默認行爲,不過可使用transform-origin屬性修改。

transform-origin
取值 [left |center |right |top |bottom |<percentage> |<length> ] | [left |center |right |top |bottom |<percentage> |<length> ] && [left |center |right |top |bottom |<percentage> |<length> ]]<length>?
初始值 50% 50%
適用於 任何可變形的元素
百分數 相對範圍框計算
計算值 計算爲一個百分數。值爲長度值時,計算爲絕對長度
繼承性
動畫性 <percentage>,<length>

取值語法看似複雜,可是實際使用起來仍是不難的。transform-origin屬性的值爲兩個或三個關鍵字,用於定義相對哪一個點變形。第一個值針對橫向,第二個值針對縱向,可選的第三個值是z軸上的長度。

橫軸和縱軸可使用英語關鍵字,百分數,長度。而z軸不能使用英語關鍵字或百分數。不過可使用長度值。目前像素值是最經常使用的。

長度值設定的是距元素左上角的距離。因此,transform-origin: 5em 22px定義的變形原點距元素的左邊5em,距元素的頂邊22px。

百分數相對對應的軸和元素的尺寸計算。設定的是距元素左上角的偏移量。如:transform-origin: 67% 40%定義的元素距元素左邊的距離爲寬度的67%,距元素頂邊的距離爲高度的40%。以下圖:

加入咱們把一個元素向右旋轉45度,經過設置變形原點的位置,那麼元素的最終位置取決於變形原點。下圖展現了不一樣的變形原點獲得的結果。

變形原點對其餘變形類型也有影響,好比傾斜和縮放。以下圖:

有種變形不怎麼受變形原點的影響——平移。使用translate()移動元素,無論元素變形原點在哪,元素最終都被移動到相同的位置。

第十二部分:變形方式 transform-style

若是在一個三維空間中改變元素的形態,例如使用translate3d(),或許但願在3D空間中呈現元素。然而,這不是默認行爲。默認狀況下,無論怎麼變形,獲得的結果都是扁平的。可是可使用transform-style修改。

transform-style
取值 flat | preserve-3d
初始值 flat
適用於 任何可變形的元素
計算值 指定的值
繼承性
動畫性

假如咱們想在適中的視域下移動元素。使用下面css:

.inner {  
    transform: perspective(750px) translateZ(60px) rotateX(45deg); 
}
<div class="outer">
    <div class="inner">inner</div>
</div>

複製代碼

結果以下圖:

可是,若是向某一邊旋轉外層div,結果就與咱們設想的不同了:內層div像粘在外層div上的照片同樣,這與預期不符。由於transform-style默認值是flat。內層div的上部前傾,下部後靠,像是緊貼在外層div上的圖像,隨外層一塊兒旋轉。

.outer {  
    transform: perspective(750px) translateY(60px) rotateX(-20deg); 
}

.inner {  
    transform: perspective(750px) translateZ(60px) rotateX(45deg); 
}
<div class="outer">
    <div class="inner">inner</div>
</div>

複製代碼

結果以下圖:

然而,把值改爲preserve-3d後,結果就大相徑庭了。內層div繪製成一個3D對象,浮動在外層div附近,所以也就不緊貼在外層div上了。

.outer {  
    transform: perspective(750px) translateY(60px) rotateX(-20deg); 
    transform-style: perserve-3d;
}

.inner {  
    transform: perspective(750px) translateZ(60px) rotateX(45deg); 
}
<div class="outer">
    <div class="inner">inner</div>
</div>

複製代碼

改動後結果以下圖:

注意

transform-style設定的變形方式可能會被其餘屬性覆蓋。這是由於那些屬性的某些值要求元素及其子元素必須以扁平的方式呈現才能起做用。遇到這種狀況,無論你把transform-style設爲何值,都會被強制重置爲flat

爲了不被覆蓋,下面屬性要設爲給出的值(這些也都是屬性的默認值):

  • overflow: visible
  • filter: none
  • clip: auto
  • clip-path: none
  • mask-image: none
  • mask-border-source: none
  • mix-blend-mode: normal

若是忽然發現3D變形效果無效,根源就可能存在上述列表中的某個屬性上。

第十三部分:處理背面 backface-visibility

在3D變形中,backface-visibility屬性能夠看到元素的背面。

backface-visibility
取值 visible | hidden
初始值 visible
適用於 任何可變形的元素
計算值 指定的值
繼承性
動畫性

backface-visibility屬性決定元素的背面朝向咱們時是否渲染背面,僅此而已。

假設翻轉兩個元素,一個元素的backface-visibility屬性設置爲visible,另外一個設置爲hidden

一個簡單的卡片翻轉效果演示 backface-visibility 的使用:

.card {
  position: relative;
  perspective: 800px;
  transform-style: preserve-3d;
  width:200px;
  height:280px;
  transition: all .6s;
  border: 1px solid #000;
  border-radius: 4px;
}

.card:hover {
  transform: rotateY(180deg);
}
img {
  position: absolute;
  width:100%;
  height: 100%;
  transition: all .5s;
  backface-visibility: hidden;
}
/*因爲咱們將兩個圖像都藏在了背面,因此另外一面沒有任何東西。 因此接下來須要再把.front-face翻轉180度*/
.back-face {
  transform: rotateY(180deg);
}

<div class="card">
    <img class="front-face" src="1.jpg">
    <img class="back-face" src="2.jpg">
</div>

複製代碼

參考連接

連接若是打不開直接複製地址在瀏覽器打開

CSS權威指南(第四版)

從矩陣與空間操做的關係理解CSS3的transform

CSS 3D 旋轉 rotate3d 與 translate3d

www.bilibili.com/video/av673…

meyerweb.github.io/csstdg4figs…

htmldog.com/references/…

相關文章
相關標籤/搜索