CSS:State Container Queries


Chromium团队正在尝试一种新型查询,称为State Querysize container queries在所有主要浏览器中得到了支持。它们允许我们根据容器的宽度进行查询。

1
2
3
4
5
6
7
8
9
10
11
.card-wrapper {
container-type: inline-size;
container-name: card;
}

@container card (min-width: 400px) {
.card {
display: flex;
align-items: center;
}
}

除此之外,我们现在还有Style查询,它允许我们查询一个容器,并检查CSS变量是否持续存在。

1
2
3
4
5
6
7
8
9
10
.special-wrapper {
--theme: dark;
container-name: stats;
}

@container stats style(--theme: dark) {
.stat {
/* 添加暗色样式。 */
}
}

目前,这仅在Chrome Canary中可用。

回到State查询,查看这到底是什么。
它的工作原理如下:

  • 将容器类型定义为sticky
  • 使用state查询
  • 检查是否激活了stuck: direction
    这意味着,当页眉被固定时,我们需要更新内边距。或者可能隐藏或显示某些内容。

State查询示例

固定状态查询

固定状态的一个用例是当我们有一个页眉,其设计会根据是否被固定而改变。所谓固定,我指的是position: sticky生效了。
考虑以下示例:

当页眉被固定时,我想简化其设计。原因是,并不总是一个好的做法让元素占用屏幕空间。

我过去使用JavaScript来检测这个问题,但现在我们可能很快就可以用CSS解决了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.page {
container-name: sticky-header;
container-type: sticky;
}

.site-header {
position: sticky;
top: 0;
}

@container state(stuck: top) {
.site-header__bottom {
display: none;
}

.site-header__actions {
display: none;
}
}
包裹状态查询

状态查询不仅仅与粘性定位有关。
考虑以下示例:

我们有一个使用flexbox构建的站点页眉。当项目换行时,我想隐藏导航并替换为一个切换菜单按钮。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.site-header {
container-type: wrap;
container-name: header;
display: flex;
flex-wrap: wrap;
align-items: center;
}

@container header state(wrap: true) {
.site-header__nav {
display: none;
}

.nav-toggle {
display: block;
}
}

能够检测到flex容器何时换行将非常有帮助。注意:这仍然是一个想法,并且尚未在任何浏览器中实现。

空状态

目前,我们可以使用:empty伪类来检查元素是否为空。

1
2
3
.figcaption:empty {
display: none;
}

这个方法很好用,但是如果 <figcaption> 元素中有空格字符,它就会失效。我们能否用状态查询做得更好呢?

考虑以下 HTML。请注意,我有意在其中添加了一个空格。

1
<section class="section"></section>

我不知道这应该如何正确地工作,因为我们不能将 CSS 应用于容器本身,但是这是一个伪代码。

1
2
3
4
5
6
7
section {
container-type: empty;
}

@container state(empty: true) {
display: none;
}

这里的空状态意味着容器没有任何子元素。

检测文档方向

很多时候需要知道容器的方向是从左到右(ltr)还是从右到左(rtl)。例如,我可能想要翻转一个图标。

通过文档方向的状态查询,这可能会有很大帮助。

1
2
3
4
5
6
7
8
9
10
11
/* 而不是.. */
html[dir="rtl"] .button-icon {
transform: scaleX(-1);
}

/* 我们可以这样做 */
@container state(dir: rtl) {
.button-icon {
transform: scaleX(-1);
}
}

就这么简单。你觉得怎么样?