CSS Box Model 診斷指南:跑版與異常空白的修法

跑版、爆寬、異常空白,先做症狀分層:吃背景色的空間歸 padding 與 border,推開鄰居的歸 margin,規律間距交給容器 gap。CSS Box Model 兩條計算規則:box-sizing 決定寬度量到哪層,垂直外距符合條件時摺疊取大值。附 DevTools 追查與上線前健檢清單。
快速重點:遇到跑版先分層:會吃到背景色、屬於命中範圍的空間,歸元素自己管(padding 與 border,border-box 下計入宣告寬度);透明、只推開鄰居的空間歸外距管,垂直相鄰時可能摺疊取大值;同類項目的規律間距交給容器的 gap。判斷順序對了,修法自然浮現。
一個假設情境:促銷活動上線當天早上,官網同時冒出三個症狀。定價頁的三欄卡片在手機上掉成直落的一長條;結帳按鈕緊貼著旁邊的客服連結,訪客想按下一步,屢屢按到隔壁;廣告版位載入完成的那一刻,整頁往下沉,訪客剛要閱讀的段落被推走。三件事發生在不同畫面,回報時卻常被當成三個互不相干的 bug 各自處理。
內部檢討通常往兩個方向找原因:編輯器壞了,或者佈景主題有問題。於是設定改了又改,舊症狀壓下去,新症狀冒出來。另一條常見路線是回頭把名詞背一遍,Padding、Margin、Border 的定義讀得滾瓜爛熟,回到畫面前面,問題照舊。定義背得再熟,也不會告訴你眼前那段空白究竟是誰的、又受了哪條規則影響。
這三個症狀指向同一個根源。版面裡每一段空間都有歸屬:屬於元素自己的、屬於鄰居之間的、屬於容器層級的、屬於載入前後的,判斷錯歸屬,改哪個屬性都不會對。歸屬之上還躲著兩條計算規則:宣告的寬度量到哪一層,由 box-sizing 決定;垂直方向的外距在符合條件時摺疊,只取較大值。往下是以症狀為起點的分層判斷流程,每個判斷點附量測方法與處置選單,連代價與適用條件一起給。每一節都收在一個反例邊界上,條件不成立時不硬套。
跑版、爆寬、來路不明的空白:第一步先分層
動手改任何數值前,先問三件事。這段空間吃不吃背景色、算不算命中範圍?吃,就歸元素自己的內距與邊框管;不吃、透明地存在於元素外側的,才是外距。改了它,影響誰?把元素自己撐大的,是內距與邊框;把鄰居推開的,是外距。它是容器裡同類項目之間的規律間距嗎?是,這段距離就不該由子元素個別扛,交給容器層級的 gap。三個問題都有可量測的答案,不靠背誦。
需要的名詞常識一段就夠。瀏覽器把每個元素畫成一個矩形盒子,這套由內而外的結構就是 CSS Box Model(盒模型):放內容的區域、外圈的內距、再外圈的邊框、邊框外側透明的外距。重點不在名稱,在三個可驗證的性質:背景色會鋪進內距這層,命中範圍也包含它;邊框有寬度與樣式,會增加外部尺寸;外距不著色,只決定元素與鄰居的距離,垂直方向還有摺疊的可能。量測工具從頭到尾同一個:開發者工具的計算值面板,這幾層在那裡各畫成一圈,滑過去就會在頁面上高亮。
左右捲動檢視完整表格
| 症狀 | 先懷疑的分層 | 檢查工具與看法 |
|---|---|---|
| 宣告寬度與實際佔位對不上、爆寬掉行 | 計算範圍:box-sizing 的口徑 | 計算值面板比對內容區與邊框盒兩種寬度 |
| 垂直間距比設計稿小 | 外距摺疊:相鄰或母子關係 | 選取兩個元素看高亮,比對合併後的值 |
| 來路不明的空白 | 歸屬未定:元素、鄰居或容器 | 高亮逐層確認空間落在哪一層 |
| 誤觸相鄰的連結或按鈕 | 命中範圍與間隔不足 | 量測目標尺寸與相鄰淨距 |
| 載入後版面往下跳 | 空間未預留:載入前後尺寸改變 | 版位紀錄與 CLS 數值 |
這張表同時是整篇的地圖。寬度對不上,往計算範圍那一節走;間距縮水,看摺疊的條件與邊界;間距該寫在誰身上、誤觸、跳版、多個書寫方向、開發者工具的走法、編輯器的對應,各有一節;收尾是一張上線前的健檢清單。各節的判斷都設計成能獨立成立,帶著具體症狀跳讀也行。如果是剛起步、連選擇器都還不熟的讀者,先把CSS 語法與選擇器的入門補上,下面每一節都用得上。
宣告的寬度為什麼和實際佔位對不上
直接回答:預設的 content-box 口徑下,width 只量內容區,內距與邊框加在其外;換成 border-box 之後,宣告的寬高涵蓋內距與邊框,外距仍在外另計。同一個數字、兩種口徑,量出來的佔位就是不同,與細不細心無關。
用構造情境算一遍(假設範例,非伸縮區塊):卡片宣告寬 240px,左右內距各 16px,邊框左右各 1px。content-box 口徑下,邊框外緣的實際寬度是 240 加 32 加 2,共 274px。設計稿標 240,驗收量到 274,多出來的 34px 來自量尺的起訖點不同,與手誤無關。同一張卡換成 border-box,240 指的就直接是邊框外緣,內容區自動縮成 206px,設計、驗收、實作三方看的是同一個數字。
痛點在多欄排版浮上檯面。一列規劃三張 240px 的卡,每張實際 274,第三張被擠到下一行,客戶看到的是版壞了,來回一輪修改與計價;工程面看到的只是計量口徑沒對齊。驗收前把 width 量到哪一層講清楚,這類來回多半收得掉。
邊框是最常被漏算的一層,因為它細到容易被無視。它的簡寫一次指定寬度、樣式、顏色,像 border:1px solid #ccc 這樣的宣告;寬度給了數字,樣式決定看不看得到,兩者一起決定這圈線佔不佔空間。
border:1px solid #ccc 指定寬度、樣式與顏色。medium 的實際寬度由瀏覽器定義;border-style 為 none 或 hidden 時使用寬度為零。改成可見樣式後是否增加外部尺寸,還取決於 box-sizing 與既有大小設定。
要把這層心算從每個元件身上拿掉,多數專案會在樣式表開頭做全域重置,對象涵蓋元素本身與前後偽元素,一次把計算範圍換成 border-box。重置之後,宣告 240px,內距與邊框改從 240 裡面扣,不再往外加。
這段設定將選中的元素和偽元素設為 border-box,宣告寬高通常包含 padding 與 border,margin 仍另計。內容區不能小於零,因此 padding 與 border 總和已超過指定尺寸時,實際盒子仍可能更大。

