CSS容器查询
什么是容器查询?
如何使用容器查询
影响规格
结束
CSS 领域即将迎来一些令人兴奋的新变化,我之所以说“即将到来”,是因为它目前尚未被任何浏览器支持,规范也尚未最终定稿(截至撰写本文时)。尽管如此,Chrome 的下一个版本已经引入了这项功能,我相信不久之后所有“现代”浏览器都会支持它。
什么是容器查询?
容器查询与媒体查询类似,但有一个主要且关键的区别。媒体查询会查询整个文档,并根据查询结果修改内容。例如,如果文档宽度超过 1025 像素,您可能希望将内容分成两列而不是一列。代码大致如下。
main.content {
column-count: 1;
column-gap: 2em;
}
@media screen and (min-width: 1025px) {
main.content {
column-count: 2;
}
}
容器查询遵循相同的原理,但它们不是查询整个文档,而是查询容器。
他们如何帮助开发者
想象一下这样的场景:你有一个联系卡片,想在网站的各个位置显示。有些地方它位于主要内容区域,而有些地方你决定将其显示在侧边栏中。在同一个媒体查询中,侧边栏的宽度可能是 250 像素,而主要内容区域的宽度可能是 700 像素,这就导致卡片的显示效果需要有所不同。解决方法很简单,只需为卡片设置不同的类和媒体查询即可,但还有更好的方法……那就是使用容器查询!
如何使用容器查询
要使用容器查询,我们必须告诉容器(我们要应用查询的元素的父元素)我们关心它的尺寸,我们通过新的contain属性来实现这一点。
`none`
表示元素正常渲染,不应用任何包含规则。`strict`
表示
除样式外的所有包含规则都应用于该元素。这等价于 `contain: size layout paint`。`content`
表示
除大小和样式外的所有包含规则都应用于该元素。这等价于 `contain: layout paint`。`size`
表示
可以调整元素的大小,而无需检查其后代元素的大小。`layout`
表示
元素外部的任何内容都不会影响其内部布局,反之亦然。`style`
表示
对于可能影响多个元素(而不仅仅是元素及其后代)的属性,这些影响不会超出包含元素的范围。请注意,此值在规范中被标记为“有风险”,可能并非所有地方都支持。`paint`
表示
元素的后代元素不会显示在其边界之外。如果包含框位于屏幕外,浏览器无需绘制其包含的元素——这些元素也必须位于屏幕外,因为它们完全包含在该框内。如果子元素超出包含元素的边界,则该子元素将被裁剪到包含元素的边框内。
目前 Mozilla 上的相关文档略显不足,这种情况比较少见。我们想使用inline-sizeMozilla 其他地方描述的属性,如下所示:
当我们使用媒体查询时,大多数时候我们关心的是可用宽度(或
inline-size)。
实际案例
让我们以前面提到的联系人卡片为例,编写一些代码来描述它。
<div class="site">
<main class="content">
<div class="contact-card">
<img class="contact-card__profile-image" src="profile.png" alt="profile" />
<div class="contact-card__profile-information">
<h1>Both Names</h1>
<p>Some info about me</p>
</div>
</div>
</main>
<aside class="side-panel">
<div class="contact-card">
<img class="contact-card__profile-image" src="profile.png" alt="profile" />
<div class="contact-card__profile-information">
<h1>Both Names</h1>
<p>Some info about me</p>
</div>
</div>
</aside>
</div>
HTML 代码虽然很简单,但我认为它表达清楚了我们有一个联系卡,它在两个地方,宽度可能差别很大。
/* Just some simple css to get it started */
.site {
display: flex;
max-width: 800px;
margin: 0 auto;
}
main.content {
width: 60%;
background: #ccc;
}
aside.side-panel {
width: 40%;
background: tomato;
}
/* Real css starts here */
main.content, aside.side-panel {
container: layout / inline-size;
}
.contact-card {
display: flex;
flex-direction: column;
align-items: center;
width: 200px;
background-color: white;
padding: 2em;
box-sizing: border-box;
border-radius: 2px;
margin: 1em;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.4)
}
.contact-card__profile-image {
height: 50px;
width: 50px;
border-radius: 50px;
border: 1px solid black;
}
.contact-card__profile-information {
margin-left: 0.5em;
}
.contact-card__profile-information h1 {
text-align: center;
margin: 0;
font-size: 1.2em;
}
.contact-card__profile-information p {
text-align: center;
margin: 0.5em 0 0 0;
}
@container layout (min-width: 450px) {
.contact-card {
width: 300px;
flex-direction: row;
align-items: flex-start;
}
.contact-card__profile-information h1 {
text-align: left;
}
.contact-card__profile-information p {
text-align: left;
}
}
这段 CSS 代码中,我们先设置了卡片的样式contact-card,然后使用容器查询,当宽度设置为 450px 时,容器会改变卡片的样式。正如你所看到的,它本质上与媒体查询相同,但它是基于容器的。
以下是代码的渲染效果(希望不久的将来我们能在更多浏览器中进行测试)。这是实际运行后的代码,jsfiddle。
影响规格
正如我一开始所说,规范尚未最终定稿,如果您想了解大家的建议,或者想提出自己的建议,现在还来得及。请前往git issues 看板查看。
结束
我对此感到非常兴奋,我主要使用 React,我非常期待组件能够根据其父组件的大小而改变。
好了,就到这里,帖子到此结束。如果你有任何问题,欢迎在评论区留言。我可能无法立即回答所有问题,但我们一起来学习吧。如果你愿意,也可以在推特上找到我。
非常感谢您的阅读❤️🧠🧠❤️🦄🦄🧠❤️🧠
文章来源:https://dev.to/link2twenty/css-container-queries-1205

