CSS Container Query 版面巡檢:把卡片寬度、圖片比例與內容密度留成證據

內容網站常見的 RWD 問題,不一定來自整個 viewport,而是來自「某個模組被放到不同容器後失去比例」。同一張文章卡片在首頁 Hero 旁邊、Blog 列表、分類頁或側欄中,可能拿到完全不同的可用寬度。這時只靠 @media 斷點會越寫越多,因為真正需要反應的是容器,不是螢幕。
CSS Container Query 可以讓卡片依照父層容器調整圖片比例、標題行數、摘要顯示與 CTA 密度。不過它不是導入後就自動變好的魔法。對 UCAMC 這類長期內容站,我會把 Container Query 視為一個需要留證據的版面變更:先記錄目前問題,再套用最小 CSS,最後確認桌面、平板、手機與 Blog 卡片都沒有破版。
先記錄容器,而不是只記錄 viewport
導入前先把問題說清楚。不要只寫「手機版不好看」,而是記錄哪一個容器、哪一張卡片、哪一段文字造成密度或 overflow。
Observe
- page: /blog
- module: post-list-card
- viewport: 390px
- container width: 342px
- symptom: title wraps to 4 lines and pushes CTA below fold
- image: 16:9 is fine, but excerpt is too long for narrow card
如果問題發生在首頁最新文章卡片,也要另外記錄,因為首頁 grid 的容器寬度可能跟 /blog 完全不同。
Observe
- page: /
- module: latest-grid .post-card
- viewport: desktop 1440px
- container width: 368px
- symptom: card height differs because excerpt length varies
這些資料會決定要用 Container Query、一般 media query,還是單純調整內容摘要。
最小可回滾的 CSS 寫法
比較安全的做法,是先讓卡片成為容器,再針對卡片內部元素調整,而不是重寫整個 layout。
.post-card,
.post-list-card {
container-type: inline-size;
container-name: article-card;
}
@container article-card (max-width: 360px) {
.post-card h2,
.post-list-card h2 {
font-size: 1.05rem;
line-height: 1.35;
}
.post-card p,
.post-list-card p {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
我會避免一開始就把所有卡片高度寫死。內容站的文章標題本來就有長短,過度固定高度容易讓中文標題被切得不自然。先處理最明顯的密度問題,再用實際頁面驗收。
圖片比例也要跟著巡檢
Container Query 常被拿來調整文字,但卡片圖片也需要一起看。首頁精選卡、Blog 列表卡與分類頁卡片如果共用資料來源,至少要確認這三件事:
coverImage或featuredImage是否存在。coverAlt是否描述文章主題,而不是泛用圖片文字。- 圖片容器是否維持穩定比例,載入後不造成 layout shift。
可以把圖片驗收寫成這樣:
Image evidence
- file: /images/blog/frontend-css-container-query-layout-audit-cover.png
- response: 200 image/png
- rendered article image: naturalWidth > 0
- Blog card: image is visible and object-fit cover
- OG image: meta property og:image points to the same topic image
這份紀錄比「有一張圖」更有價值,因為它同時檢查了內容、品牌與 SEO 顯示。
手機驗收:先找 page-level overflow
手機版最容易誤判。程式碼區塊、長英文 tag、URL 或表格,都可能在局部超出;但真正會影響讀者的是整頁是否產生水平捲動。驗收時我會先看 page-level,再看局部可捲動區塊。
const root = document.documentElement;
const pageOverflow = root.scrollWidth > root.clientWidth;
const offenders = [...document.querySelectorAll('main *')]
.map((node) => {
const rect = node.getBoundingClientRect();
return {
tag: node.tagName,
className: node.className,
right: Math.round(rect.right),
width: Math.round(rect.width),
};
})
.filter((item) => item.right > root.clientWidth + 1);
若 pre 內的 code 比容器寬,且 pre 本身可以水平捲動,這通常不是整頁破版。反過來說,如果 documentElement.scrollWidth 大於 clientWidth,就要先處理造成整頁 overflow 的元素。
驗收表:Observe / Change / Verify
我會把 Container Query 改動寫成三段,方便未來回頭查:
Observe
- Blog card at 390px: title and excerpt create dense layout
- No root route issue; problem is presentation only
Change
- Add container-type to article cards
- Clamp excerpt only inside narrow card containers
- Keep desktop card typography unchanged
Verify
- / returns 200
- /blog returns 200 and latest card remains readable
- /frontend-css-container-query-layout-audit returns 200
- 390px page scrollWidth equals clientWidth
- cover image and og:image both use topic-specific image
這樣的紀錄能避免兩種常見錯誤:一是把 layout 小問題擴大成整站改版;二是只看桌面截圖就宣布手機版完成。
什麼情況不要急著用 Container Query
Container Query 很好用,但不是每個問題都該用它解。以下情況我會先選別的方法:
- 問題只發生在單一文章標題太長:先調整 Hero 可見標題或摘要。
- 問題來自圖片主題不符:先換對應文章主題的 cover。
- 問題是全站主要內容字級太小:先做 main content typography 規則。
- 問題是舊文章 Markdown 有超長裸露 URL:先做內容整理或 code block 換行。
Container Query 最適合解決「同一元件在不同容器寬度下需要不同密度」的問題。只要這個前提成立,它就能讓內容站的卡片更穩定,也更容易長期維護。
結語
對技術 Blog 來說,前端版面不是只追求漂亮,而是要讓讀者在首頁、Blog 列表、分類頁與文章頁都能穩定閱讀。Container Query 的價值在於讓元件回應自己的空間;維護者的責任則是把導入前後的證據留下來。
下一次調整卡片或首頁模組時,不妨先問:這是 viewport 問題,還是 container 問題?如果答案是後者,就用小範圍 Container Query 加上 route、圖片、OG 與手機 overflow 驗證,讓版面改善成為可追蹤的維護紀錄。