Skip to main content

現代 CSS clamp() 完整筆記

clamp() 常被稱為「媒體查詢殺手」,因為很多「只是字體、間距要跟著螢幕慢慢變大/變小」的情境,其實根本不需要一堆 @media,一行 clamp() 就能搞定。


1. 問題背景:為什麼會寫出 40+ 個媒體查詢?

典型情境:為了讓頁面在 375 / 768 / 1024 / 1440… 等尺寸都漂亮,你會寫:

h1 {
font-size: 24px;
} /* Mobile */
@media (min-width: 768px) {
h1 {
font-size: 32px;
} /* Tablet */
}
@media (min-width: 1024px) {
h1 {
font-size: 40px;
} /* Desktop */
}
@media (min-width: 1440px) {
h1 {
font-size: 48px;
} /* Large desktop */
}

一個標題就四個斷點、12 行 CSS;若所有標題、段落、按鈕、容器都這樣寫,很快就變成「媒體查詢地獄」,而且在 800px、1200px 這種「介於斷點之間」的寬度,字體會突然跳變,不夠流暢。


2. clamp() 是什麼?核心概念

語法:

property: clamp(min, preferred, max);
  • min:最小值(數值不會小於它)
  • preferred:首選值,通常會用 vwvw + px,讓數值隨視窗寬度變化
  • max:最大值(數值不會大於它)

瀏覽器會優先採用「首選值」,但若太小就用 min,太大就用 max

/* 字體會在 24px ~ 48px 間,跟著視窗寬度線性縮放 */
font-size: clamp(24px, 5vw, 48px);

效果:

  • 320px 手機:5vw = 16px → 被下限 24px clamp 起來 → 24px
  • 768px 平板:5vw = 38.4px → 落在 24–48 範圍 → 38.4px
  • 1920px 螢幕:5vw = 96px → 被上限 48px clamp → 48px

整段寬度之間會「平滑縮放」,不再是斷點跳變。


3. 實戰例子:用 clamp() 取代多數媒體查詢

3.1 響應式標題字體(Fluid Typography)

舊寫法:

h1 {
font-size: 28px;
}
@media (min-width: 640px) {
h1 {
font-size: 36px;
}
}
@media (min-width: 1024px) {
h1 {
font-size: 48px;
}
}
@media (min-width: 1440px) {
h1 {
font-size: 56px;
}
}

新寫法:

h1 {
font-size: clamp(28px, 4vw, 56px);
}

15 行變 3 行,且縮放更平滑。

3.2 容器內距 / 外距(Padding / Margin)

.container {
padding: clamp(16px, 4vw, 64px);
}
  • 小螢幕時接近 16px
  • 大螢幕時接近 64px
  • 中間寬度則線性補間

3.3 卡片網格間距(Grid Gaps)

.grid {
gap: clamp(12px, 2vw, 32px);
}

小螢幕時卡片之間較緊,中大螢幕逐漸拉開。

3.4 其他很適合用 clamp() 的屬性

  • 字體大小:font-size
  • 內外距:padding, margin
  • 寬度限制:max-width
  • 卡片圓角:border-radius
  • 元件高度:height, min-height

4. 如何計算「首選值」的 vw

如果想要更精準控制,可以用一個簡單公式來算中間那個 vw

  1. 決定最小值 / 最大值
    • 例如:字體最小 16px、最大 32px
  2. 決定對應的視窗寬度範圍
    • 例如:375px(手機)到 1440px(桌機)
  3. 計算差值
    • 尺寸差:32 - 16 = 16px
    • 寬度差:1440 - 375 = 1065px
  4. 換成百分比
    • 16 / 1065 ≒ 0.015 = 1.5% → 就是 1.5vw
  5. 組合成 clamp()
font-size: clamp(16px, 1.5vw + 16px, 32px);

這樣可以保證在 375–1440px 這段範圍內,字體會從 16px 線性縮放到 32px。

懶人作法:直接從 2vw3vw 開始試,搭配 Clamp Calculator 之類工具微調就好。


5. 什麼時候「不要」用 clamp()?還是要媒體查詢

