CSS Container Queries

CSS

最近在 Chrome Canary 中支持了一项新的 CSS 语法:Container Queries,相比 Media Queries 有了更丰富的使用场景。

Chrome Canary: 开发者专用的每日构建版,站上网络科技最前沿(注意:Canary 版可能还不稳定)。

Media 查询的问题

我们经常用枚举查询来实现响应式页面:

1
@media screen and (min-width: 750px) and (max-width: 1200px) { ... }

比如现在要实现这样一个效果:

我们有一张卡片(Card),Card 的宽度能够自适应,且 Card 在屏幕宽度足够的时候,Title 与 Description 在同一行;在屏幕宽度不够的时候(间接导致卡片宽度不够),Title 能够与 Description 呈上下结构,以达到卡片布局的响应式。

即在卡片空间足够时,是这样的效果:

css-container-queries__media-card-demo-1

在卡片空间不够时,是这样的:

css-container-queries__media-card-demo-2

为了要实现这样的自适应效果,我们可能会这样写:

1
2
3
4
5
6
7
8
<div class="body">
<div class="content">
<div class="card">
<div class="card-title">Card Title</div>
<div class="card-desc">Card Description</div>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.body {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
display: flex;
}

.content {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}

.card {
width: 50%;
height: 200px;
border-radius: 4px;
background-color: #1d1d1d;
color: white;
display: flex;
align-items: center;
justify-content: center;
}

.card-title {
font-size: 18px;
font-weight: 700;
margin-right: 8px;
}

.card-desc {
opacity: .8;
}

@media screen and (max-width: 750px) {
.card {
flex-direction: column;
}
}

拉伸屏幕看了下效果,计划通。

这种做法能处理大部分屏幕适配问题,但响应式布局有时并不只依赖屏宽的变化,比如在上面的基础上,我们加入一个可展开收起的侧导,并希望卡片能够继续做到响应式:即在侧导展开时,能够以上下结构呈现内容;而在侧导收起时(空间更大了),卡片能够以左右结构呈现内容。

有侧导:

css-container-queries__media-sidebar-demo-1

无侧导:
css-container-queries__media-sidebar-demo-2

演示 Demo

当我们想再次去写 media 查询的时候,发现事情不太对…

侧导展开收起的时候,屏宽并没有变化呀!这时 media 查询就受到了限制,这时你发现,更好的响应式方案,不应该只针对屏幕宽度去做枚举,而是要去对容器宽度去做枚举,这时 Container Queries 就诞生了。

Container Queries

css-container-queries__intro

还是刚才的卡片例子,如果要用容器查询,该怎么实现呢?

两个注意点:

  1. 实验前需要在 Chrome Canary 中输入 chrome://flags/#enable-container-queries 找到容器查询的设置,并将其置为 Enabled 后才可生效
  2. 在使用 @container 时,父容器需要指定 contain 属性以开启 container 查询,如:contain: layout inline-size;

样例代码:

1
2
3
4
5
6
7
8
9
<div class="body">
<div class="sidebar">Foldable Sidebar</div>
<div class="content">
<div class="card">
<div class="card-title">Card Title</div>
<div class="card-desc">Card Description</div>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
.body {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
display: flex;
}

.sidebar {
position: relative;
width: 200px;
height: 100%;
background: #2d2d2d;
color: white;
display: flex;
justify-content: center;
align-items: center;
resize: horizontal;
overflow: auto;
}

.content {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
contain: layout inline-size; /* Required! */
}

.card {
width: 50%;
height: 200px;
border-radius: 4px;
background-color: #1d1d1d;
color: white;
display: flex;
align-items: center;
justify-content: center;
}

.card-title {
font-size: 18px;
font-weight: 700;
margin-right: 8px;
}

.card-desc {
opacity: .8;
}

@container (max-width: 600px) {
.card {
flex-direction: column;
}
}

效果如图(为了演示方便我把侧导的展开收起改为了可拖拽伸缩):

css-container-queries__media-sidebar-demo-3

演示 Demo

更多内容可阅读:Say Hello To CSS Container Queries

Polyfill

cqfill

Author: Cyris

Permalink: https://sound.cyris.moe/posts/css-container-queries/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。

Comments

Unable to load Disqus, please make sure your network can access.