# Day 56：切版實作——垂直置中、文字段落行距、雙欄排版

By [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake) · 2026-02-09

---

完成切版成果
------

  

  
**實作重點**: 不使用 Flexbox/Grid 的傳統排版技巧

* * *

核心技術 1: Position Absolute 垂直置中
------------------------------

### 問題情境

需要讓 `<header>` 裡的 `<nav>` 垂直置中,但**不能使用 flex 或 grid**。

### 解決方案: 絕對定位 + Transform 位移

    header {
      position: relative;  /* 成為定位參考點 */
    }
    
    header nav {
      position: absolute;
      top: 50%;                    /* 上緣對齊 header 的 50% 高度 */
      transform: translateY(-50%); /* 往上移自己高度的 50% */
      left: 300px;                 /* 水平定位 */
    }
    

* * *

### 三步驟理解垂直置中原理

#### 步驟 1: `top: 50%` 讓上緣對齊中線

    ┌──────────────────────┐
    │      header          │
    │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │ ← 50% 高度
    │ ┌──────────┐         │
    │ │   nav    │         │ ← nav 的上緣在這裡
    │ └──────────┘         │
    └──────────────────────┘
    

此時 nav 的**上緣**對齊 header 高度的一半,但視覺上偏下。

#### 步驟 2: `transform: translateY(-50%)` 往上移自己高度的一半

    ┌──────────────────────┐
    │      header          │
    │     ┌──────────┐     │
    │ ─ ─ │   nav    │─ ─  │ ← nav 的中心線對齊 header 中心線
    │     └──────────┘     │
    └──────────────────────┘
    

