Définissez les valeurs par défaut du texte de la page sur body, laissez les propriétés héritées se transmettre aux composants et ciblez délibérément les règles de mise en page. Ce guide explique comment créer et vérifier une page HTML locale sur Mac sans obliger chaque élément à annuler une règle universelle.

Pourquoi une règle universelle interfère-t-elle avec les valeurs par défaut des composants ?

Le sélecteur universel * correspond à chaque élément. Une déclaration dans cette règle s’applique donc directement à chaque élément correspondant ; elle ne fournit pas simplement une valeur que les descendants héritent. Elle ne correspond pas non plus directement aux pseudo-éléments, qui nécessitent des sélecteurs comme *::before. Sélecteurs universels.

Considérez ce fragment CSS pour un composant contenant un paragraphe et un élément span imbriqué :

/* Illustrative fragment: assumes a .tile with text descendants. */
* {
  color: #303840;
}

.tile {
  color: #245d75;
}

La tuile reçoit elle-même la couleur de texte bleue. Son paragraphe et son span reçoivent directement la couleur sombre de la règle universelle. La couleur du composant ne peut pas se transmettre à travers ces déclarations par héritage ordinaire. Selon les règles CSS de détermination des valeurs, les propriétés héritées obtiennent la valeur calculée de leur parent lorsque la cascade ne fournit aucune valeur pour cette propriété sur l’élément. CSS Cascading and Inheritance Level 4, détermination des valeurs.

Cela peut prêter à confusion, car * a une spécificité nulle. La spécificité compare les déclarations concurrentes sur un même élément au sein de l’origine et de la couche de cascade applicables. Une déclaration sur un parent n’est pas un sélecteur concurrent qui correspond à son enfant. Rendre le sélecteur du parent plus spécifique ne résout donc pas ce problème d’héritage. Spécificité.

La modification utile consiste à supprimer la déclaration de texte universelle et à définir la valeur par défaut sur body. Les descendants peuvent alors l’hériter jusqu’à ce qu’un composant ou un élément fournisse une autre valeur. MDN indique que color est une propriété héritée et explique que l’héritage suit la valeur calculée du parent. Héritage.

Quelles valeurs par défaut placer sur la page, un composant ou chaque élément ?

Avant d’écrire un sélecteur général, déterminez si la propriété doit se transmettre à un sous-arbre de texte, décrire une seule boîte ou établir une règle intentionnelle pour toutes les boîtes. L’aide à la décision ci-dessous applique cette distinction à une petite page écrite à la main.

Résultat souhaité Emplacement recommandé Raison
Le texte ordinaire de la page partage une couleur de base et une typographie body Fournit au texte un point de départ commun par héritage
Une tuile et son texte ordinaire partagent une couleur différente .tile Établit une nouvelle valeur héritée dans ce composant
Une légende a une couleur différente .caption Applique l’exception à l’élément concerné
Un panneau a une marge intérieure, une bordure ou un arrière-plan La classe du panneau Associe la décoration de la boîte à son propriétaire
Les boîtes utilisent un modèle de dimensionnement cohérent Une règle box-sizing délibérée Établit une convention explicite de dimensionnement
Les titres ont une marge par défaut facile à remplacer Un sélecteur de titre ciblé, éventuellement enveloppé dans :where() Limite la valeur par défaut aux éléments visés

L’héritage dépend de la propriété. Consultez l’entrée Inherited de la référence de la propriété au lieu de supposer que chaque déclaration sur body se transmet à ses descendants. Par exemple, les bordures ne sont pas héritées par défaut. Héritage.

Une règle universelle de dimensionnement peut tout de même être appropriée. Avec border-box, la largeur déclarée d’un élément inclut son remplissage et sa bordure ; les marges restent à l’extérieur de cette largeur. Il s’agit d’un choix précis de modèle de boîte, et non d’une raison d’appliquer universellement toutes les valeurs par défaut de la page. box-sizing.

Créez une démonstration locale complète sur votre Mac

Utilisez TextEdit en mode texte brut ou un éditeur de code existant. Dans TextEdit, choisissez File > New, puis Format > Make Plain Text. Collez le document complet ci-dessous, choisissez File > Save et nommez-le page-defaults.html. Si une invite apparaît, choisissez Use .html. Apple décrit cette procédure dans son guide HTML de TextEdit.

