CSS 容器查询一探究竟 🔥🔥🔥

引言

《请列举四种「等比例自适应矩形」实现方案?》 一文中我曾使用到容器查询单位 cqw, 当时在使用 cqw 过程中只是简单过了一下容器查询相关的内容!!

所以这次专门出一篇文章, 对容器查询做一个梳理....

一、是什么

在实际开发中您是否遇到过需要根据父容器的尺寸, 来调整元素的样式呢?

而容器查询, 作用其实就是让我们能够根据父容器的尺寸, 来调整元素的样式!!!

而针对容器查询特性, 出了两个相关功能:

  1. @container: 可根据容器尺寸条件, 来为元素设置不同的样式, 有点类似 @media, 只不过 @media 是根据媒体设备的特征条件, 而 @container 是根据特定容器的尺寸条件来的
  2. 容器查询单位: 可根据最近容器的尺寸为元素设置一个相对的长度单位, 有点类似 vw vh, 唯一的区别是一个相对的是设备的尺寸, 一个是容器尺寸

最后我们来看下它的兼容性: 兼容性还是挺不错的

二、定义容器

上文一直提到容器, 那么我们又怎么知道这个容器指的是哪个? @container容器查询单位 又是基于哪个容器做查询的呢?

这里其实可以使用 container-type 来标记某个元素为容器, 这样的话 @container容器查询单位 就知道要作用于哪个元素了

container-type 属性有三个可选值:

属性值 说明
normal 默认值, 不作为可查询容器使用
inline-size 在容器的 内联轴(水平) 方向上, 建立查询容器; (也就是你只能实时获取到容器 内联轴(水平) 方向上的尺寸)
size 水平和垂直方向都建立可查询容器 (能够实时获取到容器水平垂直方向上的尺寸)

如下代码, .box 对应元素将被设置为容器:

css 复制代码
.box {
  container-type: inline-size;
}

chrome 中, 类似 flex 对于设置为容器的元素, 会有一个 tag 标记

三、@container

上文介绍了在 CSS 中是可以通过 container-type 将元素标记为容器, 那么下面我们介绍容器元素结合 @container 来实现响应式布局!!

直接来看个简单 DEMO, 如下代码所示:

  • 通过 container-type.box 设置为容器
  • @container (width < 33em) {} 则将监听页面上容器元素, 当容器宽度小于 33em 将对对应的容器内部元素使用花括号 {} 内的 CSS 规则
html 复制代码
<style>
  .box {
    overflow: auto;
    resize: horizontal;
    container-type: inline-size;
  }
  @container (width < 33em) {
    .box p {
      text-align: center;
    }
  }
</style>
<div class="box">
  <p>在实际开发中您是否遇到过需要根据父容器的尺寸, 来调整元素的样式呢?</p>
</div>
<div class="box">
  <p>在实际开发中您是否遇到过需要根据父容器的尺寸, 来调整元素的样式呢?</p>
</div>

最后效果如下: 当我们缩小第一个 .box 宽度时, 当容器小于 33em 那么容器内容文本将居中展示

四、多容器

上午其实我们设置了两个容器元素, @container (width < 33em) {} 对这两个容器都会产生作用!!

那么如果我们想要针对每个容器设置不同的 @container 规则, 我们又可以怎么做呢?

其实容器这边还有一个属性 container-name, 通过该属性我们可以为容器设置别名; 同时 @container 也可设置容器名称, 来对指定的容器生效, 如下代码所示:

  • 针对 .first-box.second-box 设置不同的容器别名 container-name
  • @container second (width < 33em) {}: 只对监听 second 容器尺寸, 为其设置响应式布局
html 复制代码
<style>
  .first-box,
  .second-box {
    overflow: auto;
    resize: horizontal;
    container-type: inline-size;
  }

  .first-box {
    container-name: first;
  }

  .second-box {
    container-name: second;
  }

  @container second (width < 33em) {
    div p {
      text-align: center;
    }
  }

