CSS @container 容器查詢 ( Container Queries )
CSS 的 @container 容器查詢和 @media 媒體查詢類似,都可以在判斷出指定條件時,針對特定的元素套用特定的樣式,但有別於 @media 是根據頁面判斷,CSS 的 @container 是根據「容器」進行判斷,這篇教學會介紹 CSS @container 容器查詢 ( Media Queries ) 的相關用法。
快速導覽:
認識與使用 @container
CSS 的 @container
顧名思義就是針對「容器 container」所定義的 At 規則,透過特定的邏輯判斷,當「容器」符合特定的條件時,就會對「容器裡的元素」套用特定的樣式,使用時需要先建立一個「容器」,只有在容器裡的元素才會套用 @container
所定義的規則。
當元素設定了
container-type
樣式屬性,這個元素就會變成「容器 container」。
下方的範例會在容器寬度大於 400px 時,將 .container
裡的 h2
字體放大 ( .container
設定了 container-type: inline-size;
變成容器類型 )。
<!-- HTML 程式碼 -->
<div class="container">
<h2>apple</h2><h2>banana</h2><h2>oxxo</h2>
</div>
<div>
<h2>apple</h2><h2>banana</h2><h2>oxxo</h2>
</div>
<!-- CSS 程式碼 -->
<style>
@container (width > 400px) {
h2 {font-size: 50px;} /* 容器寬度大於 400px 時,裡面的 h2 會變成 50px */
}
div {
border: 1px solid #000;
margin: 20px;
}
h2 {margin: 0;}
.container {container-type: inline-size;} /* 這個元素變成容器類型 */
</style>
容器類型 container-type
使用 container-type
所建立的容器有下列幾種類型:
容器類型 | 說明 |
---|---|
normal | 預設值,不透過 @container 來判斷處理。 |
inline-size | 由「寬度」定義條件,容器高度由「內容」決定,最常使用的設定。 |
size | 由「寬度與高度」定義條件,容器高度需要「手動」設定。 |
下方的範例使用三個 div
分別表現三種容器類型,可以看出設定 normal
的容器完全不受 @container
影響,設定 inline-size
的容器高度由內容決定,設定 size
的容器沒有高度,導致內容外的 footer
元素和容器內容重疊。
<!-- HTML 程式碼 -->
<div class="notmal">
<h2>container-type: normal;</h2>
</div>
<div class="inline-size">
<h2>container-type: inline-size;</h2>
</div>
<div class="size">
<h2>container-type: size;</h2>
</div>
<footer>我是結尾</footer>
<!-- CSS 程式碼 -->
<style>
@container (width > 400px) {
h2 {font-size: 50px;}
}
div {
border: 1px solid #000;
margin: 20px 0;
}
h2 {margin: 0;}
footer {background: #f005;}
.notmal {container-type: normal;}
.inline-size {container-type: inline-size}
.size {container-type: size;}
</style>
容器名稱 container-name
如果網頁中有多個容器,則可以使用 container-name
替容器命名,並在 @container
中針對特定名稱的容器定義樣式,容器名稱可以使用英文字母大小寫、阿拉伯數字、連結線、底線 ( 開頭不為數字 ),寫法為:
@container 名稱 ( 判斷 ) {
......
}
下方範例會將三個 div
設定為容器,並分別命名為「aaa、bbb、ccc」,接著使用 @container
設定在不同寬度時會放大與變色。
<!-- HTML 程式碼 -->
<div class="rr">
<h2>寬度 > 500px 時,變紅變大</h2>
</div>
<div class="bb">
<h2>寬度 > 450px 時,變藍變大</h2>
</div>
<div class="gg">
<h2>寬度 > 400px 時,變綠變大</h2>
</div>
<!-- CSS 程式碼 -->
<style>
@container rrr (width > 500px) {
h2 {
color: red;
font-size: 30px;
}
}
@container bbb (width > 450px) {
h2 {
color: blue;
font-size: 30px;
}
}
@container ggg (width > 400px) {
h2 {
color: green;
font-size: 30px;
}
}
div {
border: 1px solid #000;
margin: 20px 0;
container-type: inline-size;
}
h2 {margin: 0;}
.rr {container-name: rrr;} /* 這個元素的容器名稱為 rrr */
.gg {container-name: ggg;} /* 這個元素的容器名稱為 ggg */
.bb {container-name: bbb;} /* 這個元素的容器名稱為 bbb */
</style>
容器縮寫格式 container
container
樣式為 container-name
和 container-type
的縮寫格式,使用「斜線 /」分隔這兩個樣式屬性的屬性值,如果只有一個屬性值則代表 container-name
,相關寫法如下:
div {
container: container-name / container-type; /* 名稱在前,類型在後 */
container: container-name;
}
下方範例會將前一個小節的範例,改成 container
的寫法。
<!-- HTML 程式碼 -->
<div class="rr">
<h2>寬度 > 500px 時,變紅變大</h2>
</div>
<div class="bb">
<h2>寬度 > 450px 時,變藍變大</h2>
</div>
<div class="gg">
<h2>寬度 > 400px 時,變綠變大</h2>
</div>
<!-- CSS 程式碼 -->
<style>
@container rrr (width > 500px) {
h2 {
color: red;
font-size: 30px;
}
}
@container bbb (width > 450px) {
h2 {
color: blue;
font-size: 30px;
}
}
@container ggg (width > 400px) {
h2 {
color: green;
font-size: 30px;
}
}
div {
border: 1px solid #000;
margin: 20px 0;
}
h2 {margin: 0;}
.rr {container: rrr / inline-size;} /* 這個元素的容器名稱為 rrr */
.gg {container: ggg / inline-size;} /* 這個元素的容器名稱為 ggg */
.bb {container: bbb / inline-size;} /* 這個元素的容器名稱為 bbb */
</style>
容器查詢語法 ( 媒體 media queries )
@container
最基本的查詢撰寫方式與 @media
類似,可以根據瀏覽器的寬高、尺寸比例等媒體訊息進行判斷,判斷時可使用「or、and、not」等邏輯判斷語法,邏輯判斷的條件基本上和 @media
的「媒體特色 ( Media Features )」相同,下方列出支援的寫法:
@container (條件) {...} /* 滿足單一條件 */
@container (條件 1), (條件 2) {...} /* 滿足條件 1 或條件 2 其中一項 ( or 寫法 ) */
@container (條件 1) and (條件 2) {...} /* 同時滿足條件 1 與條件 2 ( and 寫法 ) */
@container not (條件) {...} /* 不滿足單一條件,不可與 and 和 or 混用 */
下方範例使用四個容器,分別呈現四種不同的查詢語法。
<!-- HTML 程式碼 -->
<div class="rr">
<h2>寬度 > 500px 時,變紅變大</h2>
</div>
<div class="bb">
<h2>寬度 > 500px 或寬度 < 400px 時,變藍變大</h2>
</div>
<div class="gg">
<h2>寬度 > 400px 且寬度 < 500px 時,變綠變大</h2>
</div>
<div class="oo">
<h2>寬度沒有 > 400px 時,變橘變大</h2>
</div>
<!-- CSS 程式碼 -->
<style>
@container rrr (width > 500px){
h2 {
color: red;
font-size: 30px;
}
}
@container bbb (width > 500px) or (width < 400px) {
h2 {
color: blue;
font-size: 30px;
}
}
@container ggg (width > 400px) and (width < 500px) {
h2 {
color: green;
font-size: 30px;
}
}
@container ooo not (width > 400px) {
h2 {
color: orange;
font-size: 30px;
}
}
div {
border: 1px solid #000;
margin: 20px 0;
container-type: inline-size;
}
h2 {margin: 0;}
.rr {container-name: rrr;}
.gg {container-name: ggg;}
.bb {container-name: bbb;}
.oo {container-name: ooo;}
</style>
容器查詢語法 ( 樣式 style queries )
@container
除了可以根據媒體的狀態將容器套用對應樣式,也可以使用 style()
樣式查詢的方式,「判斷容器是否具有特定樣式」,進而套用指定的樣式,查詢判斷可以和媒體狀態互相搭配,並使用「or、and、not」等邏輯判斷語法,關寫法如下:
注意,目前這個查詢語法「只支援變數和自訂屬性」,且一個
style()
裡只能放入一組樣式,若判斷具有該樣式則回傳 true,沒有則回傳 false。
/* 目前不支援,未來可能支援的寫法 */
@container style(color: red) {...} /* 容器具有 color: red */
@container style(color: red) and style(font-size: 20px) {...} /* 容器同時具有 color: red 和 font-szie: 20px */
/* 目前支援 */
@container style(--oxxo: true) {...} /* 容器具有變數 --oxxo: true 樣式和屬性值 */
@container style(--a: 1) and style(--b: 2) {...} /* 容器同時變數 --a: 1 和 --b: 2 樣式和屬性值 */
下方範例使用四個容器,呈現使用 style()
的查詢語法。
<!-- HTML 程式碼 -->
<div class="r">
<h2>變紅 style(--oxxo: 1)</h2>
</div>
<div class="g">
<h2>變綠 style(--oxxo: 1) and style(--xoox: 1)</h2>
</div>
<div class="b">
<h2>變藍 style(--oxxo: 1) and style(--xoox: 2)</h2>
</div>
<div class="o">
<h2>沒有設定不會變色</h2>
</div>
<!-- CSS 程式碼 -->
<style>
@container style(--oxxo: 2){
h2 {background: orange;} /* 如果容器裡有 --oxxo: 2 */
}
@container style(--oxxo: 1){
h2 {color: red;} /* 如果容器裡有 --oxxo: 1 */
}
@container style(--oxxo: 1) and style(--xoox: 1){
h2 {color: green;} /* 如果容器裡有 --oxxo: 1 和 --xoox: 1 */
}
@container style(--oxxo: 1) and style(--xoox: 2){
h2 {color: blue;} /* 如果容器裡有 --oxxo: 1 和 --xoox: 2 */
}
div {
container-type: inline-size;
}
.r {
--oxxo: 1;
}
.g {
--oxxo: 1;
--xoox: 1;
}
.b {
--oxxo: 1;
--xoox: 2;
}
div[class]:hover {
--oxxo: 2; /* 滑鼠移動到 .r .g .b 三個 div 上方時, --oxxo 改為 2 */
}
</style>
容器查詢特殊單位
當元素轉換成容器後,在元素裡就可以使用下方列出的特殊單位:
單位 | 說明 |
---|---|
cqw | 1% container 的 width。 |
cqh | 1% container 的 height。 |
cqi | 1% container 的 inline-size。 |
cqb | 1% container 的 block-size。 |
cqmin | cqi 與 cqb 的最小值。 |
cqmax | cqi 與 cqb 的最大值。 |
<!-- HTML 程式碼 -->
<div class="rr">
<h2>寬度 > 400px 時,變紅,尺寸為容器的一半</h2>
</div>
<div class="bb">
<h2>寬度 > 400px 時,變藍,尺寸為容器的 80%</h2>
</div>
<div class="gg">
<h2>寬度 > 400px 時,變綠</h2>
</div>
<!-- CSS 程式碼 -->
<style>
@container rrr (width > 400px) {
/* 注意前方使用 div h2 避免權重被後方覆蓋 */
div h2 {
color: red;
width: 50cqi;
}
}
@container bbb (width > 400px) {
/* 注意前方使用 div h2 避免權重被後方覆蓋 */
div h2 {
color: blue;
width: 80cqi;
}
}
@container ggg (width > 400px) {
div h2 {color: green;}
}
div {
border: 1px solid #000;
margin: 20px 0;
container-type: inline-size;
}
h2 {
margin: 0;
width: 200px;
background: orange;
}
.rr {container-name: rrr;} /* 這個元素的容器名稱為 rrr */
.bb {container-name: bbb;} /* 這個元素的容器名稱為 bbb */
.gg {container-name: ggg;} /* 這個元素的容器名稱為 ggg */
</style>
小結
@container
是一個新的 CSS 定義,在舊版的瀏覽器或部分ㄓ Firebox 上並不支援,但如果不考慮這些瀏覽器,@container
對於 RWD 響應式網頁而言,是個相當不錯的功能,如果有機會不妨使用看看吧。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~