Cet exemple utilise des libellés fictifs et des formes dessinées en CSS. Il s’agit d’un document complet avec une feuille de style intégrée ; aucun fichier supplémentaire n’est donc nécessaire. Le code a été examiné ici ; son rendu n’a pas été exécuté dans un navigateur Mac.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Page defaults demonstration</title>
  <style>
    *, *::before, *::after {
      box-sizing: border-box;
    }

    body {
      margin: 0;
      font-family: system-ui, sans-serif;
      font-size: 1rem;
      line-height: 1.5;
      color: #303840;
      background-color: #f4f5f6;
    }

    main {
      max-width: 44rem;
      margin: 0 auto;
      padding: 2rem 1rem;
    }

    h1 {
      line-height: 1.2;
    }

    .tile {
      margin: 1.5rem 0;
      padding: 1.25rem;
      border: 2px solid currentColor;
      border-radius: 0.75rem;
      color: #245d75;
      background-color: #ffffff;
    }

    .tile h2 {
      margin-top: 0;
    }

    .shape {
      width: 4rem;
      height: 4rem;
      background-color: currentColor;
    }

    .shape--round {
      border-radius: 50%;
    }

    .caption {
      color: #66523c;
    }
  </style>
</head>
<body>
  <main>
    <h1>Shape notes</h1>
    <p>Page sample: <span>Label A</span>.</p>

    <section class="tile">
      <h2>Tile B</h2>
      <div class="shape shape--round" aria-hidden="true"></div>
      <p>Component sample: <span>Label C</span>.</p>
      <p class="caption">Caption D has its own text color.</p>
    </section>

    <p>Page sample: <span>Label E</span>.</p>
  </main>
</body>
</html>

Ouvrez page-defaults.html dans votre navigateur. Lorsque vous rouvrez la source dans TextEdit, choisissez TextEdit > Settings > Open and Save et activez Display HTML files as HTML code instead of formatted text si vous voulez que TextEdit affiche le balisage de façon cohérente. Travailler avec des documents HTML dans TextEdit sur Mac.

Vérifiez la limite de l’héritage avec trois modifications

