Retour au cours

frontend / css

CSS moderne expert : nesting, @container, @scope, @property

Leçon 191 exercice

Explication

Ce que vous allez apprendre

  • Imbriquer des règles CSS nativement, sans préprocesseur comme Sass
  • Typer une custom property avec @property pour la rendre animable
  • Limiter la portée d'un ensemble de règles avec @scope, sans dépendre de la spécificité
  • Combiner nesting, @container et color-mix() dans un style de composant moderne

Dans quel contexte ?

Une équipe migre progressivement son projet Sass vers du CSS natif pour supprimer une étape de build devenue difficile à maintenir. Elle doit reproduire l'imbrication de règles (&:hover, & .titre) et l'animation fluide d'une barre de progression dont la couleur changeait dynamiquement — un cas qui, avec de simples variables CSS classiques, ne pouvait pas être animé en douceur. Cette leçon montre les outils natifs qui remplacent ces besoins.

Étape 1 : le CSS rattrape les préprocesseurs

Pendant des années, l'imbrication de règles ou le mélange de couleurs n'existaient qu'à travers des préprocesseurs comme Sass, qui transformaient ce code en CSS classique avant de l'envoyer au navigateur.

Étape 2 : ce que cette leçon présente

Voici les fonctionnalités les plus récentes qui rendent ces outils de moins en moins indispensables : le CSS natif sait désormais faire une grande partie de ce qui nécessitait une étape de compilation.

Étape 3 : le nesting natif, imbriquer sans compilateur

Commençons par le plus visible : écrire les styles d'un composant en imbriquant ses sous-éléments (.carte { & .titre { ... } &:hover { ... } }) rend le code plus lisible qu'une liste plate de sélecteurs répétés, sans étape de build.

Étape 4 : un piège peu connu des variables classiques

Passons à un problème plus subtil. Les variables CSS classiques ne peuvent pas être animées en douceur via transition, car le navigateur ne sait pas s'il s'agit d'un nombre, d'une couleur ou d'un texte.

Le saviez-vous ?

Une transition: --ma-variable 0.3s sur une custom property CSS classique ne produit AUCUNE animation visible : le navigateur bascule instantanément d'une valeur à l'autre. Seule une variable déclarée via @property avec un syntax précis devient réellement interpolable.

Étape 5 : la solution, @property

@property résout ce problème en déclarant explicitement le TYPE d'une variable, ce qui permet enfin au navigateur de l'animer progressivement, comme n'importe quelle propriété native.

Étape 6 : @scope, contenir les styles sans spécificité

Il reste un dernier outil utile : quand du contenu externe est injecté dans une page, ses styles peuvent accidentellement "fuiter". @scope limite explicitement où une règle CSS s'applique, en délimitant une zone de départ et de fin.

FonctionnalitéRemplace (côté Sass)Avantage natif
Nesting (&)imbrication Sasspas d'étape de compilation
@property— (inexistant en Sass)rend une variable animable
@scopeconventions de nommage manuellesportée garantie par le navigateur
color-mix()fonctions mix()/lighten()calcul de couleur natif, sans build

Et ensuite ?

C'est une solution plus structurelle que de jongler avec la spécificité. Une fois ces outils modernes compris, la prochaine étape montre comment le scroll lui-même peut piloter une animation.

Commandes & code

CSS moderne expert

Les dernières fonctionnalités qui rapprochent le CSS natif des préprocesseurs, en mieux intégré au navigateur.

css
/* Nesting natif : plus besoin de Sass pour imbriquer des règles */
.carte {
    padding: 16px;
    border: 1px solid #e5e5e5;

    & .titre {
        font-size: 1.25rem;
        font-weight: 600;
    }

    & .description {
        color: #666;
    }

    &:hover {
        border-color: var(--couleur-primaire);
    }

    &.mise-en-avant {
        border-width: 2px;
    }

    @media (min-width: 640px) {
        padding: 24px;
    }
}
css
/* @scope : limite la portée d'un ensemble de règles à un sous-arbre précis,
   sans dépendre de la spécificité pour éviter les fuites de style */
@scope (.article) to (.commentaires) {
    p {
        line-height: 1.7;
    }
    img {
        max-width: 100%;
    }
}
css
/* @property : type fort pour les custom properties -> permet de les ANIMER,
   ce que les variables CSS classiques ne permettaient pas nativement */
@property --progression {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 0%;
}

.barre-progression {
    background: conic-gradient(var(--couleur-primaire) var(--progression), #e5e5e5 0);
    transition: --progression 0.6s ease;
}
.barre-progression.complete {
    --progression: 100%;
}
css
/* @container avec nesting : composition experte */
.widget {
    container-type: inline-size;

    & .contenu {
        display: grid;
        gap: 8px;
    }

    @container (min-width: 480px) {
        & .contenu {
            grid-template-columns: 1fr 1fr;
        }
    }
}

/* color-mix() : mélange deux couleurs directement en CSS, sans préprocesseur */
.bouton-survol {
    background: color-mix(in srgb, var(--couleur-primaire) 85%, black);
}

/* :has() + nesting + variables : un exemple représentatif du CSS "expert" 2026 */
.formulaire {
    --couleur-validation: #16a34a;

    &:has(input:invalid) {
        --couleur-validation: #dc2626;
    }

    & .indicateur {
        background: var(--couleur-validation);
        transition: background 0.2s;
    }
}

Résumé

  • Le nesting natif couvre l'essentiel des cas d'usage Sass, sans étape de compilation.
  • @scope borne explicitement la portée d'un style, utile face à du contenu tiers/injecté.
  • @property type une custom property et la rend enfin animable via transition.
  • color-mix() calcule des variations de couleur directement en CSS, sans fonctions de préprocesseur.

Exercices pratiques

1 disponible
1

Mission : une barre de progression qui saute au lieu de glisser

Objectif : Diagnostiquer pourquoi une custom property classique ne s'anime pas, et migrer un fragment Sass vers du nesting natif.

Contexte

Sur progression.css, une barre utilise background: conic-gradient(var(--couleur-primaire) var(--progression), #e5e5e5 0); avec transition: --progression 0.6s ease;, mais --progression est une simple custom property déclarée uniquement via :root { --progression: 0%; }, sans aucun @property. Résultat : au clic sur "Suivant", la barre saute instantanément de 0% à 40% au lieu de glisser progressivement. Par ailleurs, l'équipe veut migrer une règle Sass .carte { &:hover { border-color: blue; } & .titre { font-weight: 600; } } vers du CSS nesting natif.

Résoudre l’exercice →