容器查询 ( @container )
CSS 的 @container 容器查询和 @media 媒体查询类似,都可以在判断出指定条件时,针对特定的元素套用特定的样式,但有别于 @media 是根据页面判断,CSS 的 @container 是根据“容器”进行判断,这篇教学会介绍 CSS @container 容器查询 ( Container Queries ) 的相关用法。
快速导览:
教学影片
搭配教学影片一起阅读,效果会更好!欢迎大家订阅 STEAM 教育学习网的 Youtube 频道。
认识与使用 @container
CSS 的 @container 顾名思义就是针对“容器 container”所定义的 At 规则,透过特定的逻辑判断,当“容器”符合特定的条件时,就会对“容器里的元素”套用特定的样式,使用时需要先建立一个“容器”,只有在容器里的元素才会套用 @container 所定义的规则,建立容器后,和 @media 一样都会遵循“权重”的规则。
当元素设定了
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 | 默认值,这个元素不是容器类型。 |
| 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 的“媒体特色 ( Media Features )”类似,可以根据浏览器的宽高、尺寸比例等媒体消息进行判断,判断时可使用“or、and、not”等逻辑判断语法,下方列出支援的写法:
@container和@media在查询语法中最大的不同,就是@container可以使用“<、>、=”等判断符号,其中用“=”符号和“:”功能相同。
@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>
容器查询特殊单位
当元素转换成容器后,在元素里就可以使用下方列出的特殊单位:
- 如果无法读取容器宽高,就会使用“视窗”的宽高。
- 如果要读取“高度”,则容器必须设定为“size”并手动设定宽高。
| 单位 | 说明 |
|---|---|
| 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 定义,在旧版的浏览器或部分浏览器上并不支援,但如果不考虑这些浏览器,@container 对于 RWD 响应式网页而言,是个相当不错的功能,如果有机会不妨使用看看吧。
微信扫码关注
抖音扫码关注