选择一个元素及其所有后代元素:
.media, .media * {color: #f00;}
有没有一个选择器可以代替用逗号分隔的两个选择器?我正在寻找一种更高效的方法来输入这个。
选择一个元素及其所有后代元素:
.media, .media * {color: #f00;}
有没有一个选择器可以代替用逗号分隔的两个选择器?我正在寻找一种更高效的方法来输入这个。
在2023年,CSS语法和可用的伪类的最新添加带来了一些有趣的替代方法来解决这个问题(尽管仍然不如真正本地的自身或后代组合器理想)。
让我们考虑一个假设的.prose
类,它标识站点的作者内容,可以通过嵌套结构的<article>
或<section>
块,或者直接包含文本的<p>
或<blockquote>
元素来传递。
只有严格的后代组合器和传统的CSS语法,像<p>
和<blockquote>
这样的元素需要添加一个(可能不太语义化的)包装器,例如<div>
元素。
或者,CSS规则可以编写成匹配自身和后代的方式,但这涉及到重复(容易出错的)样板:
h1.prose, .prose h1 {...}
h2.prose, .prose h2 {...}
h3.prose, .prose h3 {...}
h4.prose, .prose h4 {...}
h5.prose, .prose h5 {...}
h6.prose, .prose h6 {...}
p.prose, .prose p {...}
blockquote.prose, .prose blockquote {...}
/* And so forth... */
利用最近的CSS发展,以上内容可以按以下方式重新编写:
.prose, .prose * {
&:is(h1) {...}
&:is(h2) {...}
&:is(h3) {...}
&:is(h4) {...}
&:is(h5) {...}
&:is(h6) {...}
&:is(p) {...}
&:is(blockquote) {...}
/* Alternatively, the :where() pseudo-class can also be used,
which differs in how specificity is calculated. */
}
显然,&:is(...)
部分仍然是样板代码,但重复性已经大大减少,这可以被认为是一种改进。
注意:截至2023年5月,浏览器对于原生CSS嵌套的支持仍在进行中(请参见https://caniuse.com/css-nesting),利用它的CSS代码应该转换为非嵌套语法(例如使用postcss-nesting插件)。:is()
伪类享有更广泛的支持(请参见https://caniuse.com/?search=is)。
:root {
--ctx-media: ;
--ctx-not-media: initial;
}
.media {
--ctx-media: initial;
--ctx-not-media: ;
}
* {
color: var(--ctx-media, #f00)
var(--ctx-not-media, inherit);
}
--ctx-media
变量被定义为根元素上的一个空格,而--ctx-not-media
未定义(:root
规则中的--ctx-not-media: initial
属性实际上并不需要,因为默认情况下所有变量都是未定义的,但为了视觉对称性,我还是提供了它)。请注意,CSS变量默认情况下是继承的,除非在@property规则中另有定义。无论何时应用media类,--ctx-media
将变为未定义,--ctx-not-media
将被定义为元素本身及其所有后代的一个空格。
接下来是color属性,无论哪个CSS变量被定义,都会扩展为一个空格,而未定义的则会扩展为其回退值。由于属性值周围的空格在语义上是惰性的,所以结果值仍然有效。对于非媒体内容,inherit值可以替换为任何所需的值。请注意,这两种情况必须包含在属性值的定义中。省略其中一种情况将导致无效的CSS:
* {
/* WRONG!!! Will resolve to `color: ;` when --ctx-media is defined */
color: var(--ctx-media, #f00);
}
--ctx-*
变量。:root {
--ctx-media: ;
--ctx-not-media: initial;
}
.media {
--ctx-media: initial;
--ctx-not-media: ;
}
@layer media {
* {
color: var(--ctx-media, #f00)
var(--ctx-not-media, revert-layer);
}
}
.media, .media * {...}
选择器更冗长。然而,假设*
是一个用于样式化处于“媒体”上下文中的元素的假设规则集的占位符,这就是这种方法的全部好处所在。
.media {color: #f00}
就足够了,因为每个后代都会“继承”这个属性,而不是“设置”它,除非有其他规则适用(比如链接的颜色)。这是所谓的“层叠”样式表的一部分。 - Charles-Édouard Costedisplay
。 - chharvey