我们需要您帮助确定哪种竞争语法应该成为规范候选项。
CSS 嵌套是一种便捷的语法添加,可让您在规则集中添加 CSS。如果您使用过 SCSS、Less 或 Stylus,那么您肯定见过以下几种变体:
.nesting {
color: hotpink;
> .is {
color: rebeccapurple;
> .awesome {
color: deeppink;
}
}
}
经过预处理器编译为常规 CSS 后,它会变成如下所示的常规 CSS:
.nesting {
color: hotpink;
}
.nesting > .is {
color: rebeccapurple;
}
.nesting > .is > .awesome {
color: deeppink;
}
我们正在考虑为此语法提供官方 CSS 版本,但意见不一,因此希望借助社区的力量来解决这个问题。本文的其余部分将介绍语法选项,以便您在结束时可以根据自己的了解填写调查问卷。
为什么上面显示的嵌套示例不能作为 CSS 嵌套的语法?
最常见的嵌套语法无法按原样使用,原因如下:
模糊解析
某些嵌套选择器可能与属性和预处理器完全一样,能够在构建时解析和管理它们。浏览器引擎不会具有相同的功能,因此选择器绝不能宽泛解读。预处理器解析冲突
CSS 嵌套方式不应破坏预处理器或现有的开发者嵌套工作流。这会破坏这些生态系统和社区,对其不利。等待
:is()
基本嵌套不需要:is()
,但更复杂的嵌套需要。如需简要了解选择器列表和嵌套,请参阅示例 3。假设选择器列表位于选择器的中间,而不是开头,在这种情况下,必须使用:is()
才能在另一个选择器的中间对选择器进行分组。
我们要比较的内容概览
我们希望正确处理 CSS 嵌套,因此会征求社区的意见。以下部分将帮助介绍我们要评估的三个可能的版本。然后,我们将介绍一些使用示例以供比较,最后会进行一个简短的调查,询问您总体而言更喜欢哪种方式。
方案 1:@nest
这是 CSS 嵌套 1 中当前指定的语法。它提供了一种便捷的方式,通过使用 &
启动新的嵌套选择器来嵌套附加样式。它还提供了 @nest
,以便将 &
上下文放置在新选择器内的任意位置,例如当您不只是附加主题时。这种方法灵活且最小化,但需要记住 @nest
或 &
(具体取决于您的用例)。
选项 2:@nest restricted
这是一种更严格的替代方法,旨在减少记住两种嵌套方法所需的开销。这种受限语法仅允许在 @nest
后进行嵌套,因此没有仅用于附加的便捷模式。消除了选择的模糊性,创建了一种易于记忆的嵌套方式,但为了遵循惯例而牺牲了简洁性。
选项 3:括号
为了避免 @nest
提案涉及的双重语法或额外杂乱,Miriam Suzanne 和 Elika Etemad 提出了一种替代语法,该语法改为依赖于额外的大括号。这样可以使语法更加清晰,只需额外添加两个字符,而无需添加新的 at 规则。此外,它还允许按所需的嵌套类型对嵌套规则进行分组,以简化多个类似嵌套的选择器。
示例 1 - 直接嵌套
@nest
.foo {
color: #111;
& .bar {
color: #eee;
}
}
@nest 始终
.foo {
color: #111;
@nest & .bar {
color: #eee;
}
}
括号
.foo {
color: #111;
{
& .bar {
color: #eee;
}
}
}
等效 CSS
.foo {
color: #111;
}
.foo .bar {
color: #eee;
}
示例 2 - 复合嵌套
@nest
.foo {
color: blue;
&.bar {
color: red;
}
}
@nest 始终
.foo {
color: blue;
@nest &.bar {
color: red;
}
}
括号
.foo {
color: blue;
{
&.bar {
color: red;
}
}
}
等效 CSS
.foo {
color: blue;
}
.foo.bar {
color: red;
}
示例 3 - 选择器列表和嵌套
@nest
.foo, .bar {
color: blue;
& + .baz,
&.qux {
color: red;
}
}
@nest 始终
.foo, .bar {
color: blue;
@nest & + .baz,
&.qux {
color: red;
}
}
括号
.foo, .bar {
color: blue;
{
& + .baz,
&.qux {
color: red;
}
}
}
等效 CSS
.foo, .bar {
color: blue;
}
:is(.foo, .bar) + .baz,
:is(.foo, .bar).qux {
color: red;
}
示例 4 - 多个层级
@nest
figure {
margin: 0;
& > figcaption {
background: lightgray;
& > p {
font-size: .9rem;
}
}
}
@nest 始终
figure {
margin: 0;
@nest & > figcaption {
background: lightgray;
@nest & > p {
font-size: .9rem;
}
}
}
括号
figure {
margin: 0;
{
& > figcaption {
background: lightgray;
{
& > p {
font-size: .9rem;
}
}
}
}
}
等效 CSS
figure {
margin: 0;
}
figure > figcaption {
background: hsl(0 0% 0% / 50%);
}
figure > figcaption > p {
font-size: .9rem;
}
示例 5 - 父级嵌套或主题更改
@nest
.foo {
color: red;
@nest .parent & {
color: blue;
}
}
@nest 始终
.foo {
color: red;
@nest .parent & {
color: blue;
}
}
括号
.foo {
color: red;
{
.parent & {
color: blue;
}
}
}
等效 CSS
.foo {
color: red;
}
.parent .foo {
color: blue;
}
示例 6 - 混合使用直接嵌套和父级嵌套
@nest
.foo {
color: blue;
@nest .bar & {
color: red;
&.baz {
color: green;
}
}
}
@nest 始终
.foo {
color: blue;
@nest .bar & {
color: red;
@nest &.baz {
color: green;
}
}
}
括号
.foo {
color: blue;
{
.bar & {
color: red;
{
&.baz {
color: green;
}
}
}
}
}
等效 CSS
.foo {
color: blue;
}
.bar .foo {
color: red;
}
.bar .foo.baz {
color: green;
}
示例 7 - 媒体查询嵌套
@nest
.foo {
display: grid;
@media (width => 30em) {
grid-auto-flow: column;
}
}
或显式 / 扩展
.foo {
display: grid;
@media (width => 30em) {
& {
grid-auto-flow: column;
}
}
}
@nest always(始终是显式)
.foo {
display: grid;
@media (width => 30em) {
@nest & {
grid-auto-flow: column;
}
}
}
括号
.foo {
display: grid;
@media (width => 30em) {
grid-auto-flow: column;
}
}
或显式 / 扩展
.foo {
display: grid;
@media (width => 30em) {
& {
grid-auto-flow: column;
}
}
}
等效 CSS
.foo {
display: grid;
}
@media (width => 30em) {
.foo {
grid-auto-flow: column;
}
}
示例 8 - 嵌套组
@nest
fieldset {
border-radius: 10px;
&:focus-within {
border-color: hotpink;
}
& > legend {
font-size: .9em;
}
& > div {
& + div {
margin-block-start: 2ch;
}
& > label {
line-height: 1.5;
}
}
}
@nest 始终
fieldset {
border-radius: 10px;
@nest &:focus-within {
border-color: hotpink;
}
@nest & > legend {
font-size: .9em;
}
@nest & > div {
@nest & + div {
margin-block-start: 2ch;
}
@nest & > label {
line-height: 1.5;
}
}
}
括号
fieldset {
border-radius: 10px;
{
&:focus-within {
border-color: hotpink;
}
}
> {
legend {
font-size: .9em;
}
div {
+ div {
margin-block-start: 2ch;
}
> label {
line-height: 1.5;
}
}}
}
}
等效 CSS
fieldset {
border-radius: 10px;
}
fieldset:focus-within {
border-color: hotpink;
}
fieldset > legend {
font-size: .9em;
}
fieldset > div + div {
margin-block-start: 2ch;
}
fieldset > div > label {
line-height: 1.5;
}
示例 9 - 复杂嵌套组“厨房水槽”
@nest
dialog {
border: none;
&::backdrop {
backdrop-filter: blur(25px);
}
& > form {
display: grid;
& > :is(header, footer) {
align-items: flex-start;
}
}
@nest html:has(&[open]) {
overflow: hidden;
}
}
@nest 始终
dialog {
border: none;
@nest &::backdrop {
backdrop-filter: blur(25px);
}
@nest & > form {
display: grid;
@nest & > :is(header, footer) {
align-items: flex-start;
}
}
@nest html:has(&[open]) {
overflow: hidden;
}
}
括号
dialog {
border: none;
{
&::backdrop {
backdrop-filter: blur(25px);
}
& > form {
display: grid;
{
& > :is(header, footer) {
align-items: flex-start;
}
}
}
}
{
html:has(&[open]) {
overflow: hidden;
}
}
}
等效 CSS
dialog {
border: none;
}
dialog::backdrop {
backdrop-filter: blur(25px);
}
dialog > form {
display: grid;
}
dialog > form > :is(header, footer) {
align-items: flex-start;
}
html:has(dialog[open]) {
overflow: hidden;
}
投票时间
希望您能认为这是一个公平的比较,并能从中了解我们正在评估的语法选项。请仔细查看,然后在下方告诉我们您更喜欢哪个版本。感谢您帮助我们将 CSS 嵌套改进为我们都熟悉且喜爱的语法!