`translateY(-50%)` 的 `-50%` 是相對於 **nav 自己的高度**,不是 header 的高度。 [developer.mozilla](https://developer.mozilla.org/zh-TW/docs/Web/CSS/Reference/Properties/transform)

#### 步驟 3: 完美置中

nav 的中心點現在精準對齊 header 的中心點,實現垂直置中效果。

* * *

### 核心概念

#### 1\. `position: absolute` 的三大影響

*   **脫離 Normal Flow**: 元素不再佔據版面空間
    
*   **定位參考點改變**: 變成最近的 `position: relative` 祖先
    
*   **Margin 語義改變**: `margin-left` 的參考點從「前一個元素」變成「父容器左邊界」
    

[stackoverflow](https://stackoverflow.com/questions/1034449/need-help-css-centering-with-absolute-positioning)

#### 2\. `left` vs `margin-left` (定位元素專用)

屬性

語義

適用場景

`left`

從參考點**定位**

✅ `position: absolute/fixed` 時更語意清晰

`margin-left`

推出**空白**

所有元素通用,但在定位時語義較弱

**最佳實踐**: 元素已經 `position: absolute` 時,優先用 `left/right/top/bottom` 表達定位意圖。 [sitepoint](https://www.sitepoint.com/css-center-position-absolute-div/)

* * *

### 其他不用 Flex/Grid 的垂直置中方法

#### 方法 2: Line-height 法

    header {
      height: 80px;
      line-height: 80px; /* 與高度相同 */
    }
    
    header nav {
      display: inline-block;
      vertical-align: middle;
      line-height: normal; /* 重設 line-height */
    }
    

**限制**: 需要固定高度,不適合響應式設計。

#### 方法 3: Table-cell 法

    header {
      display: table;
    }
    
    header nav {
      display: table-cell;
      vertical-align: middle;
    }
    

**限制**: 語義較差,且 `display: table` 有其他副作用。

* * *

核心技術 2: 按鈕置中 + 文字左對齊
--------------------

### 問題情境

有一個按鈕區塊 `.try-it-btn` 包含:

*   `<h2>`: 橘色按鈕顯示 "TRY IT NOW!"
    
*   `<p>`: 按鈕下方的說明文字
    

**需求**:

*   整個按鈕區塊在頁面中視覺上置中
    
*   `<p>` 文字要對齊按鈕的左邊緣(不是置中)
    
*   `.hero-intro` 內的標題和段落文字都要左對齊
    

* * *

### 解決方案

#### 1\. 按鈕區塊內部設定

    section .try-it-btn {
      text-align: left;        /* 內部元素左對齊 */
      display: inline-block;   /* 容器縮到內容寬度 */
      margin-top: 0px;
    }
    
    section .try-it-btn h2 {
      display: block;          /* 獨占一行 */
      padding: 20px 30px;
      background-color: orange;
      color: white;
      font-weight: bold;
      border-radius: 5px;
    }
    
    section .try-it-btn p {
      display: block;          /* 獨占一行,自動對齊左邊緣 */
      font-size: 16px;
      margin-left: 0;
    }
    

#### 2\. 父容器設定(讓按鈕區塊置中)

    section .hero-intro {
      display: inline-block;
      width: 50%;
      vertical-align: top;
      text-align: center;      /* 讓子元素 .try-it-btn 置中 */
    }
    
    /* 覆蓋父層的 text-align,讓文字內容左對齊 */
    section .hero-intro h1 {
      font-size: 60px;
      text-align: left;
      margin-bottom: 0px;
    }
    
    section .hero-intro h2 {
      font-size: 30px;
      text-align: left;
      margin-top: 0px;
      margin-bottom: 0px;
    }
    
    section .hero-intro p {
      font-size: 20px;
      text-align: left;
      margin-top: 0px;
      margin-bottom: 20px;
    }
    

* * *

### 核心概念

#### `display: inline-block` 的作用

*   讓容器寬度**縮到內容大小**(不會占滿父容器 100% 寬)
    
*   這樣父容器的 `text-align: center` 才能讓它置中
    

#### `text-align` 的繼承與覆蓋

    .hero-intro { text-align: center; }
        ↓
    讓 .try-it-btn 這個「元素本身」水平置中
        ↓
    但 .try-it-btn 內的 text-align: left 讓「文字內容」左對齊
    

**分層理解**:

*   `.hero-intro` 的 `text-align: center` 影響**直接子元素的橫向位置**(讓 `.try-it-btn` 置中)
    
*   `.hero-intro h1/h2/p` 用自己的 `text-align: left` 覆蓋,讓**文字內容**左對齊
    
*   `.try-it-btn` 內的 `text-align: left` 讓按鈕和下方文字自然對齊左邊緣
    

* * *

核心技術 3: Linear Gradient 硬切換
---------------------------

### 問題情境

需要製作一個橘色按鈕,但不是純色或漸層,而是**上下兩個橘色色塊直接分界**的效果,中間沒有平滑過渡。

### 解決方案

    section.hero .try-it-btn h2 {
      display: block;
      padding: 20px 30px;
      background: linear-gradient(to bottom, #ffb84d 50%, #ff9500 50%);
      color: white;
      font-weight: bold;
      border-radius: 5px;
    }
    

* * *

### 一般漸層 vs. 硬切換

    /* ❌ 平滑漸層:顏色會逐漸過渡 */
    background: linear-gradient(to bottom, #ffb84d, #ff9500);
    
    /* ✅ 硬切換:兩個色塊直接分界 */
    background: linear-gradient(to bottom, #ffb84d 50%, #ff9500 50%);
    

**視覺對比**:

    平滑漸層:               硬切換:
    ┌──────────┐           ┌──────────┐
    │  淺橘    │           │  淺橘    │
    │   ↕      │           │          │
    │  漸層    │           ├──────────┤ ← 直接切換
    │   ↕      │           │  深橘    │
    │  深橘    │           │          │
    └──────────┘           └──────────┘
    

* * *

### 為什麼加百分比可以做出硬切換?

    background: linear-gradient(to bottom, #ffb84d 50%, #ff9500 50%);
                                           ^^^^^^^^ ^^   ^^^^^^^^ ^^
                                           顏色1   位置  顏色2   位置
    

**運作原理**: [stackoverflow](https://stackoverflow.com/questions/49635637/hard-edged-gradient-in-css)

*   `#ffb84d 50%`: 淺橘色從 0% 延伸到 50%
    
*   `#ff9500 50%`: 深橘色從 50% 開始到 100%
    
*   兩個顏色在 50% 的位置**重疊**,就形成了**直接切換**而不是漸層
    

* * *

### 調整分界線位置

    /* 上面佔 40%,下面佔 60% */
    background: linear-gradient(to bottom, #ffb84d 40%, #ff9500 40%);
    
    /* 上面佔 70%,下面佔 30% */
    background: linear-gradient(to bottom, #ffb84d 70%, #ff9500 70%);
    

**實務技巧**:兩個百分比設定在**同一個位置**就會產生硬切換效果。 [stackoverflow](https://stackoverflow.com/questions/49635637/hard-edged-gradient-in-css)

* * *

### 延伸應用:多色硬切換

    /* 三等分,三種顏色 */
    background: linear-gradient(
      to right,
      red 33.33%,
      blue 33.33%,
      blue 66.66%,
      green 66.66%
    );
    

**產生效果**:

* * *

核心技術 4: CSS Multi-column Layout
-------------------------------

### 問題情境

將 `<article>` 內的多個 `<p>` 段落排版成雙欄,類似報紙排版效果。

### 解決方案

    article {
      column-count: 2;           /* 指定欄數 */
      column-gap: 20px;          /* 欄位間距 */
      margin-bottom: 200px;
    }
    
    article h2 {
      column-span: all;          /* h2 跨越所有欄位,不參與分欄 */
      margin-bottom: 40px;
    }
    
    article p {
      break-inside: avoid;       /* 避免段落在換欄時被切斷 */
      margin-top: 0;             /* 統一移除上方間距,避免兩欄不對齊 */
      line-height: 1.2;
    }
    

* * *

### 為什麼選擇 `column-count`?

**CSS Multi-column Layout 的三大優勢**: [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)

1.  **內容自動流動**: 左欄滿了自動流到右欄,不需要手動分組
    
2.  **不改動 HTML**: 維持語義化的單一 `<article>` 結構
    
3.  **適合流動式內容**: 比 Grid 或 Flexbox 更適合「文字排版」場景
    

* * *

### 遇到的問題與解決

#### 問題 1: 第二欄高度跟 h2 一樣高

    錯誤結果:
    ┌──────────┬──────────┐
    │          │          │
    │   h2     │  第二欄  │ ← h2 只佔一欄寬度
    │          │  很短    │
    │  第一欄  │          │
    └──────────┴──────────┘
    

**原因**: `<h2>` 也被分欄了,只佔一欄寬度。

**解決**: 用 `column-span: all` 讓 `<h2>` 跨越所有欄位。 [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)

    article h2 {
      column-span: all; /* h2 現在橫跨兩欄 */
    }
    

    正確結果:
    ┌──────────────────────┐
    │         h2           │ ← 跨越所有欄位
    ├──────────┬──────────┤
    │  第一欄  │  第二欄  │
    └──────────┴──────────┘
    

* * *

#### 問題 2: 第一欄開頭 `<p>` 有 `margin-top`,第二欄沒有

    錯誤結果:
    ┌──────────┬──────────┐
    │          │          │
    │ ↓ margin │  段落 3  │ ← 第二欄頂部緊貼
    │  段落 1  │  段落 4  │
    └──────────┴──────────┘
    

**原因**: Multi-column 會折疊新欄頂部元素的 `margin-top`(類似新容器開始)。 [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)

**解決**: 統一設定 `article p { margin-top: 0; }` 讓兩欄對齊。

    article p {
      margin-top: 0; /* 統一移除,避免不對齊 */
    }
    

    正確結果:
    ┌──────────┬──────────┐
    │  段落 1  │  段落 3  │ ← 兩欄頂部對齊
    │  段落 2  │  段落 4  │
    └──────────┴──────────┘
    

* * *

### 重要屬性說明

#### `column-count` vs `column-width`

屬性

用途

適用場景

`column-count: 2`

固定欄數

✅ 希望永遠顯示 2 欄

`column-width: 300px`

固定欄寬

響應式設計,欄數自動調整

[developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)

#### `break-inside: avoid`

    article p {
      break-inside: avoid; /* 段落不會被切成上下兩半 */
    }
    

**避免這種情況**:

* * *

### 學到的概念

1.  **CSS Multi-column Layout**: 適合報紙、雜誌式的流動排版 [mdn2.netlify](https://mdn2.netlify.app/en-us/docs/web/css/css_columns/)
    
2.  **Margin Collapsing**: 在 multi-column 環境下,新欄頂部的 margin 會被折疊
    
3.  `column-span`: 控制元素是否跨越所有欄位
    
4.  `break-inside: avoid`: 避免內容(如段落)在分欄時被切斷
    

* * *

完整代碼
----

### HTML 結構

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="style.css" />
        <title>ZERO TYPE</title>
      </head>
      <body>
        <header>
          <div class="logo">
            <img src="./public/logo.png" alt="網站 logo" />
            <p>ZERO TYPE</p>
          </div>
          <nav>
            <ul>
              <li><span>Home</span></li>
              <li>Feature</li>
              <li>News</li>
              <li>About</li>
              <li>Contact</li>
            </ul>
          </nav>
        </header>
    
        <main>
          <section class="hero">
            <div class="hero-intro">
              <h1>IDEAS?</h1>
              <h2>This is just a placeholder.</h2>
              <p>
                You can remove any link to our website from this website template,
                you're free to use this website template without linking back to us.
              </p>
              <div class="try-it-btn">
                <h2>TRY IT NOW!</h2>
                <p>Don't worry it's for free.</p>
              </div>
            </div>
            <div class="hero-img">
              <img
                src="./public/box.png"
                alt="網站主視覺圖片，一個裝滿各種不同類型檔案圖示的箱子"
              />
            </div>
          </section>
    
          <article>
            <h2>This is just a placeholder.</h2>
            <p>You can remove any link to our website...</p>
            <p>This is just a place holder...</p>
            <!-- 更多段落 -->
          </article>
        </main>
    
        <footer>
          <div class="copyright">&copy; 2023 Zerotype. All Rights Reserved.</div>
          <div class="social-media-link">
            <ul>
              <li><a href="##"><img src="./public/facebook.png" alt="" /></a></li>
              <!-- 更多社交媒體連結 -->
            </ul>
          </div>
        </footer>
      </body>
    </html>
    

### CSS 樣式(關鍵部分)

    /* Header 垂直置中 */
    header {
      position: relative;
      border: 5px solid black;
      margin-bottom: 30px;
      background-color: #f2f2f2;
    }
    
    header nav {
      position: absolute;
      top: 50%;
      left: 300px;
      transform: translateY(-50%);
    }
    
    /* Hero 區塊按鈕置中 */
    section.hero .hero-intro {
      display: inline-block;
      width: 45%;
      vertical-align: top;
      text-align: center;
    }
    
    section.hero .try-it-btn {
      text-align: left;
      display: inline-block;
      margin-top: 0px;
    }
    
    section.hero .try-it-btn h2 {
      background: linear-gradient(to bottom, #ffb84d 50%, #ff9500 50%);
      padding: 20px 30px;
      color: white;
      border-radius: 5px;
    }
    
    /* 雙欄文章排版 */
    article {
      column-count: 2;
      column-gap: 20px;
      margin-bottom: 200px;
    }
    
    article h2 {
      column-span: all;
      margin-bottom: 40px;
    }
    
    article p {
      margin-top: 0px;
      break-inside: avoid;
      line-height: 1.2;
    }
    

* * *

學習重點總結
------

### 技術層面

1.  **Position Absolute + Transform**: 不用 Flex/Grid 實現精準垂直置中 [geeksforgeeks](https://www.geeksforgeeks.org/css/how-to-center-absolutely-positioned-element-in-div-using-css/)
    
2.  **Inline-block + Text-align**: 傳統的元素置中組合技巧
    
3.  **Linear Gradient 硬切換**: 用相同位置的色標製作雙色分界 [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient)
    
4.  **Multi-column Layout**: 流動式雙欄排版的最佳選擇 [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)
    

### 設計思維

1.  **語義化 HTML**: 保持結構清晰,不為排版犧牲語義
    
2.  **漸進式除錯**: 從視覺問題追蹤到 CSS 屬性,逐步解決
    
3.  **屬性語義選擇**: 定位用 `left/top`,留白用 `margin`,各司其職
    

* * *

延伸學習資源
------

*   [MDN: transform](https://developer.mozilla.org/zh-TW/docs/Web/CSS/Reference/Properties/transform) [developer.mozilla](https://developer.mozilla.org/zh-TW/docs/Web/CSS/Reference/Properties/transform)
    
*   [MDN: CSS Multi-column Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout) [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)
    
*   [MDN: linear-gradient()](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient) [developer.mozilla](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient)
    
*   [How to Center an Absolute Positioned Element](https://www.freecodecamp.org/news/how-to-center-an-absolute-positioned-element/) [freecodecamp](https://www.freecodecamp.org/news/how-to-center-an-absolute-positioned-element/)
    

* * *

**筆記時間**: 2026-02-09  
**核心學習**: Position Absolute 垂直置中、Linear Gradient 硬切換、Multi-column Layout  
**學習階段**: Phase 2 - CSS 切版實作

---

*Originally published on [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/day-56)*
