Chrome 正在试验 css @container 查询器功能,这是由 Oddbird 的 Miriam Suzanne 和一群网络平台开发者支持的 CSS 工作组 Containment Level 3 规范。@container 查询器使我们能够根据父容器的大小来设置元素的样式。
你可以把这些想象成一个媒体查询(@media),但不是依靠 viewport 来调整样式,而是你的目标元素的父容器会调整这些样式。
容器查询将是自 CSS3 以来 Web 样式的最大变化,将会改变我们对“响应式设计”含义的看法。
viewport 和用户代理不再是我们创建响应式布局和 UI 样式的唯一目标。通过容器查询,元素将能够定位自己的父元素并相应地应用自己的样式。这意味着存在于侧边栏、主体或头图中的相同元素可能会根据其可用大小和动态看起来完全不同。
@container 实例
在本示例中,我在父级中使用了两张带有以下标记的卡片:
<div class="card-container">
<div class="card">
<figure> ...</figure>
<div>
<div class="meta">
<h2>...</h2>
<span class="time">...</span>
</div>
<div class="notes">
<p class="desc">...</p>
<div class="links">...</div>
</div>
<button>...</button>
</div>
</div>
</div>
复制代码
然后,我在将查询容器样式的父级(.card-container)上设置 Containment(contain 属性)。我还在 .card-container 的父级上设置了一个相对网格布局,因此它的 inline-size 将根据该网格而改变。这就是我使用 @container 查询的内容:
.card-container {
contain: layout inline-size;
width: 100%;
}
复制代码
现在,我可以查询容器样式来调整样式!这与使用基于宽度的媒体查询设置样式的方式非常相似,当元素小于指定尺寸时使用 max-width 设置样式,当元素大于指定尺寸时使用 min-width。
/* 当父容器宽度小于 850px,
不再显示 .links
并且减小 .time 字体尺寸 */
@container (max-width: 850px) {
.links {
display: none;
}
.time {
font-size: 1.25rem;
}
/* ... */
}
/* 当父容器宽度小于 650px 时,
减小 .card 元素之间的网格间距到 1rem */
@container (max-width: 650px) {
.card {
gap: 1rem;
}
/* ... */
}
复制代码
容器查询 + 媒体查询
容器查询的最佳功能之一是能够将 微观上的布局 与 宏观上的布局 分开。我们可以使用容器查询设置单个元素的样式,创建细微的微观布局,并使用媒体查询(宏布局)设置整个页面布局的样式。这创造了一个新的控制水平,使界面更具响应性。
这是另一个示例。它展示了使用媒体查询进行宏观布局(即日历从单面板到多面板)和微观布局(即日期布局/大小和事件边距/大小移动),以创建一个漂亮的和谐的查询。
容器查询 + CSS 网格
我个人最喜欢的查看容器查询影响的方法之一是查看它们在网格中的工作方式。以下面的植物贸易 UI 为例:
本网站根本没有使用媒体查询。相反,我们只使用容器查询和 CSS 网格来在不同的视图中显示购物卡组件。
在产品网格中,布局使用了 grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); 标记创建。这将创建一个布局,告诉卡片占用可用的小数空间,直到它们的大小达到 230px,然后下一格切换到下一行。你可以在 1linelayouts.com 上查看更多网格技巧。
然后,我们有一个容器查询,当卡片宽度小于 350px 时,它会将卡片样式设置为采用垂直块布局,并通过应用 display: flex(默认情况下具有内联流)转换为水平内联布局。
@container (min-width: 350px) {
.product-container {
padding: 0.5rem 0 0;
display: flex;
}
/* ... */
}
复制代码
这意味着每张卡片拥有自己的响应式样式。这是我们使用产品网格创建宏观布局以及使用产品卡片创建微观布局的另一个示例,酷毙了!
用法
为了使用@container,首先需要创建一个具有 Containment 的父元素。为此,我们需要在父级上设置 contain: layout inline-size。因为我们目前只能将容器查询应用于内联轴,所以我们只可以使用 inline-size。这也可以防止我们的布局在块方向上中断。
设置 contain: layout inline-size 会创建一个新的 Containment 块 和新的块格式上下文,让浏览器将其与布局的其余部分分开,现在我们就可以使用容器查询了!
限制
目前,您不能使用基于高度的容器查询,只能使用块轴方向上的查询。为了让网格子元素与 @container 一起工作,我们需要添加一个容器元素。尽管如此,添加容器仍可让我们获得所需的效果。
试试看
您现在可以在 Chromium 中试验 @container 属性,方法是导航到:Chrome Canary 中的 chrome://flags 页面并打开 #
experimental-container-queries 标志。