CSS新特性:@container容器查询

又是在网上流浪的一天 …
今天学习css的一个新特性:@container容器查询,其实也不是很新了。(2022年各大浏览器开始支持)
@container 兼容性

提到查询,大家是不是首先会想到 @media

媒体查询 @media

在目前前端响应式方案中,最常见的就是通过@media来实现,比如根据可视窗口的宽高动态改变元素的尺寸或内容。

@media的使用规则为:

COPY
1
2
3
@media 媒体类型 媒体特征表达式{
// 满足条件时,对应样式
}

如下,在screen最大宽度为600px900px时,div的背景色也响应式的发生了变化。这里只是简单举个例子,更多使用特性可以在MDN上查看

COPY
1
2
3
4
5
6
7
8
9
10
11
@media screen and (max-width: 600px) {
.div_1 {
background: blue;
}
}

@media screen and (max-width: 900px) {
.div_1 {
background: red;
}
}

那当我们想对div的子元素也进行响应式处理呢?

COPY
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@media screen and (max-width: 600px) {
.div_1 {
background: blue;
}

}

@media screen and (max-width: 900px) {
.div_1 {
background: red;
}
.div_1 p{
color: red;
}
}

可以看到某些场景下,子元素如果也要根据条件进行响应式,则需要继承父元素的条件,多少有点繁琐了。
那么我们是否可以使用 @container 实现呢?

上述例子可以在codepen上查看

容器查询 @container

不同于@media针对于各重媒体类型的查询,@container 针对的是对容器内部元素进行处理。

@media 适用于外层,@container适用于内层,@container颗粒度更细

基本使用

@container的使用规则为:

COPY
1
2
3
@container 容器条件{
// 满足条件时,对应样式
}

比如:

COPY
1
2
3
4
5
@container (width > 400px) {
h2 {
font-size: 1.5em;
}
}

关键字

可以使用以下关键字:

  • and与条件(同时满足)
  • or或条件(满足其一即可)
  • not否定条件(取反)
    注意:and每个容器查询只允许有一个“not”条件,并且不能与or关键字一起使用
COPY
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 容器宽度大于等于400时生效*/
@container not (width < 400px) {
/* <stylesheet> */
}

/* 容器宽度、高度均大于400时生效 */
@container (width > 400px) and (height > 400px) {
/* <stylesheet> */
}

/* 满足其中一个条件及生效 需要container-type: size */
@container (width > 400px) or (height > 400px) {
/* <stylesheet> */
}

/* 暂时未生效 */
@container (width > 400px) not (height > 400px) {
/* <stylesheet> */
}

具体效果见:https://codepen.io/guozhigq/pen/oNQZQVj

在上面的例子中,可能有同学发现我们对于父元素添加了container-type: size属性,那么这个属性又起什么作用呢?

关键属性

container-type属性定义在父元素中,用来指定查询的范围(条件)
主要有以下的值:

  • size
    • 监听父元素的 变化。定义为size后,可以使用widthheight的判断条件。
      可以尝试将例子中的container-type: size改为container-type: inline-size尝试,你会发现与height相关的判断会失效(inline-size监听父元素的 的变化)
      COPY
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      .card{
      /* container-type: size; */
      container-type: inline-size;
      }
      /* 判断条件中没有 height,仍然有效 */
      @container not (width < 400px){}

      /* 判断条件中有 height,失效 */
      @container (width > 400px) and (height > 400px){}

      /* 判断条件中 height 不是唯一条件,仍然有效 */
      @container (width > 400px) or (height > 400px){}

      /* @container (width > 400px) not (height > 400px){} */
  • inline-size
    • 监听父元素的 变化,在此条件下与height相关的判断不生效,参考以上代码
  • normal
    • 不监听父元素的尺寸变化,在此条件下widthheight的判断条件都不生效,

判断条件

另外的,判断条件除了widthheight 之外还有:

  • aspect-ratio: 根据父元素的比例进行判断
    COPY
    1
    2
    3
    4
    5
    6
    7
    8
    .card{
    /* container-type 必须设置为size */
    container-type: size;
    }
    /* 判断宽高比大于2时生效 */
    @container (aspect-ratio > 2){}
    /* 结合其他判断条件一起使用 */
    @container (aspect-ratio > 2) and (width > 400px) and (height > 400px){}
  • orientation: 根据屏幕方向进行判断(landscape横屏 portrait竖屏)
    • 在codepen测试时,父元素 width > height时landscape(横屏)生效
    • 在codepen测试时,父元素 width < height时portrait(竖屏)生效
      COPY
      1
      2
      3
      4
      5
      6
      7
      8
      9
      .card{
      /* container-type 必须设置为size */
      container-type: size;
      }
      /* 在codepen测试时,父元素 width > height时landscape生效 */
      /* 在codepen测试时,父元素 width <> height时portrait生效 */
      @container (orientation: landscape){}
      @container (orientation: portrait){}

  • inline-size: 具体如何使用暂时不清楚
  • block-size: 具体如何使用暂时不清楚

综上,可以看出来@container的判断基于父元素,而@media则基于视图,@container使用更灵活,能够满足更多的使用场景。

作者: 果汁
文章链接: https://guozhigq.github.io/post/d8a09431.html
版权声明: All posts on this blog are licensed under the CC BY-NC-SA 4.0 license unless otherwise stated. Please cite 果汁来一杯 !