Ces vérifications transforment le document en petit exercice de diagnostic. Enregistrez la source et rechargez le navigateur après chaque modification. Gardez une copie du document original ou annulez chaque changement avant d’essayer le suivant.

  1. Modifiez uniquement la couleur de body en #4b465f. Le texte autour de Label A et Label E devrait changer. La tuile conserve sa propre couleur.
  2. Rétablissez la couleur de la page, puis modifiez uniquement .tile en color: #526637. Le texte ordinaire de son titre et de son paragraphe devrait suivre ce changement, y compris Label C. Caption D conserve sa couleur explicite.
  3. Rétablissez la couleur de la tuile, puis ajoutez temporairement * { color: #303840; } au début de la feuille de style. Le paragraphe contenant Label C reçoit alors cette déclaration directe. Supprimez ensuite la règle temporaire.

Ces vérifications illustrent la différence entre un composant qui établit une valeur héritée et un descendant qui reçoit sa propre déclaration. Le comportement attendu du texte découle des règles d’héritage et de détermination des valeurs de la spécification.

Quel est le contrat entre la page HTML et sa feuille de style ?

Séparez le chargement des ressources du comportement des sélecteurs. L’exemple intègre son CSS dans un élément style. Si vous préférez une feuille de style séparée, déplacez uniquement le contenu de cet élément dans un fichier texte brut nommé page-defaults.css, enregistré à côté du fichier HTML. Remplacez l’élément style entier par la ligne suivante dans head. Il s’agit d’un fragment de remplacement, et non d’un autre document complet.

<link rel="stylesheet" href="page-defaults.css">

Le type de lien stylesheet désigne une ressource CSS externe utilisée pour présenter le document. Le nom de fichier dans href doit pointer vers le fichier que vous avez réellement enregistré ; la déclaration ne crée pas ce fichier. La norme HTML définit cette relation dans Type de lien : stylesheet.

Pour cet exemple, le contrat obtenu est simple : le HTML fournit les éléments et les classes, tandis que le CSS fournit leur présentation. Renommer .tile dans la feuille de style nécessite de mettre à jour la classe correspondante dans le HTML. Déplacer le fichier CSS nécessite de mettre à jour sa référence de ressource. Aucun de ces changements ne nécessite un sélecteur plus spécifique.

Si la version externe semble dépourvue de style, vérifiez d’abord que le fichier CSS existe sous le nom attendu et que son contenu est bien du CSS, et non le document HTML qui l’entoure. Revenez à la version intégrée pour isoler les erreurs de chargement des ressources avant de modifier la cascade.

Quand utiliser :where() ou les couches de cascade ?

Utilisez ces fonctionnalités lorsqu’elles résolvent un problème supplémentaire. L’exemple complet ci-dessus ne dépend ni de l’une ni de l’autre.

Utilisez :where() pour des valeurs par défaut ciblées à spécificité nulle

Supposons que la page s’étoffe et comprenne plusieurs niveaux de titres. Ce fragment de feuille de style facultatif établit un espacement commun tout en permettant de remplacer facilement cette valeur par des sélecteurs de titres ordinaires :

/* Optional fragment: add to the example stylesheet. */
:where(h1, h2, h3) {
  margin-bottom: 0.75rem;
}

h2 {
  margin-bottom: 1rem;
}

Le sélecteur :where() entier a une spécificité nulle, arguments compris. Mais remplacer * par :where(*) ne résout pas le problème de couleur précédent : ce sélecteur correspond toujours à chaque élément et lui fournit une déclaration directe. Utilisez l’héritage pour résoudre ce problème. MDN indique que :where() est largement pris en charge par les navigateurs depuis janvier 2021 ; consultez son tableau de compatibilité si vous devez prendre en charge un navigateur plus ancien. La pseudo-classe :where().

Dans un navigateur qui ne prend pas en charge :where(), utilisez une liste de sélecteurs ordinaire telle que h1, h2, h3 pour ces valeurs par défaut d’espacement, puis placez les exceptions de spécificité égale plus loin dans la même feuille de style et la même couche. Les valeurs par défaut restent ciblées, mais leur spécificité n’est plus nulle. Spécificité.

Utilisez des couches lorsque des groupes de règles nécessitent un ordre explicite

Pour une feuille de style plus importante, ce fragment facultatif montre comment déclarer l’ordre des couches. Il s’ajoute à l’exemple complet ; il ne remplace pas l’ensemble de son CSS.

/* Optional fragment for browsers supporting cascade layers. */
@layer defaults, components;

@layer defaults {
  p {
    margin-bottom: 1rem;
  }
}

@layer components {
  .tile p {
    margin-bottom: 0.5rem;
  }
}

Pour les déclarations d’auteur normales, les couches ultérieures ont priorité sur les couches antérieures ; les déclarations normales hors couche ont priorité sur les déclarations en couche. Les déclarations importantes inversent l’ordre des couches : l’ajout de !important modifie donc cet agencement. Les couches organisent les règles concurrentes ; elles ne font pas hériter un enfant directement stylisé de la valeur de son parent. La règle @layer.

MDN indique que @layer est pris en charge par les principaux navigateurs depuis mars 2022. Si un navigateur cible plus ancien ne le prend pas en charge, laissez les styles essentiels en dehors des blocs de couches et utilisez l’approche sans couche montrée dans l’exemple complet. Ne placez pas l’unique copie de styles nécessaires dans une fonctionnalité non prise en charge. Prise en charge des couches de cascade.

Comment corriger une feuille de style existante sans ajouter de règles de remplacement ?

Procédez propriété par propriété. Pour un problème de couleur de texte, repérez la règle générale qui attribue directement la couleur aux descendants. Supprimez cette déclaration de la règle universelle, définissez la valeur de la page sur body et gardez les couleurs des composants sur leurs éléments racines. Conservez les déclarations au niveau des éléments uniquement là où le design exige une exception.

Répétez ensuite les trois modifications de la démonstration. Si le texte ordinaire d’un composant ne suit toujours pas son parent, recherchez une déclaration ciblant ce descendant. Si la modification de la bordure d’un composant ne change les bordures d’aucun de ses descendants, c’est normal : l’héritage des bordures diffère de celui de la couleur du texte. Héritage.

Une valeur par défaut facile à maintenir a un propriétaire clairement défini. Placez la typographie de la page à la limite de la page, la présentation du composant à la limite du composant et les exceptions délibérées sur les éléments concernés. Réservez les déclarations universelles aux choix que vous souhaitez vraiment appliquer à chaque élément correspondant, puis vérifiez ces limites avec une petite page locale.

Sources