同一張卡片放在主內容很寬,放進側欄卻擠成一團,單靠視窗寬度不一定夠。使用@container可以按祖先容器的可用寬度決定排版,讓卡片在寬區橫排、窄區直排,即使它們出現在同一個桌面視窗裡。
這適合會重用的模板卡片、作者資訊或相關文章元件。視窗可以是1000px,主內容容器有600px,側欄卻只有260px;若兩者都套同一條桌面media query,窄卡片就可能被迫使用不合適的橫排。先分清「視窗夠寬」與「元件實際得到多少寬度」,再選擇響應式條件。
在外層建立可查詢容器
<div class="host wide">
<article class="card">
<div class="picture"></div>
<div>主內容卡片</div>
</article>
</div>
<div class="host narrow">
<article class="card">
<div class="picture"></div>
<div>側欄卡片</div>
</article>
</div>
.host { container-type: inline-size; }
.wide { width: 600px; }
.narrow { width: 260px; }
.card {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
padding: 12px;
}
.picture { height: 70px; background: #618a76; }
@container (min-width: 400px) {
.card { grid-template-columns: 140px 1fr; }
}
預設卡片是一欄,圖片與文字上下排。當符合條件的祖先容器至少400px寬,才改成140px與剩餘空間兩欄。這裡400是示範的排版分界,不是所有卡片都應使用的固定值;你應按圖片、文字和間距實際需要決定。
外層host負責提供尺寸條件,內部card負責改變佈局。不要把需要按自身寬度變換的元素同時當成它自己的查詢目標,期待它依自己的尺寸套規則。尺寸查詢選擇的是合適的祖先容器,保持一層清楚的外部容器會比較容易排查。
同一視窗實際比較兩個容器
在Chromium154、視窗寬1000px的獨立頁面,600px host裡的卡片顯示兩欄,260px host裡的卡片顯示一欄。接著只把原本600px的host改成300px,不改視窗,卡片就從兩欄回到一欄。這正是容器查詢與視窗條件的差別。
示範頁給卡片12px內距與12px欄間距,600px容器下的計算列寬為140px和424px;260px容器則是一列236px。把前者改成300px後,單列為276px。這些數字用來核對測試頁面,並不代表你的網站必須出現同樣列寬。
const card = document.querySelector('.card');
console.log(getComputedStyle(card).gridTemplateColumns);
檢查你的元件時,可以對照容器實際寬度與計算後的列寬。如果規則沒生效,先看host有沒有container-type,再看card是否真在那個祖先裡、條件是否達到。不要一開始就把400改成更小,讓規則勉強觸發卻把窄側欄再次擠壞。
查詢容器的選擇要清楚
未命名的查詢會尋找符合條件的祖先容器。如果版型內部又新增一層container-type,查詢可能對應到與你原本想像不同的層。重用元件時,這種變化很容易發生,所以應檢查最終DOM與計算樣式,而不只看元件檔案。
需要指定用途時,可以給容器一個清楚的名稱,再讓規則查詢該名稱。名稱不會替你建立尺寸查詢能力,container-type仍要正確設定。也不要為每個細小區塊都隨意建立容器,讓後續維護者難以判斷哪一層真正負責寬度。
.host {
container-name: article-card;
container-type: inline-size;
}
@container article-card (min-width: 400px) {
.card { grid-template-columns: 140px 1fr; }
}
inline-size適合這類按橫向可用寬度調整的例子。不要只為使查詢可用就把它改成更強的size限制,忽略高度佈局會受到影響。選擇容器類型要對應你實際要查詢的尺寸,先保持最小需要的設定。
media query仍負責視窗層級的變化
容器查詢並不是要求你把所有media query移除。整頁導覽什麼時候變成摺疊、主欄與側欄什麼時候上下排列,仍可以按視窗條件處理;卡片內部的橫排或直排,再按它拿到的容器寬度處理。
把兩者職責分開後,同一個元件放進不同區域就比較容易重用。你不必為每個頁面複製一套「這個卡片在這個桌面尺寸應幾欄」的規則,也不需要在JavaScript裡反覆讀視窗寬度替卡片加類名。先用CSS表達明確的尺寸條件即可。
容器本身的寬度仍來自外部佈局。示範為方便觀察寫了600px與260px,實際模板通常由grid、flex或父容器分配空間。不要照抄固定寬度到手機頁面,造成橫向溢出;保留真實頁面的寬度規則,只在合適的外層建立查詢容器。
先保留能讀的基礎排版
預設一欄可以讓不支援這項功能的環境仍讀到圖片與內容,而支援容器查詢時再增強成橫排。這只是這個元件的漸進設計選擇,不是保證所有舊瀏覽器版型一致。上線前應核對目標瀏覽器的支援情況,並在需要時提供合適的替代規則。
也要測試特別長的標題和沒有圖片的卡片。容器寬度達標,不代表內容一定適合固定圖片欄;文字換行、連結長度和實際圖片比例仍要按原規則處理。不要把容器查詢當成自動修復所有溢出的工具。
如果元件還有展開內容、按鈕或狀態提示,寬窄切換後應保持閱讀與操作順序。這篇只是改CSS列佈局,不應該為了橫排順手倒置DOM,讓畫面和鍵盤路線分離。以同一份合理的內容順序調整排版,通常更容易保持操作一致。
用寬窄兩份容器驗收
邊界附近也值得觀察。例如容器在399px與400px之間切換時,橫排之後的文字是否仍有足夠空間,圖片欄是否使標題只剩一兩個字。如果剛達到條件就明顯擁擠,說明分界應該按內容需要調整,而不是堅持示例的400px。把測試標題換成真實長度,也比較容易選出合適的條件。
不要在規則裡用外層很寬的假容器包住一個其實很窄的卡片,只為了讓查詢觸發。查詢容器應代表元件實際獲得的可用空間;如果中間還有固定寬度或內距,讓這兩者差異很大,先整理結構,再決定在哪一層建立容器。否則條件看似正確,實際卡片仍可能擠成一團。
如果頁面同時使用多個命名容器,保留與元件用途相關的名稱,並把對應規則放在容易找到的位置。名稱不是全站獨一無二的id,但匹配仍要有清楚的約定。複製元件時核對它會找到哪個祖先,避免一個同名內層無意間改變原本的尺寸來源。
瀏覽器縮放、較大的文字設定與不同字型也可能改變內容需要的空間。容器寬度條件仍會按佈局計算,但是否讀得舒服要靠實際內容判斷。驗收時至少看一份長標題和一份正常標題,確認窄容器不會把重要文字藏到看不見的位置。
在同一頁面放一份寬容器與一份窄容器,再改變其中一份寬度,確認只有對應元件調整。這比單獨把視窗縮小更能證明規則真的按container工作。也檢查命名容器是否選對、預設一欄是否清楚、切換時有沒有橫向捲動。
最後回到模板實際使用的主內容、側欄和彈出區域各測一次,保存適合該功能的尺寸與畫面。這組1000/600/260px是合成案例,正式頁面可能有不同空間;按真實容器做驗收,才能知道元件是否在每個放置位置都能讀和操作。

評論0