想象一下,像这些 Transformer Tabs 这样的东西,在响应式设计中作为流体列中的一个小部件。 根据浏览器窗口宽度,此设计可能是 4 列、2 列或 1 列宽。 当它从 4 列变为 2 列时,该列可能暂时变宽,即使屏幕变窄。 在为这些标签编写媒体查询逻辑时,最好考虑小部件有多少可用空间,而不是整个窗口,因为这可能完全无关,尤其是在重用此小部件时。
Jonathan Neal 对此有一些想法,包括您可能没有想到的复杂部分,例如小部件的内容如何影响其父容器并导致无限循环。
Jonathan 的网站现在已离线,因此我将在此处复制此博文的内容以供后代。
这篇文章的灵感来自我的朋友,也是 normalize.css 的共同创建者, Nicolas Gallagher.
我们需要在元素/组件/小部件级别而不是视窗级别使用原生 CSS 媒体查询。 网上就是这样做的。 — @necolas
因此,没有任何大张旗鼓,我想分享我对元素媒体查询的看法,然后在评论中打开讨论。
想法 #1:标记将是什么
我们将使用一个 伪类,因为我们正在针对元素的状态。 伪类的示例包括 :hover
、:focus
和 :checked
。
我们不会使用伪元素,因为我们不针对元素内的影子元素。 伪元素的一些示例包括 ::first-letter
、::before
和 ::after
。 不要被 IE7&8 误导,:before 不是正确的语法。 实际上,如果您不支持 IE7&8,则应该开始使用正确的语法以摆脱这种遗留的不一致性。
[:]: 符号由本文档引入,以区分伪类和伪元素。 为了与现有样式表兼容,用户代理还必须接受 CSS 级别 1 和 2 中引入的伪元素的先前单冒号符号(即:first-line、:first-letter、:before 和 :after)。 — 选择器 W3C 工作草案
我们将以其前身的命名伪类 media
,使用圆括号包装查询,类似于 :not
和 :contains
。
.widget:media(max-width: 30em) {color: tomato;}
多个查询需要多个圆括号。
.widget:media((max-width: 30em) and (min-width: 30em)) {color: bisque;}
想法 #2:em 将如何工作
em
的大小将相对于元素的字体大小,就像它对现有 CSS 值的工作方式一样。 rem
单位将用于定位文档的字体大小。
html {font-size: 16px;}
.parent {font-size: 12px;}
.parent > *:media(max-width: 30em) {/* applied up to 360px */}
.parent > *:media(max-width: 30rem) {/* applied up to 480px */}
这带来了现有媒体查询的一个问题。 目前,当我们将 html
的字体大小定义为 12px 时,@media (max-width: 30em)
会评估为 360px 还是 480px? 如果我们认为 @media “存在”于 html
元素上,那么答案是 360px。 另一方面,如果我们认为 @media “存在”于超越 html
的某个以太中,那么答案是 480px。 可悲的是,大多数浏览器同意后一种解释。 因此,作为对元素媒体查询讨论的附带好处,我们应该指定 @media 查询中 em 的大小应该相对于 html
元素的字体大小。
想法 #3:如何处理无限循环
无限循环将在出现问题的块处冻结。 虽然无限循环更有可能在元素媒体查询中发生,但这个问题自 :hover
以来就一直存在。 因此,一个清晰的规范将是双倍有用。
.widget {color: salmon;width: 100%;}
.widget:media(max-width: 320px) {color: whitesmoke;width: 321px;}
/* the infinite loop is stopped, .widget is whitesmoke with a width of 321px */
同样,这将解决经典的 CSS 循环问题。
.widget {color: plum;}
.widget:hover {color: orange;display: none;}
/* the infinite loop is stopped, .widget is not displayed, but is otherwise orange */
问答
元素媒体查询应该能够定位页面,例如
.widget:media(page-max-width: 30em)
和.widget:media(device-max-width: 30em)
吗?
是的,利用这种语法可以真正提高样式表的可读性。 我可以想象很多开发人员更喜欢这些类型的 :media
伪类查询而不是传统的 @media
查询。 事实上,许多开发人员已经在使用 SASS 中的嵌套来尝试执行类似的操作。
:media
伪类中的查询数量是否会增加选择器权重,因此.widget:media((min-width: 2em) and (max-width: 30em))
会胜过.widget:media(max-width: 30em)
吗?
不会,因为 @media
查询不是选择器,因此没有权重。 相反,*:not(#foo)
的权重高于 *:not(.foo)
,因为伪类正在评估选择器,而选择器始终增加权重。 另一方面,@media (min-width: 5em) and (max-width: 500em)
的权重并不高于 @media (max-width: 500em)
。
灵感
Necolas 的推文、Chris Coyier 关于 CSS 特定性、MediaClass(为元素媒体查询提供 polyfill),以及与 Ian Hickson 的精彩对话,他教会了我 :
和 ::
之间的区别。