搜尋

transform 轉換函式

透過 CSS 的 transform 樣式屬性,就能靈活運用和串接 translate()、translate3d()、rotate()、rotate3d()、scale3d()、skew()、matrix() 和 matrix3d() 等控制變形效果的 CSS 函式,在網頁中實現各種變形效果,這篇教學會介紹這些轉換函式的用法。

延伸閱讀:transform 3D 轉換與透視

快速導覽:

CSS 教學 - transform 轉換函式

CSS 的座標系統

使用 CSS 處理 transform 轉換時,會混用「笛卡爾座標系統」以及「球面座標系統」兩種座標系統,參考下圖,如果要將元素平移,會參考由 XYZ 三軸所組成笛卡爾座標系統 ( 黑色線 ),如果使用球面座標系統 ( 紅色線 ),則會讓元素繞著三個軸進行旋轉。

CSS 教學 - transform 轉換函式 - CSS 的座標系統

下圖使用四個 div 簡單展示兩種坐標系統。

CSS 教學 - transform 轉換函式 - CSS 的座標系統

transform 轉換

transform 是個可以「轉換元素外形」的樣式屬性,預設值為 none,沒有繼承特性,這個樣式會透過一些「CSS 轉換函式」,讓元素產生平移、旋轉、傾斜、尺寸改變等變形效果,下方列出相關的 CSS 函式:

CSS 轉換函式 說明
translate(x, y) 在 xy 兩軸上的平移。
translateX(d)translateY(d)translateZ(d) 分別在 xyz 三軸上的平移。
translate3d(x, y, z) 在 xyz 立體空間的平移。
rotate(deg) 繞著 z 軸的旋轉,順時鐘方向為正。
rotateX(deg)rotateY(deg)rotateZ(deg) 分別繞著 xyz 三軸旋轉,順時鐘方向為正。
rotate3d(x, y, z, deg) 在 xyz 立體空間中繞著 xyz 三軸旋轉,順時鐘方向為正。
scale(x, y) 在 xy 兩軸上的尺寸變化。
scaleX(d)scaleY(d)scaleZ(d) 分別在 xyz 三軸上的尺寸變化。
scale3d(x, y, z) 在 xyz 立體空間的尺寸變化。
skew(x, y) 在 xy 兩軸的傾斜角度。
skewX(deg)skewY(deg) 分別在 xy 兩軸的傾斜角度。
matrix(a, b, c, d, tx, ty) 在 xy 平面的矩陣轉換。
matrix3d(16 個參數) 在 xyz 立體空間的矩陣轉換。
perspective(d) 透視視角。

transform 的寫法中,除了可以單獨使用一個 CSS 轉換函式,也可以使用「串連」的方式,使用「空白」分隔每個轉換函式,讓元素「變形之後再次變形」,下方呈現單一函式、串連三個函式、五個函式的寫法:

div {
  transform: translate(x, y);
  transform: translate(x, y) scaleX(d) rotateY(deg);
  transform: translate(x, y) scaleX(d) rotateY(deg) skewX(ax) rotate(deg);
}

雖然同樣都用了平移和旋轉的函式,但因為「順序不同」,最後呈現的結果也有所不同,例如下方範例的兩組 div,「先移動再旋轉」的 div 會移動到左側之後再旋轉,但「先旋轉再移動」的 div 因為 x 軸已經轉了 90 渡,因此移動之後就會跑到下方

線上展示:https://codepen.io/oxxo/pen/GgKgjgv

<!-- HTML 程式碼-->
<div>原本位置</div><div class="a">oxxo</div><div class="b">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
  }
  .a, .b {  
    color: white;
    background: linear-gradient(to left, red, black);
  }
  .a {transform: translateX(150px) rotate(90deg);}  /* 先移動再旋轉 */
  .b {transform:  rotate(90deg) translateX(150px);} /* 先旋轉再移動 */
</style>

CSS 教學 - transform 變形轉換 - transform 轉換寫法「順序不同」呈現的結果也不同

translate() 平移

CSS 的平移函式有下列幾個,內容都是填入具有「長度單位」的數值,建議使用絕對長度單位,如果使用百分比為單位,則會乘以原本尺寸的寬或高。

CSS 平移函式 說明
translate(x, y) 在 xy 兩軸上的平移。
translateX(d)translateY(d)translateZ(d) 分別在 xyz 三軸上的平移。
translate3d(x, y, z) 在 xyz 立體空間的平移。

