CSS容器查詢獲得主流瀏覽器支持,是什么?怎么用?
近期,主流瀏覽器終于都支持了 CSS 容器查詢功能:

在引入響應(yīng)式設(shè)計(jì)之前,許多公司通過(guò)提供不同的站點(diǎn)來(lái)處理基于屏幕尺寸更改布局的問(wèn)題。2010 年,Ethan Marcotte 引入了響應(yīng)式設(shè)計(jì)的概念。響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)的理念是設(shè)計(jì)和開(kāi)發(fā)應(yīng)根據(jù)屏幕尺寸、設(shè)備和方向響應(yīng)用戶的行為和環(huán)境。這個(gè)想法實(shí)現(xiàn)的核心就是 CSS 媒體查詢,它允許根據(jù)視口的大小設(shè)置各種布局規(guī)則。

如今,開(kāi)發(fā)人員通常使用基于組件的 JavaScript 框架(如 React、Vue 等)以及 CSS 框架(如 Tailwind CSS、Material UI 和 Bootstrap)來(lái)制作響應(yīng)式和可重用的布局和應(yīng)用。一種新的響應(yīng)式設(shè)計(jì)方法出現(xiàn)了——容器查詢,容器查詢可以根據(jù)組件的大小或樣式而不是設(shè)備的視口直接查詢組件。
媒體查詢的問(wèn)題?
在介紹容器查詢之前,先來(lái)看看媒體查詢的概念。通常網(wǎng)頁(yè)由不同的組件組成,我們可以通過(guò)使用 CSS 媒體查詢使它們具有響應(yīng)性。但是它是有局限性的。例如,可以使用媒體查詢?cè)谝苿?dòng)設(shè)備和桌面設(shè)備上顯示組件的最小版本。
通常,響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)與視口或屏幕尺寸無(wú)關(guān),而是于容器的大小有關(guān)。來(lái)看下面的例子:

這里是一個(gè)非常經(jīng)典的帶有卡片組件布局,這里有兩種顯示形式:左側(cè)的堆疊式和右側(cè)的平鋪式。
這在CSS 中有多種實(shí)現(xiàn)方法,最常見(jiàn)的方法如下所示。我們需要?jiǎng)?chuàng)建一個(gè)基礎(chǔ)組件,然后對(duì)其進(jìn)行媒體查詢:
這里創(chuàng)建了 .c-article--horizontal? 類(lèi)來(lái)處理組件的平鋪部分,如果視口寬度大于 46rem,則組件應(yīng)切換到平鋪模式。這確實(shí)可以實(shí)現(xiàn)預(yù)期的效果,但是有局限,我們希望組件根據(jù)其父級(jí)寬度進(jìn)行變化,而不是瀏覽器的視口或屏幕尺寸。
可以用 CSS 容器查詢來(lái)實(shí)現(xiàn)這個(gè)布局。我們需要當(dāng)右側(cè)區(qū)域的父級(jí)大于 400px 時(shí)切換到平鋪模式:
使用容器查詢,就可以在將組件放入窄的父組件中,它會(huì)變成堆疊版本,將組件放入寬的父組件中,它會(huì)變成平鋪版本,所有這些都與視口寬度無(wú)關(guān)。

上面的代碼只是簡(jiǎn)單的實(shí)現(xiàn),下面就來(lái)看看 CSS 容器查詢特性是如何使用的!
什么是容器查詢?
容器是包含另一個(gè)元素的元素。因此,簡(jiǎn)單來(lái)說(shuō),CSS 容器查詢就是指定元素相對(duì)于其父容器或元素的更改,而不是整個(gè)視口。
因此,仍然可以使用響應(yīng)式網(wǎng)格來(lái)進(jìn)行整體頁(yè)面布局,但該網(wǎng)格中的組件可以通過(guò)查詢其容器來(lái)定義自己的行為變化。然后,它可以根據(jù)它是在窄容器還是寬容器中顯示來(lái)調(diào)整其樣式。
容器查詢能夠以非常精確和可預(yù)測(cè)的方式定義組件的全部樣式,例如:增加或減少padding、更改字體大小、添加或刪除背景圖片,或者更改子元素的 display 屬性和方向。

