在傳統網頁設計中,我們常常需要依賴JavaScript來實現複雜的動態佈局效果。但隨着現代CSS的發展,尤其是CSS Values and Units Level 4規範中引入的sin()cos()tan()等數學函數,我們現在可以直接使用純CSS創建出更加智能和靈活的佈局方案。

為什麼要在佈局中使用三角函數?

三角函數能夠描述元素間的相對位置關係和週期性變化。通過它們,我們可以:

  • 創建自然的曲線和圓形佈局
  • 實現基於角度的動畫效果
  • 構建響應式且比例協調的設計系統
  • 減少對硬編碼數值的依賴

讓我們看看幾個實用的應用場景。

1. 圓形菜單佈局

傳統的圓形菜單通常需要使用JavaScript計算每個菜單位置單位置,現在用CSS就能輕鬆搞定:

.menu-container {
  position: relative;
  width: 300px;
  height: 300px;
}

.menu-item {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 50px;
  height: 50px;
  
  /* 默認定位到中心 */
  transform: translate(-50%, -50%);
}

/* 為每個菜單項設置不同角度 */
.menu-item:nth-child(1) { --angle: 0deg; }
.menu-item:nth-child(2) { --angle: 60deg; }
.menu-item:nth-child(3) { --angle: 120deg; }
.menu-item:nth-child(4) { --angle: 180deg; }
.menu-item:nth-child(5) { --angle: 240deg; }
.menu-item:nth-child(6) { --angle: 300deg; }

/* 應用三角函數計算位置 */
.expanded .menu-item {
  --radius: 100px; /* 展開半徑 */
  transform: 
    translate(
      calc(cos(var(--angle)) * var(--radius) - 50%),
      calc(sin(var(--angle)) * var(--radius) - 50%)
    );
}

這種方法的優勢在於:

  • 完全響應式 - 只需調整--radius變量即可改變整個佈局大小
  • 易於維護 - 添加或刪除菜單項無需重新計算位置
  • 性能更好 - 瀏覽器可以優化CSS計算

2. 波形背景與分隔線

利用正弦函數創建自然波動的視覺效果:

.wave-separator {
  height: 80px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--primary-color) 100%
  );
  mask: radial-gradient(
    50% 20px at 50% 100%,
    #000 99%,
    transparent 101%
  );
}

/* 更復雜的複雜的波浪效果 */
.wave-background {
  position: relative;
  height: 200px;
  overflow  overflow: hidden;
}

.wave-background::before {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 40px;
  background-color: var(--accent-color);
  
  /* 使用sin函數創建波浪形狀 */
  mask-image: paint(wave);
}

/* 如果瀏覽器支持Houdini API */
@supports (background: paint(id)) {
  @property --wave-amplitude {
    syntax: '<length>';
    initial-value: 10px;
    inher    inherits: false;
  }
  
  @property --wave-frequency {
    syntax: '<number>';
    initial-value: 2;
    inherits: false;
  }
}

雖然完整的波形可能需要Houdini API的支持,但簡單的波動效果已經可以通過現有的CSS功能結合三角函數實現。

3. 圍繞中心點旋轉的元素組

創建一個元素圍繞中心點旋轉並同時自轉的效果:

.orbit-system {
  position: relative;
  width: 400px;
  height: 400px;
}

.center-element {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 70px;
  height: 70px;
  transform: translate(-50%, -50%);
}

.orbiting-element {
  position: absolute;
  width: 30px;
  height: 30px;
  animation: orbit 8s linear infinite;
  
  /* 為每個軌道元素設置不同的起始角度 */
  &:nth-child(2) { --start-angle: 45deg; }
  &:nth-child(3) { --start-angle: 135deg; }
  &:nth-child(4) { --start-angle: 225deg; }
  &:nth-child(5) { --start-angle: 315deg; }
}

@keyframes orbit {
  0% {
    transform: 
      rotate(var(--start-angle, 0deg))
      translateX(150px)
      rotate(calc(-1 * var(--start-angle, 0deg)));
  }
  100% {
    transform: 
      rotate(calc(var(--start-angle, 0deg) + 360deg))
      translateX(150px)
      rotate(calc(-1 * calc(var(--start-angle, 0deg) + 360deg)));
  }
}

這個例子展示瞭如何組合使用三角函數和CSS動畫來創建複雜的運動路徑,而無需手動計算每一幀的位置。

4. 基於視口的傾斜標題

製作一個隨頁面滾動而角度自然變化的標題:

.dynamic-heading {
  font-size: clamp(2rem, 5vw, 6rem);
  text-align: center;
  
  /* 使用tan函數根據滾動位置計算傾斜角度 */
  transform: skewY(calc(tan(var(--scroll-ratio, 0)) * 15deg));
  transition: transform 0.1s ease-out;
}

/* 通過JS更新--scroll-ratio自定義屬性 */
// JavaScript代碼示例
window.addEventListener('scroll', () => {
  const scrollRatio = window.scrollY / (document.body.scrollHeight - window.innerHeight);
  document.documentElement.style.setProperty('--scroll-ratio', scrollRatio);
});

這種方法將視覺變化與實際用户交互聯繫起來,創造出更加沉浸式的體驗。

瀏覽器兼容性與回退方案

目前,主流現代瀏覽器已基本支持CSS三角函數:

  • Chrome 111+
  • Firefox 108+
  • Safari 15.4+

對於不支持這些功能的舊版瀏覽器,可以考慮以下回退策略:

.element {
  /* 基礎樣式作為回退 */
  margin-left: 25%;
  
%;
  
  /* 現代瀏覽器的增強樣式 */
  @supports (left: calc(sin(1rad) * 1px)) {
    margin-left: unset;
    left: calc(50% + sin(var(--angle)) * var(--radius));
  }
}

總結

CSS三角函數的引入為我們打開了一扇新的大門,使得創建複雜、動態、響應式的佈局變得更加簡單直觀。通過將數學邏輯直接融入樣式表,我們減少了對外部腳本的依賴,提高了性能,並且使代碼更加語義化。

雖然這些高級特性可能還不適合每個項目立即全面採用,但它們代表了CSS發展的方向——朝着更具表現力、更加強大的設計工具演進。嘗試在你的下一個項目中加入一些三角函數魔法吧!

注意:本文中的示例為了簡潔明瞭進行了簡化,實際應用中可能需要考慮更多的邊界情況和兼容性處理。