下方範例會使用 transform 搭配三種平移函式,移動三個 div 的位置。

線上展示:https://codepen.io/oxxo/pen/KwPwgwr

<!-- HTML 程式碼-->
<div>原本位置</div><div class="a">apple</div><div class="b">banana</div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
  }
  .a, .b, .c {color: white;}
  .a {
    transform: translate(150px, 0);
    background: #f55;
  }
  .b {
    transform: translateX(150px) translateY(150px);
    background: #0a0;
  }
  .c {
    transform: translate3d(0, 150px, 0);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - translate() 平移

操作過程中,因為操作 Z 軸的位移需要搭配「父元素的相機視角」才有反應,如果單純使用 Z 軸平移,會完全看不出效果,下方範例的紅色 div,因為缺少了父元素相機視角,不論有無設定 translateZ 數值都不會發生變化,但藍色與綠色 div 就會發生變形,越靠近使用者就越大,越遠就越小 ( 文字和邊框也會跟著縮放 )

參考:transform 3D 轉換與透視

線上展示:https://codepen.io/oxxo/pen/azozmOz

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b camera"><div>oxxo</div></div>
<div class="co"></div><div class="c camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    top: 100px;
  }
  body>div {position: absolute;}
  .ao, .bo, .co {z-index: 2;}          /* 這三個是顯示原本位置與大小 */
  .ao, .a {left: 20px;}
  .bo, .b.camera{left: 200px;}
  .co, .c.camera{left: 380px;}
  .camera {
    transform-style: preserve-3d;      /* 設定內容元素為同一組 */
    perspective:300px;                 /* 相機視角往後移動 300px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a {
    transform: translateZ(150px) translateX;
    background: #f55;
  }
  .b div {
    transform: translateZ(-150px);
    background: #0a0;
  }
  .c div {
    transform: translateZ(150px);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - translate() 操作 Z 軸的位移需要搭配「父元素的相機視角」

rotate() 旋轉

CSS 的旋轉函式有下列幾個,內容都是填入具有「角度單位」的數值。

CSS 旋轉函式 說明
rotate(deg) 繞著 z 軸的旋轉,順時鐘方向為正。
rotateX(deg)rotateY(deg)rotateZ(deg) 分別繞著 xyz 三軸旋轉,順時鐘方向為正。
rotate3d(x, y, z, deg) 在 xyz 立體空間中繞著 xyz 三軸旋轉,順時鐘方向為正。

下方範例會使用 transform 搭配三種旋轉函式,將三個 div 移動到不同的位置,當中 rotate3d(x, y, z, deg) 所使用的 xyz 數值為「後方 deg 的比例」,如果 deg 為 30,設定 0.5 就是 15 度,-2 就是 -60 度。

線上展示:https://codepen.io/oxxo/pen/jENEMPe

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">apple</div>
<div class="bo"></div><div class="b">banana</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}  /* 標記原始位置 */
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: rotate(50deg);
    background: #f55;
  }
  .b {
    transform: rotateZ(50deg);
    background: #0a0;
  }
  .c {
    transform: rotate3d(0, 0, 1, 50deg);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - rotate() 旋轉

操作過程中,如果要繞著 X 或 Y 軸的旋轉需要搭配「父元素的相機視角」才有反應,如果單純繞著 X 或 Y 軸旋轉,只會有高度或寬度縮放的效果 ( 類似看著一個方塊的「影子放大縮小」 ),下方範例的紅色 div,因為缺少了父元素相機視角,如果繞著 X 或 Y 軸旋轉只會有縮放效果,但藍色與綠色 div 就會發生變形,產生更為立體的旋轉效果 ( 文字和邊框也會跟著旋轉 )。

參考:transform 3D 轉換與透視

線上展示:https://codepen.io/oxxo/pen/JoPoRYG

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b camera"><div>oxxo</div></div>
<div class="co"></div><div class="c camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    top: 100px;
  }
  body>div {position: absolute;}         /* 這三個是顯示原本位置與大小 */
  .ao, .bo, .co {
    z-index: 2;
  }
  .ao, .a {  left: 20px;}
  .bo, .b.camera{  left: 180px;}
  .co, .c.camera{  left: 340px;}
  .camera {
    transform-style: preserve-3d;      /* 設定內容元素為同一組 */
    perspective: 100px;                /* 相機視角往後移動 100px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a {
    transform: rotateY(60deg);
    background: #f55;
  }
  .b div {
    transform: rotateY(60deg);
    background: #0a0;
  }
  .c div {
    transform: rotateX(60deg);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - rotate() 繞著 X 或 Y 軸的旋轉需要搭配「父元素的相機視角」

scale() 尺寸縮放

CSS 的尺寸縮放函式有下列幾個,內容都是填入「沒有單位的倍率」數值。

CSS 旋轉函式 說明
scale(x, y) 在 xy 兩軸上的尺寸變化。
scaleX(d)scaleY(d)scaleZ(d) 分別在 xyz 三軸上的尺寸變化。
scale3d(x, y, z) 在 xyz 立體空間的尺寸變化。

下方範例會使用 transform 搭配三種尺寸縮放函式,將三個 div 縮放為相同的大小。

線上展示:https://codepen.io/oxxo/pen/PwYwGPE

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">apple</div>
<div class="bo"></div><div class="b">banana</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}  /* 標記原始位置尺寸 */
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: scale(1.5);
    background: #f55;
  }
  .b {
    transform: scaleX(1.5) scaleY(1.5);
    background: #0a0;
  }
  .c {
    transform: scale3d(1.5, 1.5, 1);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - scale() 尺寸縮放

由於網頁元素本身沒有「厚度」( Z 軸尺寸 ),只有將多個不同 Z 軸位置的元素組合後,才會產生 Z 軸方向的厚度,因此如果要針對 Z 軸縮放,就需要額外設定「父元素場景」以及「場景的父元素的相機視角」,下方範例的紅色 div,因為缺少了場景與父元素相機視角,呈現效果仍然會是平面效果,但另外兩個 div 是由場景和元素所構成,就可以看見設定 scaleZ() 之後,對於厚度產生了影響。

參考:transform 3D 轉換與透視

線上展示:https://codepen.io/oxxo/pen/mybyrVM

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a">oxxo</div>
<div class="bo"></div>
<div class="b camera">
  <div class="space">
    <div>oxxo</div><div>oxxo</div>
  </div>
</div>
<div class="co"></div>
<div class="c camera">
  <div class="space">
    <div>oxxo</div><div>oxxo</div>
  </div>
</div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    position: absolute;
  }
  body>div {top: 100px;}
  .ao, .bo, .co {
    z-index: 2;
  }
  .ao, .a {left: 20px;}
  .bo, .b.camera{left: 180px;}
  .co, .c.camera{left: 340px;}
  .camera {
    perspective: 100px;                  /* 相機視角 */
    perspective-origin:center center;
  }
  .a {
    transform:  rotateY(60deg) scaleZ(1.5);
    background: #f55;
  }
  .b .space {
    transform-style: preserve-3d;
    transform: rotateY(60deg) scaleZ(1.5);  /* 整個場景旋轉和縮放 */
    border: none;
  }
  .b .space div:nth-child(1) {
    transform: translateZ(20px);            /* 場景內容元素調整位置 */
    background: #0a0;
  }
  .b .space div:nth-child(2) {
    transform: translateZ(-20px);           /* 場景內容元素調整位置 */
    background: #0a0;
  }

  .c .space {
    transform-style: preserve-3d;
    transform: rotateY(60deg) scaleZ(0.5);  /* 整個場景旋轉和縮放 */
    border: none;
  }
  .c .space div:nth-child(1) {
    transform: translateZ(20px);            /* 場景內容元素調整位置 */
    background: #09f;
  }
  .c .space div:nth-child(2) {
    transform: translateZ(-20px);           /* 場景內容元素調整位置 */
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - scaleZ() 額外設定「父元素場景」以及「場景的父元素的相機視角」

skew() 傾斜

CSS 的尺寸縮放函式有下列幾個,內容都是填入「傾斜的角度」數值。

CSS 旋轉函式 說明
skew(x, y) 在 xy 兩軸的傾斜角度。
skewX(deg)skewY(deg) 分別在 xy 兩軸的傾斜角度。

下方範例會使用 skew 搭配傾斜函式,將三個 div 傾斜為不同的角度。

線上展示:https://codepen.io/oxxo/pen/pvzvEgG

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">apple</div>
<div class="bo"></div><div class="b">banana</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 100px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: skew(30deg, 30deg);
    background: #f55;
  }
  .b {
    transform: skewX(30deg);
    background: #0a0;
  }
  .c {
    transform: skewY(30deg);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - skew() 傾斜

matrix() 2D 矩陣

matrix() 是透過「矩陣」讓元素進行「2D 變換」的轉換公式matrix() 具有六個參數,這六個參數會組成 2x3 的矩陣,雖然 matrix() 在表面上是 2x3 矩陣,但本質其實是 3x3 的矩陣,因為 matrix() 是針對 xy 平面的函式,在 Z 軸的參數保持不變的狀況下,可直接使用 2x3 矩陣進行運算。

CSS 教學 - transform 變形轉換 - matrix() 矩陣本質是 3x3 的矩陣

matrix() 的六個參數都有各自的意義,分別對應平移、旋轉、縮放和傾斜的函式,對照公式如下:

matrix 寫法 對照其他轉換函式
matrix(1, 0, 0, 1, x, y) translate(x, y)
matrix(cos(deg), sin(deg), -sin(deg), cos(deg), 0, 0) rotate(deg)
matrix(a, 0, 0, b, 0, 0) scale(a, b)
matrix(1, tan(y_deg), tan(x_deg), 1, 0, 0) skew(x_deg, y_deg) ( 注意 x 和 y 的位置 )

使用 matrix() 時不需要數值單位,會自動轉換成「絕對長度」、「放大倍率」和「角度」,下方範例透過 matrix() 函式,產生平移、旋轉、縮放和傾斜的效果。

線上展示:https://codepen.io/oxxo/pen/ogvgzxz

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a">oxxo</div>
<div class="bo"></div>
<div class="b">oxxo</div>
<div class="co"></div>
<div class="c">oxxo</div>
<div class="do"></div>
<div class="d">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    left: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {top: 50px;}
  .bo, .b {top: 180px;}
  .co, .c {top: 310px;}
  .do, .d {top: 440px;}
  .a {
    transform: matrix(1, 0, 0, 1, 50, -20);
    /* 等同 transform: translate(50px, -20px); */
    background: #f55;
  }
  .b {
    transform: matrix(0.707, 0.707, -0.707, 0.707, 0, 0);
    /* 等同 transform: rotate(45deg); */
    /* sin(45deg)=0.707    cos(45deg)=0.707 */
    background: #f90;
  }
  .c {
    transform: matrix(1.5, 0, 0, 0.8, 0, 0);
    /* 等同 transform: scale(1.5, 0.8); */
    background: #0a0;
  }
  .d {
    transform: matrix(1, 0.577, 0.577, 1, 0, 0);
    /* 等同 transform: skew(30deg, 30deg); */
    /* tan(30deg)=0.577 */
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - matrix() 2D 矩陣

如果要「串連多個轉換函式」,矩陣的處理就必須要擴展為 3x3 的矩陣運算,透過「矩陣的相乘」就能計算出最後的結果 ( 可使用「矩陣計算機」)。

CSS 教學 - transform 變形轉換 - matrix() 矩陣的相乘

下方範例會根據上圖的計算結果,讓三個 div 分別使用「串聯四種轉換函式」、「四個 matrix()」以及「計算後成為單一個 matrix() 函式」的三種方式,產生出完全相同的效果。

線上展示:https://codepen.io/oxxo/pen/wBwBzGj

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a">oxxo</div>
<div class="bo"></div>
<div class="b">oxxo</div>
<div class="co"></div>
<div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 80px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {left: 50px;}
  .bo, .b {left: 180px;}
  .co, .c {left: 310px;}
  .a {
    transform: translate(20px, 50px)
               scale(1.2, 1.2)
               rotate(45deg)
               skew(30deg, 30deg);
    background: #f55;
  }
  .b {
    transform: matrix(1, 0, 0, 1, 20, 50) 
               matrix(1.2, 0, 0, 1.2, 0, 0) 
               matrix(0.707, 0.707, -0.707, 0.707, 0, 0)
               matrix(1, 0.577, 0.577, 1, 0, 0);
    background: #f90;
  }
  .c {
    transform: matrix(0.359, 1.338, -0.359, 1.338, 20, 50);
    background: #0a0;
  }
</style>

CSS 教學 - transform 變形轉換 - 計算後成為單一個 matrix() 函式

matrix3d() 3D 矩陣

matrix3d() 是透過「矩陣」讓元素進行「3D 變換」的轉換公式*,matrix3d() 具有 16 個參數,這六個參數會組成 4x4 的矩陣。

CSS 教學 - transform 變形轉換 - matrix3d() 3D 矩陣

matrix3d() 的 16 個參數都有各自的意義,平移對照公式如下:

div {
  transform: matrix3d( 1,   0,   0,   0,
                       0,   1,   0,   0,
                       0,   0,   1,   0,
                       x,   y,   z,   1);
  /* 等同 transform: transform: translate3d(x, y, z); */
}

尺寸縮放對照公式如下:

div {
  transform: matrix3d( x,   0,   0,   0,
                       0,   y,   0,   0,
                       0,   0,   z,   0,
                       0,   0,   0,   1);
  /* 等同 transform: transform: scale3d(x, y, z); */
}

旋轉對照公式如下:

div {
  transform: matrix3d( 1,         0,          0,   0,
                       0,  cos(deg),   sin(deg),   0,
                       0, -sin(deg),   cos(deg),   0,
                       0,         0,          0,   1);
  /* 等同 transform: transform: rotateX(deg); 繞 x 旋轉 */

  transform: matrix3d( cos(deg),   0,  -sin(deg),   0,
                              0,   1,          0,   0,
                       sin(deg),   0,   cos(deg),   0,
                              0,   0,          0,   1);
  /* 等同 transform: transform: rotateY(deg); 繞 y 旋轉 */

  transform: matrix3d( cos(deg),   sin(deg),   0,   0,
                      -sin(deg),   cos(deg),   0,   0,
                              0,          0,   1,   0,
                              0,          0,   0,   1);
  /* 等同 transform: transform: rotateZ(deg); 繞 z 旋轉 */
}

傾斜對照公式如下:

div {
  transform: matrix3d( 1,          tan(y_deg),   0,   0,
                       tan(x_deg),          1,   0,   0,
                       0,                   0,   1,   0,
                       0,                   0,   0,   1);
  /* 等同 transform: transform: skew(x_deg, y_def); */
}

使用 matrix3d() 時不需要數值單位,會自動轉換成「絕對長度」、「放大倍率」和「角度」,下方範例透過 matrix() 函式,產生平移、旋轉、縮放和傾斜的效果。

線上展示:https://codepen.io/oxxo/pen/yyByaOw

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a camera"><div>oxxo</div></div>
<div class="bo"></div>
<div class="b camera"><div>oxxo</div></div>
<div class="co"></div>
<div class="c camera"><div>oxxo</div></div>
<div class="do"></div>
<div class="d camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    left: 100px;
  }
  body>div {position: absolute;}       /* 這四個是顯示原本位置與大小 */
  .ao, .bo, .co {z-index: 2;}
  .ao, .a.camera {top: 50px;}
  .bo, .b.camera {top: 180px;}
  .co, .c.camera {top: 310px;}
  .do, .d.camera {top: 440px;}
  .camera {
    perspective: 100px;                /* 相機視角往後移動 100px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a div {
    transform: matrix3d( 1,    0,    0,  0,
                         0,    1,    0,  0,
                         0,    0,    1,  0,
                        20,   20,  -20,  1);
    /* 等同 transform: translate3d(20px, 20px, -20px); */
    background: #f55;
  }
  .b div {
    transform: matrix3d( 2,      0,      0,  0,
                         0,    0.8,      0,  0,
                         0,      0,    0.5,  0,
                         0,      0,      0,  1);
    /* 等同 transform: scale3d(2, 0.8, 0.5); */
    background: #0a0;
  }
  .c div {
    transform: matrix3d( 1,       0,       0,  0,
                         0,   0.707,   0.707,  0,
                         0,  -0.707,   0.707,  0,
                         0,       0,       0,  1);
    /* 等同 transform: rotateX(45deg); */
    background: #09f;
  }
  .d div {
    transform: matrix3d(    1,   0.268,   0,  0,
                        0.268,       1,   0,  0,
                            0,       0,   1,  0,
                            0,       0,   0,  1);
    /* 等同 transform: skew(15deg, 15deg); */
    background: #f90;
  }
</style>

CSS 教學 - transform 變形轉換 - matrix3d() 3D 矩陣

如果要「串連多個轉換函式」,matrix3d() 可以像 matrix() 一樣,透過「矩陣的相乘」計算出最後的結果,但需要特別注意 CSS 的 matrix3d() 矩陣在計算時會先進行「轉置矩陣」,計算完成後再透過轉置矩陣轉回原本的格式 ( 使用「矩陣計算機」)。

CSS 教學 - transform 變形轉換 - matrix3d() 矩陣相乘需要進行矩陣轉置

下方範例會根據上圖的計算結果,讓三個 div 分別使用「串聯三種轉換函式」、「三個 matrix3d()」以及「計算後成為單一個 matrix3d() 函式」的三種方式,產生出完全相同的效果。

線上展示:https://codepen.io/oxxo/pen/VYZYKjp

<!-- HTML 程式碼-->
<div class="ao"></div>
<div class="a camera"><div>oxxo</div></div>
<div class="bo"></div>
<div class="b camera"><div>oxxo</div></div>
<div class="co"></div>
<div class="c camera"><div>oxxo</div></div>

<!-- CSS 程式碼 -->
<style>
  div {
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    color: white;
    left: 50px;
  }
  body>div {position: absolute;}         /* 這三個是顯示原本位置與大小 */
  .ao, .bo, .co {z-index: 2;}
  .ao, .a.camera {top: 50px;}
  .bo, .b.camera {top: 200px;}
  .co, .c.camera {top: 350px;}
  .camera {
    perspective: 100px;                /* 相機視角往後移動 100px */
    perspective-origin:center center;  /* 攝影機對齊中心 */
  }
  .a div {
    transform: translate3d(20px, 20px, 10px) rotateZ(30deg) rotateY(30deg);
    background: #f55;
  }
  .b div {
      transform: matrix3d( 1,    0,   0,  0,
                           0,    1,   0,  0,
                           0,    0,   1,  0,
                          20,   20,  10,  1)
                matrix3d( 0.866,    0.5,   0,  0,
                           -0.5,  0.866,   0,  0,
                              0,      0,   1,  0,
                              0,      0,   0,  1)
                matrix3d( 0.866,   0,   -0.5,  0,
                              0,   1,      0,  0,
                            0.5,   0,  0.866,  0,
                              0,   0,      0,  1);
    background: #0a0;
  }
  .c div {
      transform: matrix3d( 0.75,   0.433,   -0.5,  0,
                          -0.5,   0.866,      0,  0,
                          0.433,    0.25,  0.707,  0,
                            20,      20,     10,  1);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - 計算後成為單一個 matrix3d() 函式

perspective() 透視距離

perspective() 可以設定「元素和使用者之間的距離」,距離使用「大於 1px」並具有「長度單位」的數值,當距離越大時,元素的「透視變形程度」就越小,當距離越小時,元素的「透視變形程度」就越大,如果設定為 none 表示距離無限遠,不會發生透視變形的狀況,下圖為 W3C 所定義的規範,d 為透視距離,Z 為元素本身在 Z 軸的位移,若 d 小於 1px 會直接使用 1px 作為數值。

CSS 教學 - transform 變形轉換 - W3C perspective() 透視距離

下方範例會呈現 100px、50px 和 none 的透視變形差異,雖然都繞著 X 軸旋轉,但因為透視變形的關係,看到的效果就會不同,類似使用「望遠鏡頭」和「廣角鏡頭」所拍攝的照片差異。

線上展示:https://codepen.io/oxxo/pen/XJrmrwg

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b">oxxo</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    top: 100px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {left: 40px;}
  .bo, .b {left: 200px;}
  .co, .c {left: 360px;}
  .a {
    transform: perspective(100px) rotateX(30deg);
    background: #f55;
  }
  .b {
    transform: perspective(60px) rotateX(30deg);
    background: #0a0;
  }
  .c {
    transform: perspective(none) rotateX(30deg);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - perspective() 透視距離

因為 perspective() 屬於 CSS 的函式,在 transform 使用時需要注意「串連函式」的「順序」,如果將 perspective() 擺在其他轉換函式的後方,會因為串連的緣故,前方的轉換都不會套用透視效果,加上每個元素如果都有自己的透視距離,在視覺上會顯得不協調,建議參考「transform 3D 轉換與透視」,使用整體的透視效果會更好。

下方範例將 perspective() 擺在其他轉換函式的後方,呈現時就會沒有效果 ( 後方又有函式時,就會套用透視進行轉換 )

線上展示:https://codepen.io/oxxo/pen/JoPYjjL

<!-- HTML 程式碼-->
<div class="ao"></div><div class="a">oxxo</div>
<div class="bo"></div><div class="b">oxxo</div>
<div class="co"></div><div class="c">oxxo</div>

<!-- CSS 程式碼 -->
<style>
  div {
    position:absolute;
    width: 100px;
    height: 100px;
    border: 1px solid #000;
    left: 50px;
  }
  div:nth-of-type(2n+1) {z-index: 2;}
  .a, .b, .c {color: white;}
  .ao, .a {top: 50px;}
  .bo, .b {top: 180px;}
  .co, .c {top: 310px;}
  .a {
    transform: rotateX(30deg) rotateX(30deg) perspective(100px);
    background: #f55;
  }
  .b {
    transform: rotateX(30deg) perspective(100px) rotateX(30deg) ;
    background: #0a0;
  }
  .c {
    transform: perspective(100px) rotateX(30deg) rotateX(30deg);
    background: #09f;
  }
</style>

CSS 教學 - transform 變形轉換 - perspective() 只會對後方轉換函式有作用

小結

目前幾乎所有的瀏覽器都支援 transform 樣式屬性以及相關的 CSS 轉換函式,只要輕鬆轉寫幾行 CSS,就能實現許多有趣又吸睛的視覺效果。

繼續閱讀:transform 3D 轉換與透視

意見回饋

如果有任何建議或問題,可傳送「意見表單」給我,謝謝~

CSS 教學

基本介紹

認識 CSS 開始使用 CSS CSS 語法規則 CSS 命名原則

CSS 選擇器

認識 CSS 選擇器 優先順序 ( 權重 ) 樣式繼承與聯集 元素選擇器 ID 和 Class 選擇器 屬性選擇器 文件結構選擇器 虛擬類別選擇器 ( 結構 ) 虛擬類別選擇器 ( 類型 ) 虛擬類別選擇器 ( 輸入 ) 虛擬類別選擇器 ( 行為 ) 虛擬類別選擇器 ( 超連結 ) 虛擬類別選擇器 ( 邏輯 ) 虛擬類別選擇器 ( 其他 ) 虛擬元素選擇器 群組與組合選擇器

數值與單位

關鍵字與文字數值 長度與角度單位 顏色單位 位置名稱與時間單位

變數與內容函式

變數 數學計算 文字與清單計數 生成內容與引號

顏色與濾鏡

色彩模型 漸層色 影像濾鏡

文字樣式

使用通用字型 使用外部字型 @font-face 定義字型 文字尺寸 常用文字樣式 文字換行 文字空白與 Tab 大小 文字行高與縮排 文字水平與垂直對齊 文字書寫方向 特殊文字樣式

元素容器

容器顯示類型 ( display ) 元素 display 對照表 盒子模型 ( Box Model ) 寬度與高度 內邊距 ( padding ) 外邊界 ( margin ) 邊框 ( border ) 邊框圓角 影像邊框 輪廓 ( outline ) 可見性與透明度 內容溢出與裁切

背景與陰影

背景顏色 背景圖 ( 定位、尺寸 ) 背景圖 ( 固定、重複 ) 背景圖 ( 多重背景、混合 ) 背景縮寫 ( background ) 容器陰影 ( box-shadow )

清單與表格

清單樣式 清單計數器 定義計數規則 表格基本樣式 表格邊框樣式 表格內容寬度與對齊

基本排版與定位

元素排版方式 浮動 ( float ) 浮動形狀 定位 ( position )

Flexbox 彈性排版

Flexbox 彈性盒子 Flexbox 對齊方式 Flexbox 彈性伸縮

Grid 網格排版

Grid 網格容器與格線 Grid 網格空間與命名 Grid 網格流向與間距 Grid 排列網格項目 Grid 項目對齊與順序

轉場與動畫

轉場 ( transition ) 轉場觸發事件 動畫 ( animation ) 動畫觸發事件 多重動畫的權重與順序

變形、裁切與遮罩

裁切路徑 ( clip-path ) 影像遮罩 ( mask ) 物件填滿方式與定位 轉換函式 ( transform ) 3D 轉換與透視