---
title: "讓大標題剛好撐滿一整行：text-fit 實測，以及放大後字反而變小的陷阱 - Neil 的作品集"
description: "text-fit 一行 CSS 就能讓文字放大到撐滿容器，或縮小到放得下，取代以前的 JavaScript 寫法。但我實測發現，只寫 grow 時，使用者放大頁面，字反而會變小，調大的預設字級也會被抵銷；換行時第一行還可能撐破容器。這篇用互動範例整理寫法、適合與不適合的情境，以及兼顧無障礙的建議寫法。"
canonical_url: "https://neillin.com/blog/css-text-fit/"
last_updated: 2026-10-25
meta:
  author: Neil
  keywords: "無障礙網頁, 設計管理, 資料視覺化, UI, UX, 切版"
  "og:description": "text-fit 一行 CSS 就能讓文字放大到撐滿容器，或縮小到放得下，取代以前的 JavaScript 寫法。但我實測發現，只寫 grow 時，使用者放大頁面，字反而會變小，調大的預設字級也會被抵銷；換行時第一行還可能撐破容器。這篇用互動範例整理寫法、適合與不適合的情境，以及兼顧無障礙的建議寫法。"
  "og:image": "https://neillin.com/_og/s/o_0397e7ec1a31f1f6.png"
  "og:image:height": "600"
  "og:image:type": image/png
  "og:image:width": "1200"
  "og:title": "讓大標題剛好撐滿一整行：text-fit 實測，以及放大後字反而變小的陷阱 - Neil 的作品集"
  "twitter:image": "https://neillin.com/_og/s/o_0397e7ec1a31f1f6.png"
---