content-box 不是缺陷,是一種口徑。嵌入第三方報表 iframe、需要固定內容區寬度的元件,維持 content-box 反而可預期:內容區就是引用方量到的那個尺寸。該檢查的是全站口徑一致與否,不是哪一邊絕對正確;驗收時和協作者約定同一把量尺,比背預設值有用。
間距無故縮水,先別急著修
兩個區塊各設了外距,量出來的間距卻比相加小,這多半不是 bug。一般排版裡,垂直相鄰且符合摺疊條件時,兩段外距合併取較大值,不是相加;Flex 與 Grid 容器內部不適用同一套規則。先量測確認是摺疊,再決定怎麼處置,順序反了就會修錯地方。
症狀兩型。相鄰型:上一個區塊的底部外距與下一個的頂部外距碰頭,量出來只剩較大那段。父子型:子元素的外距穿過沒有內距與邊框擋著的母元素,表現在母元素與外部鄰居之間,看起來像子元素的外距憑空消失。確診方式同一種:選取元素看高亮與計算值,確認空間在哪一層被合併;父子型先選子元素,看高亮落在母元素邊界的外側還是內側。
兩個一般區塊的相鄰正外距若符合摺疊條件,30px 與 20px 合併後為 30px;不符合條件就不能套此公式。含負值時採最大正值加最小負值,全為負值則取最小值。
確診之後,修法是選擇題。在母元素補一段極小的內距或邊框破壞摺疊條件,見效快,但屬侵入式手段,元素身上從此留著一條為了拆問題而存在的設定;改成 Flex 或 Grid 佈局、或把間距交給容器的 gap,是結構性解,規則單純可預期,代價是動到排版結構。怎麼選,看這段版面之後還會不會長東西。
一條邊界要畫清:「看起來變小」不等於錯誤。設計稿以相加值標註間距、實作以摺疊值呈現時,該修的可能是標註的假設,不是樣式。以驗收量測為準,先量再改,也別把所有間距問題都歸給摺疊:覆蓋、繼承與單位換算,都會造成同樣的表象。
間距要寫在誰身上?
專案長大後間距失控,原因通常出在位置寫錯,而非數值選錯。同類項目之間的規律間距,交給容器的 gap:不摺疊、不在容器邊緣留殘距、行列兩個方向可分開設。性質不同的兩個區塊之間的一次性推開,用外距。全站的節奏,用級距表收斂。三者是分工,不是取代。假設情境:商品卡牆原本每張卡都寫一段外距,改成交給容器統一間距之後,設計臨時把三欄改成四欄,間距只需要在一處調整。
判斷寫在哪一層,用檢驗問題比背口訣可靠,四個問題對三種工具:
左右捲動檢視完整表格
| 檢驗問題 | 內距 | 外距 | 容器 gap |
|---|---|---|---|
| 背景色會延伸到這層嗎 | 會,背景鋪進內距 | 不會,這層永遠透明 | 不適用,空間屬容器層級 |
| 可以設成負值嗎 | 不行,負值無效 | 可以,把鄰居拉近甚至重疊 | 不行 |
| 垂直相鄰會摺疊嗎 | 不會 | 一般排版下符合條件就會 | 不會 |
| 計入宣告寬度嗎 | border-box 下計入 | 不計,永遠在尺寸之外 | 不適用,作用於子元素之間 |
級距表是業界常見慣例,不是規範:把常用距離收在 4 與 8 的倍數序列上,例如 8、16、24、32、48,需要的值只從序列裡挑。價值不在數學,在減少決策,雙方對「大一號」指的是 24 還是 32 有共識,抽查也容易核對。把級距收成變數、讓全站引用同一份定義的做法,延伸看Sass 變數與模組化;卡片牆與 Bento 格線對節奏特別敏感,版型規劃見Bento Grid 排版。
gap 普及之後,外距沒有退場。文章標題與摘要之間、定價區與頁尾之間,兩個性質不同的區塊要的是段落感,一次性、有方向性的推開仍是外距的職責。判斷的落點一句話:項目同質、間距規律,交容器;元素異質、關係一次性,用外距。
手機上點不到、旁邊又誤觸:可點擊範圍的兩條底線
可點擊目標有兩條獨立的底線。一條管本身:命中範圍要夠大,WCAG 2.2 的 Target Size (Minimum) 條目把最低值定在 24×24 CSS 像素,並列有例外:行內文字構成的目標、使用者代理決定的尺寸、本質上必須縮小的呈現,以及彼此間隔足夠的小目標。一條管鄰居:相鄰目標之間要留得出間隔。內距撐大命中範圍,外距與 gap 拉開誤觸風險,檢查以計算值為準,不憑目測。
觸控與滑鼠的差別在精準度。手指的接觸面積遠大於指標,按鈕只包住文字時,可命中的就那行字的高度。用內距往四周撐是成本最低的放大,改字級會連動行高與版面,動容器寬度影響更廣。量法:選取目標,看含內距後的尺寸是否到達 24 CSS 像素的邊長,再量與相鄰目標的淨距。
高風險位置三個:手機版導覽(項目密、使用者移動快)、結帳流程的按鈕與表單控制(出錯代價直接反映在訂單)、頁尾社群連結列(圖示小、間距緊)。界限畫清楚:24 像素是無障礙的最低門檻,規範對行內文字目標與間隔足夠的小目標另設例外,達標不代表好按,也不是任何搜尋排名的因素,它只承諾多數情境點得到。量測時連間隔一起看:兩個目標貼在一起,各自達標仍然可能誤觸。
單位取捨決定這些數字在別的字級下還成不成立。px 是絕對值,好預期,但使用者放大字級時不跟著變;rem 跟著根字級縮放,與文字相關的間距適合;clamp 設上下限做流體間距,避免小螢幕貼死、大螢幕鬆散。左右留白多數情境至少抓 16px 這一級,再按密度調整。行動版留白與閱讀壓迫的節奏,延伸看RWD 主題的留白調整。
廣告期間畫面一直跳,是空間沒有先預留
投放期間的跳版,來源多半是盒子尺寸在載入前後改變。圖片沒帶尺寸屬性、字體換檔前後度量不同、廣告與嵌入內容注入的瞬間撐出高度,瀏覽器被迫重排,畫面就往下跳。這個現象有名稱:CLS,累計版面配置位移,量測非預期位移的總量,定義與計算方式見web.dev 的 CLS 專文。
三類構造情境,各對應一種預留手法。無尺寸圖片:補 width 與 height,或用 aspect-ratio 固定比例,讓瀏覽器在檔案抵達前先佔住位置。字體度量差異:設定度量覆寫或挑度量接近的替代字體,縮小換檔瞬間的高度變化。注入式廣告與嵌入:替版位容器預留 min-height,內容抵達時填的是已存在的空間。三種手法講的是同一件事:先讓空間存在,別等內容來了再擠。以常見橫幅版位為例(構造數字),容器先給一個接近實際大小的最小高度,注入那一刻的位移就收在容器內部。
與排名的關係要說得精確:Core Web Vitals 是搜尋評估的眾多訊號之一,CLS 分數良好不保證排名,排名也不只看它。投放期間更直接的成本是誤點與流失:訪客按下按鈕的那一瞬間版面跳動,目標已經移位,點到的是廣告或不相干的連結。
診斷有先後:先查投放的到達頁,再查帶廣告版位的頁面,這兩處的跳版才有商業意義。指標的完整脈絡延伸看Core Web Vitals 與搜尋的關係;載入端的其他改善,看網站速度優化指南。
一份 CSS 服務多個書寫方向
多語系專案的間距為什麼鏡像錯位?因為規則寫死了物理方向:margin-left 寫死的左,在由右至左書寫的語系裡該是右。解法是換座標系,兩套互相覆蓋的樣式可以整個省掉:用 inline 與 block 兩個軸描述間距,讓起訖的對應交給瀏覽器按書寫設定換算。
inline 軸沿著一行文字,block 軸沿著段落堆疊方向。在 writing-mode:horizontal-tb 下,direction:ltr 的 margin-inline-start 對應 margin-left,direction:rtl 則對應 margin-right;padding-block-end 對應 padding-bottom。直書時軸向會改變,應依實際 writing-mode 檢查,不能把 inline 一律解讀成由左到右。