如何使用容器查詢?
容器查詢中的“容器”就是被查詢的元素,但是容器查詢中規(guī)則僅影響后代元素。容器查詢將允許定義這些元素如何在容器大小之間變化的規(guī)則。
容器查詢語(yǔ)法
要想設(shè)置容器查詢,需要給被查詢的元素設(shè)置 container-type 屬性來(lái)指定容器的類(lèi)型。語(yǔ)法如下:
container-type 屬性有以下屬性值:
- size:創(chuàng)建一個(gè)查詢?nèi)萜鳎С謨?nèi)聯(lián)軸和塊軸維度上進(jìn)行查詢。
- inline-size:創(chuàng)建一個(gè)查詢?nèi)萜鳎С衷趦?nèi)聯(lián)軸(文本流方向)維度上進(jìn)行查詢,這是最常用的選項(xiàng)。
- block-size:創(chuàng)建一個(gè)查詢?nèi)萜鳎С衷趬K軸維度上維度查詢。
- style:允許通過(guò)定義查詢?nèi)萜鬟M(jìn)行樣式查詢。
- state:允許通過(guò)定義查詢?nèi)萜鬟M(jìn)行狀態(tài)查詢。
例如:
我們可以使用 container-name 屬性為容器指定一個(gè)名稱,以區(qū)分具有唯一名稱的容器。
現(xiàn)在,我們就可以使用 card 為對(duì)應(yīng)容器定義容器查詢:
這樣,定義的容器查詢樣式就不會(huì)干擾到其他容器,只會(huì)對(duì)指定的容器生效。
我們可以使用 container? 來(lái)簡(jiǎn)寫(xiě) container-type? 和 container-name 屬性,格式如下:
下面來(lái)看一個(gè)例子:
這里我們給 main? 標(biāo)簽定義了一個(gè) container? 類(lèi),它將作為容器查詢中的容器。接下來(lái),可以設(shè)置一個(gè)容器查詢來(lái)更改文章及其任何后代,這些樣式將基于 main 的寬度發(fā)生改變。使用容器查詢會(huì)隨著容器的增長(zhǎng)而改變樣式。
這里的代碼很簡(jiǎn)單,當(dāng)容器 container? 的寬度達(dá)到 60ch 時(shí),就增大 padding? 和 font-size 的值。
- min-width?:當(dāng)容器的大于或等于指定的寬度時(shí),min-width 定義的樣式會(huì)生效;
- max-width?:當(dāng)容器的小于或等于指定的寬度時(shí),max-width 定義的樣式會(huì)生效;
- @container:檢測(cè)元素的父元素何時(shí)更改寬度,并指定每次寬度更改時(shí)要在子元素中進(jìn)行哪些更改。
容器查詢長(zhǎng)度單位
除此之外,容器查詢還引入了幾個(gè)專(zhuān)用的長(zhǎng)度單位,當(dāng)使用容器查詢將樣式應(yīng)用于容器時(shí),可以使用容器查詢長(zhǎng)度單位。這些單位指定相對(duì)于查詢?nèi)萜鞒叽绲拈L(zhǎng)度。使用相對(duì)于其容器的長(zhǎng)度單位的組件可以更靈活地用于不同的容器,而無(wú)需重新計(jì)算具體的長(zhǎng)度值。
容器查詢長(zhǎng)度單位包含:
- cqw:查詢?nèi)萜鲗挾鹊?1%
- cqh:查詢?nèi)萜鞲叨鹊?1%
- cqi:查詢?nèi)萜鲀?nèi)聯(lián)大小的 1%
- cqb:查詢?nèi)萜鲏K大小的 1%
- cqmin:cqi? 或 cqb 中較小的值
- cqmax:cqi? 或 cqb 中較大的值
下面來(lái)看一個(gè)例子,根據(jù)容器的大小來(lái)設(shè)置二級(jí)標(biāo)題的字體大小:
容器元素選擇器規(guī)則
上面我們說(shuō)過(guò),容器本身是不能在容器查詢中設(shè)置樣式的(除非它是嵌套容器并響應(yīng)其祖先容器的查詢)。但是,容器可以用作其子項(xiàng)的 CSS 選擇器的一部分。
這有什么作用嗎?這樣的話,就可以保留對(duì)可能需要源自容器的 CSS 偽類(lèi)和選擇器的訪問(wèn),例如 :nth-child。
舉個(gè)例子
卡片布局
下面來(lái)看一個(gè)卡片布局的例子:
當(dāng)有四個(gè)元素時(shí),是這樣的:

卡片的數(shù)量減少時(shí),由于我們使用了 auto-fit 屬性,卡片的寬度就會(huì)變寬。

這看起來(lái)太寬了,影響了視覺(jué)效果。如果每個(gè)卡片的布局能根據(jù)父元素的寬度來(lái)設(shè)置就太好了,這時(shí)就可以使用容器查詢:
效果如下:

這樣就得到了一個(gè)根據(jù)父級(jí)寬度進(jìn)行樣式響應(yīng)的卡片組件。
表單布局
下面再來(lái)看一個(gè)表單的例子,當(dāng)表單所在容器寬度不同時(shí),分別顯示為水平或堆疊模式。

可以用容器查詢輕松實(shí)現(xiàn)該布局:
完成了這個(gè)樣式,可以給父元素添加一個(gè)resize屬性,使其大小可變,以測(cè)試容器查詢是否生效:

使用容器查詢完美實(shí)現(xiàn)了預(yù)期效果!
調(diào)試容器查詢
目前 Chrome DevTools 中已經(jīng)支持檢查和調(diào)試容器查詢。在 Elements 中,容器元素后面會(huì)顯示 container 標(biāo)志:

當(dāng)容器滿足查詢條件時(shí),可以檢查@container應(yīng)用于后代的規(guī)則:

當(dāng)鼠標(biāo)懸浮在父元素(div.form-item)上時(shí),就會(huì)顯示當(dāng)前父元素的寬度:

參考:
[1] https://ishadeed.com/article/say-hello-to-css-container-queries/
[2] https://developer.chrome.com/en/blog/devtools-tips-9/
[3] https://web.dev/cq-stable/?





