clamp() 解決的是「數值隨寬度平滑變化」的問題,但結構變化還是交給 @media

  • 佈局改變

    • 例如從單欄 → 雙欄:

      @media (min-width: 768px) {
      .layout {
      display: grid;
      grid-template-columns: 1fr 1fr;
      }
      }
  • 顯示 / 隱藏元素

    @media (max-width: 767px) {
    .desktop-only {
    display: none;
    }
    }
  • 行為改變

    • 例如桌機是完整導覽列,手機變漢堡選單。

黃金法則:
數值縮放(size / spacing)用 clamp(),結構與行為改變用 @media


6. 常見錯誤&避雷指南

錯誤 1:什麼都想用 clamp() 取代

  • 佈局崩壞、漢堡選單壞掉,大多是想拿 clamp() 取代 layout media queries。
  • 解法:只把「單純大小」相關的地方換成 clamp(),layout 照用 @media

錯誤 2:vw 值太大,縮放過頭

/* Bad:在小螢幕直接頂到 max,clamp 形同虛設 */
font-size: clamp(16px, 10vw, 32px);
  • 400px 螢幕 → 10vw = 40px,直接被上限 32px 卡住。
  • 建議:多數情境 1vw ~ 5vw 比較合理。

錯誤 3:最小值設太小,導致難以閱讀

/* Bad:8px 幾乎看不到 */
font-size: clamp(8px, 2vw, 24px);
  • 文字最小值不要低於 14px,主體內容建議 16px 起跳。

錯誤 4:只在 DevTools 看,沒在實機測

  • clamp 在模擬器上看起來 ok,但實機上可能顯得太大/太小。
  • 解法:至少用一台實機或遠端測試服務(BrowserStack 等)過一輪。

7. 實務工作流:怎麼在專案裡導入 clamp()

  1. 先做好桌機版(固定 px 值)

  2. 找出「應該隨螢幕縮放」的東西

    • 各層級標題、段落文字
    • 卡片、Section 的內外距
    • 容器最大寬度、Grid 間距、圓角等
  3. 把固定值改成 clamp()

    /* Before */
    h1 {
    font-size: 48px;
    }
    .section {
    padding: 40px;
    }

    /* After */
    h1 {
    font-size: clamp(32px, 4vw, 48px);
    }
    .section {
    padding: clamp(20px, 3vw, 40px);
    }
  4. 在幾個關鍵寬度檢查

    • 375px、768px、1024px、1440px
  5. 微調 vw(必要時加上 + px 偏移)

  6. 保留「只負責佈局/顯示切換」的媒體查詢

實務上通常可以減少 60–70% 以上、原本只用來「改大小」的媒體查詢。


8. 瀏覽器支援與 fallback 策略

clamp() 的支援度目前已超過 96%(Chrome / Firefox / Safari / Edge 都支援),剩下主要是非常老舊的瀏覽器。

若想保險一點,可以這樣寫 fallback:

.heading {
font-size: 32px; /* 舊瀏覽器 fallback */
font-size: clamp(24px, 4vw, 48px); /* 支援 clamp 的覆蓋上來 */
}

不認得 clamp() 的瀏覽器會忽略第二行,只用 32px。


9. Quick Reference:常用 clamp() 模板

/* 標題字體 */
h1 {
font-size: clamp(32px, 5vw, 64px);
}
h2 {
font-size: clamp(24px, 4vw, 48px);
}
h3 {
font-size: clamp(20px, 3vw, 32px);
}

/* 內文字體 */
p {
font-size: clamp(16px, 1.5vw, 20px);
}

/* 容器間距 */
.container {
padding: clamp(16px, 4vw, 80px);
margin: clamp(20px, 5vw, 100px) auto;
}

/* 內容寬度 */
.content {
max-width: clamp(320px, 90vw, 1200px);
}

10. 整體觀念總結(一句話記住)

  1. clamp() 處理「要隨螢幕平滑變化的數值」:字體大小、間距、寬度、圓角等。
  2. @media 處理「版面與行為改變」:欄位數變化、導覽列型態、顯示/隱藏元素。
  3. 實作策略:先寫出桌機版固定值 → 把該流動的數值改成 clamp() → 只保留少量關鍵媒體查詢。

記憶點:
clamp() 管 size,media query 管 layout」── 這樣用,你的 CSS 會更短、更好維護,也更接近真正的 Fluid Design。