</style>
<div class="first-box">
  <p>在实际开发中您是否遇到过需要根据父容器的尺寸, 来调整元素的样式呢?</p>
</div>
<div class="second-box">
  <p>在实际开发中您是否遇到过需要根据父容器的尺寸, 来调整元素的样式呢?</p>
</div>

最后效果如下:

  • 缩小 first 容器, 没有任何效果(只是文本正常换行)
  • 缩小 second 容器, 当容器小于 33em@container 生效

补充: 上文提到两个容器相关的 CSS 属性: container-typecontainer-name, 它们实际上还有个简写属性 container, 语法: container: <container-name> / <container-type> 例: container: sidebar / inline-size;

五、容器查询单位

既然我们能够实时查询到容器元素的尺寸, 那么自然我们就可以基于容器元素的尺寸来为子元素设置相对长度单位, 也就是所谓的 容器查询单位, 目前已有的容器查询单位有:

单位名 备注
cqw Container Query Width 缩写, 1cqw 等于最近祖先容器宽度的 1%
cqh Container Query Height 缩写, 1cqh 等于最近祖先容器高度的 1%
cqi Container Query Inline-Size 缩写, 1cqi 等于最近祖先容器 Inline-Size 方向上对应尺寸的 1%, 默认情况下 Inline-Size 指的就是水平方向, 对应的是宽度
cqb Container Query Block-Size 缩写, 1cqb 等于最近祖先容器 Block-Size 方向上对应尺寸的 1%, 默认情况下 Block-Size 指的就是垂直方向, 对应的是高度
cqmin Container Query Min 缩写, 1cqmin 等于最近祖先容器最小尺寸的 1%, 例如: 容器宽度为 100 高度为 50, 则会相对于高度(最小的尺寸)进行计算
cqmax Container Query Min 缩写, 1cqmax 等于最近祖先容器最大尺寸的 1%, 例如: 容器宽度为 100 高度为 50, 则会相对于宽度(最大的尺寸)进行计算

下面看个简单例子:

  • 通过 container-type 将元素设置为容器
  • p 标签使用 cqw 来设置字体大小 font-size, 让字体大小根据外层容器的宽度进行自适应
  • calc(100cqw / 33): 使用 CSS 函数 calc 来计算长度, 100cqw 等于容器宽度, 33 是文本长度, 那么这样的话就可以保证文本实时占满整个容器
html 复制代码
<style>
  .box {
    overflow: auto;
    resize: horizontal;
    container-type: inline-size;
  }

  .box p {
    text-align: center;
    font-size: calc(100cqw / 33);
  }
</style>
<div class="box">
  <p>在实际开发中您是否遇到过需要根据父容器的尺寸, 来调整元素的样式呢?</p>
</div>

最后效果如下: 缩小容器, 文字大小会跟着改变, 文本始终一行展示并占满整个容器

六、参考

相关推荐
newxtc31 分钟前
【爱给网-注册安全分析报告-无验证方式导致安全隐患】
前端·chrome·windows·安全·媒体
一个很帅的帅哥1 小时前
axios(基于Promise的HTTP客户端) 与 `async` 和 `await` 结合使用
javascript·网络·网络协议·http·async·promise·await
dream_ready1 小时前
linux安装nginx+前端部署vue项目(实际测试react项目也可以)
前端·javascript·vue.js·nginx·react·html5
编写美好前程1 小时前
ruoyi-vue若依前端是如何防止接口重复请求
前端·javascript·vue.js
flytam1 小时前
ES5 在 Web 上的现状
前端·javascript
喵喵酱仔__2 小时前
阻止冒泡事件
前端·javascript·vue.js
GISer_Jing2 小时前
前端面试CSS常见题目
前端·css·面试
某公司摸鱼前端2 小时前
如何关闭前端Chrome的debugger反调试
javascript·chrome
八了个戒2 小时前
【TypeScript入坑】什么是TypeScript?
开发语言·前端·javascript·面试·typescript
不悔哥2 小时前
vue 案例使用
前端·javascript·vue.js