Deux syntaxes concurrentes ont besoin de votre aide pour déterminer laquelle doit être retenue en tant que candidate de spécification.
L'imbrication CSS est un ajout de syntaxe pratique qui permet d'ajouter du CSS dans un ensemble de règles. Si vous avez déjà utilisé SCSS, Less ou Stylus, vous avez certainement vu quelques variantes de ce code:
.nesting {
color: hotpink;
> .is {
color: rebeccapurple;
> .awesome {
color: deeppink;
}
}
}
Une fois compilé en CSS standard par le préprocesseur, il se transforme en CSS standard comme suit:
.nesting {
color: hotpink;
}
.nesting > .is {
color: rebeccapurple;
}
.nesting > .is > .awesome {
color: deeppink;
}
Nous envisageons sérieusement une version CSS officielle de cette syntaxe. Nous avons des préférences divergentes et nous aimerions demander l'aide de la communauté pour nous aider à trancher. Le reste de cet article présente les options de syntaxe afin que vous puissiez répondre à une enquête à la fin.
Pourquoi l'exemple d'imbrication exact présenté ci-dessus ne peut-il pas être la syntaxe de l'imbrication CSS ?
Plusieurs raisons expliquent pourquoi la syntaxe d'imbrication la plus populaire ne peut pas être utilisée telle quelle:
Analyse ambiguë
Certains sélecteurs imbriqués peuvent resssembler exactement à des propriétés et des préprocesseurs, qui peuvent les résoudre et les gérer au moment de la compilation. Les moteurs de navigateur n'auront pas les mêmes affordances. Les sélecteurs ne doivent jamais être interprétés de manière vague.Conflits d'analyse du préprocesseur
La méthode CSS d'imbrication ne doit pas endommager les préprocesseurs ni les workflows d'imbrication existants des développeurs. Cela serait perturbateur et irrespectueux pour ces écosystèmes et communautés.En attente de
:is()
L'imbrication de base n'a pas besoin de:is()
, mais une imbrication plus complexe en a besoin. Consultez l'exemple 3 pour une présentation succincte des listes de sélecteurs et de l'imbrication. Imaginons que la liste de sélecteurs se trouvait au milieu d'un sélecteur au lieu du début. Dans ce cas,:is()
est nécessaire pour regrouper les sélecteurs au milieu d'un autre sélecteur.
Présentation de ce que nous comparons
Nous voulons que l'imbrication CSS soit correcte, et dans cet esprit, nous incluons la communauté. Les sections suivantes décrivent les trois versions possibles que nous évaluons. Nous allons ensuite examiner quelques exemples d'utilisation à des fins de comparaison. À la fin, vous devrez répondre à une courte enquête pour nous indiquer ce que vous avez préféré dans l'ensemble.
Option 1: @nest
Il s'agit de la syntaxe actuellement spécifiée dans CSS Nesting 1. Il offre un moyen pratique d'imbriquer des styles d'ajout en commençant de nouveaux sélecteurs imbriqués avec &
. Il propose également @nest
pour placer le contexte &
n'importe où dans un nouveau sélecteur, par exemple lorsque vous n'ajoutez pas seulement des sujets. Il est flexible et minimal, mais vous devez vous souvenir de @nest
ou de &
en fonction de votre cas d'utilisation.
Option 2: @nest restricted
Il s'agit d'une alternative plus stricte, dans le but de réduire les dépenses mentionnées liées au rappel de deux méthodes d'imbrication. Cette syntaxe restreinte ne permet que l'imbrication après @nest
. Il n'existe donc pas de modèle pratique d'ajout uniquement. Il élimine l'ambiguïté de choix, créant un moyen facile à retenir d'imbriquer, mais sacrifie la concision au profit de la convention.
Option 3: Crochets
Pour éviter la double syntaxe ou l'encombrement supplémentaire associé aux propositions @nest
, Miriam Suzanne et Elika Etemad ont proposé une syntaxe alternative qui repose sur des accolades supplémentaires. Cela permet de clarifier la syntaxe, avec seulement deux caractères supplémentaires et aucune nouvelle règle at. Il permet également de regrouper les règles imbriquées par type d'imbrication requis, afin de simplifier plusieurs sélecteurs imbriqués de manière similaire.
Exemple 1 : Nidification directe
@nest
.foo {
color: #111;
& .bar {
color: #eee;
}
}
@nest always
.foo {
color: #111;
@nest & .bar {
color: #eee;
}
}
crochets
.foo {
color: #111;
{
& .bar {
color: #eee;
}
}
}
CSS équivalent
.foo {
color: #111;
}
.foo .bar {
color: #eee;
}
Exemple 2 : Imbrications composées
@nest
.foo {
color: blue;
&.bar {
color: red;
}
}
@nest always
.foo {
color: blue;
@nest &.bar {
color: red;
}
}
crochets
.foo {
color: blue;
{
&.bar {
color: red;
}
}
}
CSS équivalent
.foo {
color: blue;
}
.foo.bar {
color: red;
}
Exemple 3 – Listes de sélecteurs et imbrication
@nest
.foo, .bar {
color: blue;
& + .baz,
&.qux {
color: red;
}
}
@nest always
.foo, .bar {
color: blue;
@nest & + .baz,
&.qux {
color: red;
}
}
crochets
.foo, .bar {
color: blue;
{
& + .baz,
&.qux {
color: red;
}
}
}
CSS équivalent
.foo, .bar {
color: blue;
}
:is(.foo, .bar) + .baz,
:is(.foo, .bar).qux {
color: red;
}
Exemple 4 : Plusieurs niveaux
@nest
figure {
margin: 0;
& > figcaption {
background: lightgray;
& > p {
font-size: .9rem;
}
}
}
@nest always
figure {
margin: 0;
@nest & > figcaption {
background: lightgray;
@nest & > p {
font-size: .9rem;
}
}
}
crochets
figure {
margin: 0;
{
& > figcaption {
background: lightgray;
{
& > p {
font-size: .9rem;
}
}
}
}
}
CSS équivalent
figure {
margin: 0;
}
figure > figcaption {
background: hsl(0 0% 0% / 50%);
}
figure > figcaption > p {
font-size: .9rem;
}
Exemple 5 : imbrication de parents ou modification de l'objet
@nest
.foo {
color: red;
@nest .parent & {
color: blue;
}
}
@nest always
.foo {
color: red;
@nest .parent & {
color: blue;
}
}
crochets
.foo {
color: red;
{
.parent & {
color: blue;
}
}
}
CSS équivalent
.foo {
color: red;
}
.parent .foo {
color: blue;
}
Exemple 6 : Mélange de l'imbrication directe et de l'imbrication parent
@nest
.foo {
color: blue;
@nest .bar & {
color: red;
&.baz {
color: green;
}
}
}
@nest always
.foo {
color: blue;
@nest .bar & {
color: red;
@nest &.baz {
color: green;
}
}
}
crochets
.foo {
color: blue;
{
.bar & {
color: red;
{
&.baz {
color: green;
}
}
}
}
}
CSS équivalent
.foo {
color: blue;
}
.bar .foo {
color: red;
}
.bar .foo.baz {
color: green;
}
Exemple 7 : Encapsulage de requêtes multimédias
@nest
.foo {
display: grid;
@media (width => 30em) {
grid-auto-flow: column;
}
}
ou explicitement / étendue
.foo {
display: grid;
@media (width => 30em) {
& {
grid-auto-flow: column;
}
}
}
@nest always (est toujours explicite)
.foo {
display: grid;
@media (width => 30em) {
@nest & {
grid-auto-flow: column;
}
}
}
crochets
.foo {
display: grid;
@media (width => 30em) {
grid-auto-flow: column;
}
}
ou explicitement / étendue
.foo {
display: grid;
@media (width => 30em) {
& {
grid-auto-flow: column;
}
}
}
CSS équivalent
.foo {
display: grid;
}
@media (width => 30em) {
.foo {
grid-auto-flow: column;
}
}
Exemple 8 : Enchâssement de groupes
@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 always
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;
}
}
}
crochets
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 équivalent
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;
}
Exemple 9 : Groupe d'imbrication complexe "Évier de cuisine"
@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 always
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;
}
}
crochets
dialog {
border: none;
{
&::backdrop {
backdrop-filter: blur(25px);
}
& > form {
display: grid;
{
& > :is(header, footer) {
align-items: flex-start;
}
}
}
}
{
html:has(&[open]) {
overflow: hidden;
}
}
}
CSS équivalent
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;
}
C'est l'heure de voter
Nous espérons que vous avez trouvé cette comparaison et cet échantillon des options de syntaxe que nous évaluons justes. Veuillez les examiner attentivement et nous indiquer ci-dessous celle que vous préférez. Merci de nous avoir aidés à faire évoluer l'imbrication CSS vers une syntaxe que nous allons tous connaître et apprécier.