採用時機看專案形態。構造案例(假設情境):同一份版型要服務繁中市場與一個由右至左書寫的市場,標題與內文之間用 margin-inline-end 控制距離,橫排由左到右時它作用在右側,由右至左時自動換到左側,兩個語系共用同一條規則,不需要鏡像覆蓋。跨境電商與多語站先受益;單一語系、固定橫排的專案收益有限,記得判斷點在哪裡就好。水平置中的需求,交給容器的對齊屬性表達,語意比手動分配外距明確。
驗證方式很輕:挑一個用邏輯屬性寫的間距,暫時把容器的 direction 或 writing-mode 換掉,看空間是不是跟著換邊;會換,代表規則真的吃書寫設定,並非只是換了名字的物理屬性。這個檢查也是回頭審視既有樣式的機會:把物理方向寫死的間距列出清單,逐一換成軸向寫法,按頁面權重排先後。
把不明空白追到源頭:開發者工具的走法
判斷卡關時,走法是一條線:選取懷疑的元素,讀計算值面板的盒模型圖與最終數值,讓高亮逐層落在實體空間上,先確認空白歸誰管;查無異常就沿 DOM 往上走,連容器的設定一起看,證據齊了才動手。
流程因症狀而有不同入口:
- 空白型。點選被空白影響的元素,確認空間在元素內側還是外側;高亮不落在元素本體,就往相鄰元素與容器追。
- 爆寬型。看計算值裡兩種口徑的寬度數字,再查 box-sizing 由誰設定、規則來自哪個檔案。
- 間距異常型。量兩個元素之間的實際距離,與兩邊宣告值比對,出現差值就是摺疊或覆蓋,往規則來源追。
兩個常見誤判值得記。把該交給容器的規律間距寫成每個子元素的外距,改一次要動許多處,邊緣還留殘距;被覆蓋規則與快取誤導,畫面上的值來自贏得優先權的那條,原始碼裡改輸的怎麼改都不生效。在面板裡勾掉規則看反應,只是取線索;確診後回原始碼修改,臨時實驗不留現場。
若空白來自父容器的 gap、padding 或對齊方式,只看子元素的 margin 可能找不到原因。沿 DOM 向上檢查容器,將高亮區域、計算值與規則來源一起比對,再把確認有效的修正寫回樣式。

