關於CSS中的 3D transform

Created: 2024/6/20
Updated: 2025/10/14

記錄了關於CSS中的3D transform一些觀念並練習


最近在練習關於css 3d的部分,將一些心得作為筆記。

這篇我將介紹如何使用 CSS 的 transform 屬性來模擬 3D 效果,並探討transform-style對元素子層的影響。

透視效果

perspective 屬性用於在 2D 平面上模擬 3D 形狀,給使用者提供深度感(即 Z 軸)。透視值越大,表示物體離我們越遠,深度感也越強。使用方法如下:

transform: perspective(800px);

這段 CSS 設置會讓元素看起來像是在 800px 的距離之外觀看。調整這個值可以控制視覺深度。

3D 變換樣式

transform-style屬性決定了一個元素的子元素是否保留其在 3D 空間中的定位。這對於創建複雜的 3D 結構至關重要。

  • flat (預設值): 子元素將不會獨立存在於 3D 空間中,它們會被扁平化並平鋪在父元素的 2D 平面上。
  • preserve-3d (用於 3D 結構) 子元素將保持其獨立的 3D 位置與轉換狀態。若父元素未設定此值,子元素的 3D 轉換將無法生效。

可用值如下:

transform-style: flat;
 
transform-style: preserve-3d;

撰寫類似旋轉木馬的 Slider

我們將實現一個簡易的 3D 旋轉木馬效果的 Slider,並添加動畫效果。

步驟 1:設置基礎結構

首先,我們需要設置基本的 HTML 結構和 CSS 樣式。

我們使用 CSS 變數(--quantityvar(--position))來定義總項目數和每個項目的位置。

<div class="wrapper">
  <div class="slider" style="--quantity: 6">
    <div class="item" style="--position: 1">
      <div class="content">1</div>
    </div>
    <div class="item" style="--position: 2">
      <div class="content">2</div>
    </div>
    <div class="item" style="--position: 3">
      <div class="content">3</div>
    </div>
    <div class="item" style="--position: 4">
      <div class="content">4</div>
    </div>
    <div class="item" style="--position: 5">
      <div class="content">5</div>
    </div>
    <div class="item" style="--position: 6">
      <div class="content">6</div>
    </div>
  </div>
</div>

步驟 2:設置基本樣式

設定外層容器 (.wrapper)、Slider 容器 (.slider) 和項目 (.item) 的尺寸與定位。我們將 Slider 容器置於畫布中央,並讓所有項目堆疊在同一個位置。

.wrapper {
  width: 100%;
  height: 80vh;
  overflow: hidden;
  position: relative;
}
 
.wrapper .slider {
  width: 200px;
  height: 250px;
  left: calc(50% - 100px);
}
 
.wrapper .slider .item {
  position: absolute;
  inset: 0;
}
 
.wrapper .slider .item .content {
  width: 100%;
  height: 100%;
  background-color: red;
}

步驟 3:添加 3D 效果

使用 perspectivetransform-style 屬性來實現 3D 效果。修改slider和item

.wrapper .slider {
  width: 200px;
  height: 250px;
  left: calc(50% - 100px);
  transform-style: preserve-3d;
  transform: perspective(2500px);
}

接著transform,添加z軸,以及y軸轉的角度

.wrapper .slider .item {
  position: absolute;
  inset: 0 0 0 0 ;
  /* 使用 CSS 變數計算每個項目的位置 */
  transform: 
    rotateY(calc((var(--position) - 1) * (360 / var(--quantity)) * 1deg))
    translateZ(450px);
}

calc((var(--position) - 1) * (360 / var(--quantity)) * 1deg) 這段運算的目的是將 N 個quantity均勻地分佈在 360∘ 的圓周上。

參數數值意義目的
360 / var(--quantity)間隔角度計算每個項目之間的固定角度間隔。例如,有 6 個項目,間隔為 360/6=60∘。
var(--position) - 1序號修正這是項目的索引。由於第一個項目 (--position: 1) 應從 0∘ 開始,因此需減去 1。
rotateY(...)Y 軸旋轉根據計算出的角度,將項目圍繞中心軸旋轉,使其面向圓周外側。
translateZ(450px)Z 軸平移(半徑)這是圓柱體的半徑。它將項目沿 Z 軸向外推出 450 像素,使其在旋轉後不會堆疊在中心點,而是形成一個圓。

Example:

  • 項目 1 (--position: 1)(11)×60=0(1-1) \times 60^\circ = 0^\circ
  • 項目 2 (--position: 2)(21)×60=60(2-1) \times 60^\circ = 60^\circ
  • 項目 6 (--position: 6)(61)×60=300(6-1) \times 60^\circ = 300^\circ

步驟 4:添加動畫效果

最後,我們為 .slider 容器添加一個無限的旋轉動畫 (autoRun),讓整個旋轉木馬持續運行。我們在 to 狀態中將 rotateY 設置為 360∘,實現一圈完整的旋轉。

.wrapper .slider {
  width: 200px;
  height: 250px;
  left: calc(50% - 100px);
  transform-style: preserve-3d;
  transform: perspective(2500px);
  animation: autoRun 20s linear infinite;
}
 
@keyframes autoRun {
  from {
    transform: perspective(2500px) rotateX(-16deg) rotateY(0deg);
  }
  to {
    transform: perspective(2500px) rotateX(-16deg) rotateY(360deg);
  }
}

接著一個簡單的 3D 旋轉木馬效果的 Slider就實現了。