> Index of every page on this site: [llms.txt](https://neillin.com/llms.txt)

:::

# 讓大標題剛好撐滿一整行：text-fit 實測，以及放大後字反而變小的陷阱

2026年10月25日  

[前端技術](https://neillin.com/blog?category=frontend "查看「前端技術」分類的所有文章")CSS前端開發無障礙瀏覽器支援

  

> 話說在前頭：文中的行為我在 Chromium 153 上實測過。`text-fit` 目前只有 Chromium 支援，規格也還在討論，細節請以 caniuse、MDN 為準。有講錯的地方歡迎指正。

## 前言

活動主視覺的大字標語、雜誌封面的標題，設計稿上常常是「字剛好撐滿整行」。設計師在 Figma 裡拉一下字級就對齊了，但網頁的寬度一直在變。以前要做到這件事，只能靠 JavaScript 一直量文字寬度、算字級（例如 FitText.js），視窗一縮放就要重算一次。

Chrome 150 加入了 `text-fit`，一行 CSS 就能讓文字自動放大或縮小到剛好填滿容器。我實測之後發現它很好用，但如果直接照最簡單的寫法用，**使用者把頁面放大時，字反而會變小**。

先看一下你的瀏覽器支援度：

你的瀏覽器支援度

- `text-fit`偵測中（需要 JavaScript）

## 一、寫法

```
.hero-title {
  text-fit: grow; /* 放大到剛好撐滿容器寬度 */
}

.tab-label {
  white-space: nowrap; /* 不換行，才看得出縮小的效果 */
  text-fit: shrink;    /* 太長時縮小到剛好放得下 */
}
```

`text-fit` 最多可以寫三個值，順序固定：

| 位置 | 值 | 意思 |
| --- | --- | --- |
| 第一個（必填） | `none`／`grow`／`shrink` | 不縮放／放大到撐滿／縮小到放得下 |
| 第二個 | `consistent`（預設）／`per-line`／`per-line-all` | 多行時：所有行用同一個倍率／每行各自縮放，但最後一行不動／每一行都各自縮放 |
| 第三個 | 百分比 | `grow` 時是**放大上限**，`shrink` 時是**縮小下限** |

```
text-fit: grow per-line-all 200%; /* 每行各自放大，最多放大到原本的 2 倍 */
text-fit: shrink 80%;             /* 縮小，但不小於原本的 80% */
```

有兩點要注意：

- **沒有 `text-fit: auto`。** 我在 [技巧清單](https://neillin.com/blog/css-techniques-checklist)裡一開始寫錯了，瀏覽器不認得這個值，整條宣告會被忽略。
- **`font-size` 的計算值不會變。** 縮放是在排版完成後才套用的，用 `getComputedStyle()` 讀到的還是原本的字級。不過元素的高度會跟著放大後的字變高，不會跟下面的內容重疊（字距是固定值時例外，見第五節）。

## 二、動手試試

下面有三個情境：活動主視覺的標語、中文和德文的「加入購物車」按鈕，以及會換行的標題。可以拉動容器寬度、切換寫法，也可以勾選「把預設字級調大一倍」，看文字實際被縮放到多大：

互動範例：調整容器寬度（虛線）、切換寫法，看文字實際被放大或縮小到多大

容器寬度720px 模擬使用者把瀏覽器預設字級調大一倍

週年慶全館五折

偵測中（需要 JavaScript）

此處為互動範例，請在網頁上操作。

勾選「把預設字級調大一倍」之後，只寫 `grow` 的標語，實際字級幾乎不變；改成 `grow per-line-all 200%`，字才會跟著變大。「會換行的標題」可以按「找出會撐破容器的寬度」，看第三節的 bug。

## 三、無障礙實測：三個要小心的地方

### 1. 瀏覽器放大時，字反而變小

我用滿版的活動標語「週年慶全館五折」測試：容器跟視窗一樣寬，字級是 `2rem`。下表是字實際在螢幕上的高度：

| 寫法 | 放大 100% | 放大 200% | 放大 400% |
| --- | --- | --- | --- |
| 沒用 `text-fit` | 36px | 72px | 144px |
| `text-fit: grow` | 201px | **195px** | **185px** |
| `text-fit: grow per-line-all 200%` | 72px | 144px | 185px |

只寫 `grow` 時，**放大頁面反而讓字越來越小**。因為放大後，以 CSS 像素計算的視窗變窄了，`grow` 又會讓文字剛好撐滿這個變窄的寬度，結果就把放大的效果抵銷掉了。

這違反 WCAG 1.4.4（文字可放大到 200%）。CSSWG 也有一個還沒解決的 issue 在討論這件事：容器寬度跟著視窗走的時候，放大可能完全改變不了字的大小。

**加上放大上限就好了。** `grow 200%` 讓文字最多放大到原本的兩倍，寬螢幕上不一定會撐滿，但放大頁面時，字會正常跟著變大。

### 2. 使用者調大的預設字級，被抵銷掉了

有些使用者會在瀏覽器設定裡把預設字級從 16px 調大。我把預設字級調成 32px 再測一次：

| 寫法 | 預設字級 16px | 預設字級 32px |
| --- | --- | --- |
| `text-fit: grow` | 201px | 201px（沒變） |
| `text-fit: grow per-line-all 200%` | 72px | 144px |

只寫 `grow` 時，不管基準字級多大，最後都會縮放到同一個寬度，所以使用者調大的設定完全沒有效果。

`shrink` 也一樣。按鈕寬度如果寫死成 `300px`，使用者把字調大之後，`shrink` 又會把字縮回去。容器寬度改用 `rem` 設定就不會有這個問題，因為容器也會跟著使用者的字級變大。

### 3. 換行時，第一行可能撐破容器

這是我測到的一個 bug。標題在窄螢幕換成兩行時，預設的 `consistent` 照規格應該取「最寬那一行」的倍率，讓每一行都不超出容器。但在某些寬度下，Chromium 153 會套用較短那一行的倍率：

- 「週年慶全館商品五折起限時三天」，容器 320px 寬：**第一行被放大到 800px 寬**，頁面出現橫向捲動。

我用 4 段文字、200 到 700px 每 10px 測一次，一共 204 種情況：

| 寫法 | 撐破容器 |
| --- | --- |
| `grow`（預設 `consistent`） | 6 次 |
| `grow 150%` | 6 次（有上限，但還是會溢出） |
| `grow per-line` | 0 次 |
| `grow per-line-all` | 0 次 |

會在哪個寬度發生跟字型有關，範例裡的寬度不一定跟我測的一樣，所以範例的按鈕會讓你的瀏覽器自己掃一遍。會換行的標題，目前建議改用 `per-line-all`。

另外，WCAG 1.4.12 文字間距的部分，`grow` 沒問題：使用者加大字距時，`grow` 會把字縮小一點來抵銷，文字仍然完整顯示，沒有被切掉。`shrink` 則有一個例外，見第五節。

## 四、什麼時候適合用？

`text-fit` 的本質是**讓字級跟著容器寬度走，而不是跟著內容的重要性或使用者的設定走**。所以它適合「版面比字級重要」的少數地方，不適合拿來當全站的字級系統。

### 適合用

| 情境 | 寫法 | 原因 |
| --- | --- | --- |
| 活動主視覺、Landing page 的大字標語 | `grow` + 上限 | 字少、只有一行，設計上就是要撐滿整行 |
| 雜誌風格的文章封面標題 | `grow per-line-all` + 上限 | 標題是視覺重點，換行時每行各自撐滿也是常見的編排 |
| 數據儀表板、價格方案卡片上的大數字 | `grow` + 上限 | 數字要在卡片裡盡量大又不能超出，卡片寬度又會隨版面改變 |
| 多語系的按鈕、分頁標籤、導覽列 | `shrink` + 下限 + 換行退路 | 翻譯後的字數無法預測，例如德文常比中文長好幾倍，稍微縮小就能放進同一行 |
| 使用者輸入的名稱（暱稱、商品名稱），放在固定寬度的卡片上 | `shrink` + 下限 | 內容長度無法控制，偶爾出現的長字串不會撐破版面 |

### 不適合用

| 情境 | 原因 |
| --- | --- |
| **內文段落** | 每段的字級會因為行寬不同而不一樣，閱讀時字忽大忽小；內文也最需要尊重使用者調整的字級 |
| **一般的標題層級（h2、h3）** | 標題大小是用來表達層級的。用 `text-fit` 之後，短的 h3 可能比長的 h2 還大，視覺上的層級就亂了 |
| **表單欄位的標籤、錯誤訊息、說明文字** | 這些是使用者完成操作必須看清楚的文字，不能為了版面縮小 |
| **要維持一致字級的列表** | 例如商品卡片的標題：每張卡片的字數不同，用 `shrink` 會讓每張卡片的字大小都不一樣，看起來很亂 |
| **用 `shrink` 處理本來就不該擠在一起的內容** | 文字放不下時，通常應該先調整版面（換行、加寬、精簡文字），縮小字級是最後的手段 |

### 判斷原則

用之前可以先問自己兩個問題：

1. **這段文字變大或變小，會不會影響使用者看懂內容？** 會的話就不要用。 `text-fit` 只適合「字級是裝飾性的」地方。
2. **使用者放大頁面時，這段文字有沒有跟著變大？** 一定要加百分比上下限，並實際放大到 200%、400% 檢查。

## 五、我建議的寫法

**大標語（`grow`）：**

```
.hero-title {
  /* 字級用 rem：使用者調大預設字級時，基準會跟著變大 */
  font-size: 3rem;
  /* 字距用百分比：固定值的字距會讓放大後的字蓋到上下的內容 */
  letter-spacing: 2%;
  /*
    per-line-all：每行各自縮放，避開換行時第一行撐破容器的問題
    200%：最多放大 2 倍，瀏覽器放大時字才會跟著變大
  */
  text-fit: grow per-line-all 200%;
}
```

基準字級要設得夠大，`200%` 的上限才能涵蓋常見的螢幕寬度。

**按鈕、分頁標籤（`shrink`）：**

```
.tab-list {
  container-type: inline-size; /* 讓下面的容器查詢可以判斷寬度 */
}

.tab-label {
  letter-spacing: 5%;   /* 字距用百分比，才會跟著字一起縮 */
  white-space: nowrap;  /* 先嘗試放在一行 */
  text-fit: shrink 80%; /* 最多縮小到 80%，避免字小到看不清楚 */
}

/* 容器太窄時，改回換行，不要硬縮小；門檻要用最長的翻譯實測決定 */
@container (width < 12rem) {
  .tab-label {
    white-space: normal;
  }
}
```

只加 `shrink 80%` 不夠：縮到 80% 還放不下時，文字會直接超出按鈕。要搭配容器查詢，太窄時改回換行。

另外兩個我實測踩到的坑：

- **`display: flex` 或 `grid` 的按鈕， `text-fit` 加在按鈕上沒有作用。** 很多設計系統的按鈕會用 flex 讓圖示和文字對齊，這時要把文字包在 `<span>` 裡，把 `text-fit` 加在 span 上，並設定 `min-width: 0`。flex 子項目預設不會縮到比內容窄，不加的話 span 會被文字撐寬，就沒有空間可以縮。

```
.icon-button {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
}

.icon-button > .label {
  min-width: 0;         /* 讓 span 可以比文字窄，text-fit 才有空間縮 */
  white-space: nowrap;
  text-fit: shrink 80%;
}
```

- **字距要改用百分比。** `letter-spacing` 用 px、em、rem 這類固定值時，我測到兩個問題：
  - **放大時，字可能蓋到上下的內容。** 字只在畫面上放大了，排版高度卻沒有跟著變。我用 3 種字型、5 段文字、4 種寬度、2 種寫法測試，固定值的字距在 120 種組合裡有 30～41 種會發生， `normal` 和百分比一次都沒有。
  - **縮小時， `shrink` 可能整個放棄。** 固定的字距不會跟著縮，字很多、按鈕又很窄時，光是字距加起來就比按鈕寬， `shrink` 會直接放棄，文字以原本的大小超出。  
  改成百分比（以字級為基準，例如 `letter-spacing: 5%`）之後，兩個問題都沒有再出現。不過使用者依 WCAG 1.4.12 用工具加大字距時，通常是用固定值的 `0.12em`，一樣可能遇到，所以上面「太窄時改回換行」的退路很重要。

## 六、不支援的時候

```
@supports (text-fit: grow) {
  .hero-title {
    text-fit: grow per-line-all 200%;
  }
}
```

不支援的瀏覽器會顯示原本的字級，只是沒有撐滿整行。標題本來就要在這個字級下看起來正常，所以不需要再用 JavaScript 補。

## 結論

- `text-fit: grow` 一行就能讓大標題撐滿整行， `shrink` 能讓太長的文字縮小到放得下，取代以前的 JavaScript 寫法。
- **一定要加百分比上下限。** 沒有上限的 `grow` 會抵銷瀏覽器放大和使用者的字級設定，放大頁面時字反而變小。
- 會換行的標題用 `per-line-all`。預設的 `consistent` 在 Chromium 153 某些寬度下會讓第一行撐破容器。
- `shrink` 要搭配下限和換行的退路，不要讓字小到看不清楚。
- 用 `text-fit` 的元素，字距（ `letter-spacing`）改用百分比。
- `text-fit` 適合字少、字級屬於視覺設計的地方（大標語、大數字、多語系按鈕），不適合內文、一般標題層級和表單文字。

## 延伸閱讀

- [width: 100% 為什麼會撐破容器？用 stretch 撐滿剛剛好](https://neillin.com/blog/css-stretch/)
- [放大之後，置中的內容上半部不見了？用 safe center 讓它捲得到](https://neillin.com/blog/css-safe-alignment/)
- [現代 CSS 與 HTML 技巧整理清單：115 個特性、支援度與實驗優先序](https://neillin.com/blog/css-techniques-checklist/)

## 相關連結

- [MDN — text-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/text-fit "另開新視窗")
- [CSS fit-width text 說明文件（Google）](https://github.com/explainers-by-googlers/css-fit-text "另開新視窗")
- [CSSWG issue #12886 — 預設縮放上限與無障礙](https://github.com/w3c/csswg-drafts/issues/12886 "另開新視窗")
- [WCAG 2.2 — 1.4.4 調整文字大小](https://www.w3.org/WAI/WCAG22/Understanding/resize-text "另開新視窗")
- [Can I use（瀏覽器支援度查詢）](https://caniuse.com "另開新視窗")

```json
{"@context":"https://schema.org","@graph":[{"@id":"https://neillin.com/#website","@type":"WebSite","inLanguage":"zh-Hant-TW","name":"Neil 的作品集","url":"https://neillin.com/","workTranslation":{"@id":"https://neillin.com/en/#website"}},{"@id":"https://neillin.com/blog/css-text-fit/#webpage","@type":"WebPage","description":"text-fit 一行 CSS 就能讓文字放大到撐滿容器，或縮小到放得下，取代以前的 JavaScript 寫法。但我實測發現，只寫 grow 時，使用者放大頁面，字反而會變小，調大的預設字級也會被抵銷；換行時第一行還可能撐破容器。這篇用互動範例整理寫法、適合與不適合的情境，以及兼顧無障礙的建議寫法。","name":"讓大標題剛好撐滿一整行：text-fit 實測，以及放大後字反而變小的陷阱","url":"https://neillin.com/blog/css-text-fit/","isPartOf":{"@id":"https://neillin.com/#website"},"potentialAction":[{"@type":"ReadAction","target":["https://neillin.com/blog/css-text-fit/"]}]},{"@id":"https://neillin.com/#person","@type":"Person","jobTitle":"UI/UX 設計師","name":"Neil Lin","url":"https://neillin.com/","sameAs":["https://github.com/Neil-Lin"]},{"@id":"https://neillin.com/blog/css-text-fit/#/schema/blog-posting/1","@type":"BlogPosting","dateModified":"2026-10-25","datePublished":"2026-10-25","description":"text-fit 一行 CSS 就能讓文字放大到撐滿容器，或縮小到放得下，取代以前的 JavaScript 寫法。但我實測發現，只寫 grow 時，使用者放大頁面，字反而會變小，調大的預設字級也會被抵銷；換行時第一行還可能撐破容器。這篇用互動範例整理寫法、適合與不適合的情境，以及兼顧無障礙的建議寫法。","headline":"讓大標題剛好撐滿一整行：text-fit 實測，以及放大後字反而變小的陷阱","inLanguage":"zh-Hant-TW","keywords":"CSS, 前端開發, 無障礙, 瀏覽器支援","url":"https://neillin.com/blog/css-text-fit/","author":{"@id":"https://neillin.com/#person"},"mainEntityOfPage":{"@type":"WebPage","@id":"https://neillin.com/blog/css-text-fit/"},"publisher":{"@id":"https://neillin.com/#person"}},{"@id":"https://neillin.com/blog/css-text-fit/#/schema/breadcrumb-list/1","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"回首頁","item":"https://neillin.com/"},{"@type":"ListItem","position":2,"name":"部落格","item":"https://neillin.com/blog/"},{"@type":"ListItem","position":3,"name":"讓大標題剛好撐滿一整行：text-fit 實測，以及放大後字反而變小的陷阱","item":"https://neillin.com/blog/css-text-fit/"}]}]}
```

## Sitemap

See the full [sitemap](https://neillin.com/sitemap.md) for all pages.