編輯器的間距欄位,轉出來仍是這套規則
用 Elementor、Divi 或區塊編輯器的人,沒有離開 CSS Box Model 這套規則,只是隔了一層包裝。間距欄位轉出來仍是內距與外距,摺疊照樣發生,計算範圍照樣分兩種口徑。判斷路徑回到症狀分層與兩條計算規則,用不著另學一套工具常識。
把欄位讀成屬性就好。看到標了間距、內距、邊界字樣的欄位,先問它寫出來的是內距還是外距;答案在計算值裡,不在欄位名稱的翻譯裡。名稱依版本與語系而異,屬性就那兩個,行為全球一致。
決策主軸是影響範圍。單頁的一次性微調,留在編輯器裡做完;全站的一致性,離開編輯器,寫進佈景的全域樣式或設計系統變數,讓級距只有一處定義。桌機、平板、手機三組數字分開存是方便也是風險,數值一旦各自漂移就難收斂,定期把三組值抄回級距表核對,漂移才看得見。
三種環境的顆粒度不同,選擇前值得各看一圈:Elementor 完整教學、Divi 5 介面解析,以及區塊編輯器與頁面編輯器的比較。顆粒度決定能控制到多細;控制不了的部分,終究要回到樣式本身。
上線前的間距健檢清單
交付或投放之前,跟空間有關的收尾檢查共七項,每項標明在哪裡看、異常長什麼樣。
- 計算口徑。任選幾個元素看 box-sizing 計算值;異常長相是同尺寸元件在不同頁面佔位不一。
- 圖片尺寸屬性。抽範本頁與內容頁的圖片,看有無 width、height 或比例設定;異常長相是滾動中畫面突然下沉。
- 垂直間距。抽幾組上下相鄰的區塊,量實際距離與宣告值;對不上、只剩較大值,就是摺疊在現場。
- 級距一致性。把主要間距數值列出來對級距表;異常長相是大量落在級距外的零碎值。
- 互動目標底線。手機版選導覽、結帳與頁尾的目標,量命中範圍到不到 24 CSS 像素、間隔清不清楚。
- 跳版熱點。走一遍到達頁與廣告版位頁;異常長相是載入中與載入後的構圖位移。
- 行動版呼吸感。小螢幕下看左右留白與段落間距;異常長相是文字貼邊,或留白大到版面空洞。
回到開場那個上線日。三個症狀的答案都在上面:掉版源於計算口徑,誤觸源於命中範圍與間隔,跳版源於空間未預留。判斷順序內化之後,除錯從猜謎變成讀儀表,先分層、再量測、後處置,每一步有數字可看。這份能力不直接換算成排名或轉換數字,但讓每次版面修改都有理由可說。清單走完一遍,跟空間有關的風險大多在部署前就被看過。
要往下累積,版面結構看版面設計的骨架原則,文字節奏看排版設計的間距細節,頁面該有的組成看網頁設計必備元素。空間的歸屬判斷清楚了,後面每一篇都接得上。
常見問題
外距設了 40px,畫面卻只量到 25px,怎麼查?
手機按鈕的最小可點範圍有標準可循嗎?
舊站有必要回頭補全域 border-box 嗎?
padding 的百分比是相對什麼計算的?
編輯器把桌機、平板、手機的間距分開存,影響是什麼?
操作步驟
- 確認專案的 box-sizing 口徑一致:多數專案在樣式表開頭全域套用 border-box(*, *::before, *::after { box-sizing: border-box; });依賴固定內容區寬度的元件(如第三方嵌入)可保留 content-box,但需與協作者約定並標註。
- 打開瀏覽器開發者工具,點選跑掉的元素,在 Computed 面板檢視 content、padding、border、margin 四層實際數值,找出超出預期的層。
- 核對寬度單位:若使用百分比寬度加 padding,確認是否為 content-box 殘留造成的溢出。
- 檢查垂直間距是否被 margin collapse 吃掉,特別是母元素包住第一個子元素或兩個相鄰區塊的情況。
- 確認負值 margin 沒有把鄰近元素拉偏,負值常見於進階排版也是位移的隱形元兇。
- 判斷容器內同類項目是否仍用逐一設定 margin 的方式處理規律間距;若是,評估改用 Flex / Grid 的 gap,讓間距不摺疊、也不殘留於容器邊緣。
- 切換到行動裝置檢視模式重新檢視,確認縮放後的留白節奏沒有失衡。