12k
All articles

Comment corriger l'espace superflu au-dessus et en dessous du texte en CSS

Supprimez l’espace au-dessus et au-dessous du texte avec text-box-trim en CSS. Comprenez le rôle des métriques de police et de line-height, choisissez text-box-edge et prévoyez une solution de repli.

OpenReplay Team
OpenReplay Team
Comment corriger l'espace superflu au-dessus et en dessous du texte en CSS

L’espace superflu au-dessus et en dessous du texte a deux origines : les métriques verticales intégrées à la police, et le demi-interlignage que line-height ajoute (ou retire) de chaque côté de la ligne. La solution CSS native est text-box: trim-both cap alphabetic.

Vous avez défini line-height: 1.1 et supprimé toutes les marges, mais le titre occupe toujours une boîte plus haute que ses lettres. Vous avez donc ajouté une marge négative, ajustée jusqu’à obtenir un rendu satisfaisant, puis vous êtes passé à autre chose. Et puis la police de la charte graphique a changé.

Cet article explique d’où vient cet espace, pourquoi les marges négatives ne peuvent pas le supprimer de manière fiable, et comment text-box-trim, text-box-edge et la propriété raccourcie text-box permettent de le rogner sur les titres et les boutons. Il se termine par une solution de repli pour les anciens navigateurs.

Points clés à retenir

  • L’espace superflu autour du texte provient de l’espace vertical qu’une police réserve à ses glyphes les plus hauts et les plus profonds, auquel s’ajoute l’interlignage que line-height ajoute ou retire, et que CSS répartit à parts égales au-dessus et en dessous de chaque ligne.
  • text-box-trim détermine les bords à rogner (none, trim-start, trim-end, trim-both), et text-box-edge détermine la ligne jusqu’à laquelle chaque bord est rogné.
  • text-box: trim-both cap alphabetic rogne le haut jusqu’à la hauteur de capitale et le bas jusqu’à la ligne de base, ce qui correspond à la façon dont la plupart des maquettes mesurent les espacements.
  • text-box-edge n’a aucun effet tant que text-box-trim n’a pas une valeur autre que none.
  • text-box-trim n’est pas héritée : déclarez-la sur chaque élément à rogner, et non sur body.

Le symptôme : un écart que le padding n’explique pas

Un titre sans padding, sans marge et avec un line-height serré affiche toujours un espace vide au-dessus de ses capitales et sous sa ligne de base. Les DevTools montrent une boîte de contenu plus haute que les lettres visibles, et rien dans votre feuille de styles n’explique cette différence.

Le correctif habituel consiste à appliquer une marge négative trouvée par tâtonnements :

h1 {
  line-height: 1.1;
  /* Tuned by eye for one font; wrong for any other */
  margin-block: -0.2em -0.15em;
}

Ces valeurs sont données à titre d’exemple. Elles ne découlent d’aucun calcul, et c’est bien là le problème.

Pourquoi y a-t-il un espace superflu au-dessus et en dessous du texte ?

L’espace superflu au-dessus et en dessous du texte a deux causes, les métriques de la police et le demi-interlignage, et toutes deux relèvent du texte et non du modèle de boîte.

D’abord, une police réserve un espace vertical pour l’ensemble de ses glyphes, des grandes capitales jusqu’aux jambages descendants de lettres comme g et y. La quantité d’espace réservée varie d’une police à l’autre, comme le souligne la documentation MDN de text-box-trim : un même font-size produit donc une boîte de ligne plus ou moins haute selon la police.

Ensuite, line-height ajoute de l’interlignage. La spécification CSS 2.1 relative à l’interlignage et au demi-interlignage définit l’interlignage comme la différence entre la valeur de line-height et la somme de l’ascendante et de la descendante de la police. La moitié de cet interlignage est placée au-dessus des glyphes, l’autre moitié en dessous. Dans de nombreuses polices, la somme de l’ascendante et de la descendante dépasse 1.1em ; avec line-height: 1.1, le demi-interlignage est donc souvent faible, voire négatif. Dans tous les cas, l’espace vide que les métriques propres à la police laissent au-dessus des capitales et sous la ligne de base subsiste.

Chaque police réserve un espace vertical différent : une marge négative ajustée pour une police est donc fausse pour une autre. Cela vaut aussi pour la police de repli affichée avant le chargement d’une police web, un problème qui est également à l’origine des décalages de mise en page liés aux polices. Si vous rejouez une session dans laquelle la police web arrive tardivement, vous pouvez voir l’image précise où la police est remplacée et où le titre corrigé par une marge « magique » fait un saut.

Comment combler l’écart avec text-box-trim ?

text-box-trim détermine les bords d’un bloc de texte à rogner, et text-box-edge détermine la ligne jusqu’à laquelle chaque bord est rogné. text-box-trim accepte quatre mots-clés :

  • none : la valeur initiale. Rien n’est rogné.
  • trim-start : rogne le bord supérieur (over).
  • trim-end : rogne le bord inférieur (under).
  • trim-both : rogne les deux bords.

Voici le même titre, dans lequel l’astuce de la marge a été remplacée :

h1 {
  line-height: 1.1;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

Avec text-box-trim, le bord supérieur de la boîte se situe désormais au sommet des capitales et le bord inférieur sur la ligne de base. L’espace superflu disparaît, quelle que soit la police, car le navigateur lit les positions directement dans la police au lieu de se fier à votre estimation.

La propriété raccourcie text-box combine les deux propriétés en une seule déclaration. Ces deux règles sont équivalentes :

h1 {
  text-box: trim-both cap alphabetic;
}

/* Same result: an omitted trim keyword means trim-both */
h1 {
  text-box: cap alphabetic;
}

Quelles valeurs de text-box-edge sont utiles ?

Pour le texte horizontal, deux paires de bords couvrent la quasi-totalité des cas : cap alphabetic et ex alphabetic. text-box-edge accepte deux mots-clés : le premier définit le bord supérieur, le second le bord inférieur.

Mot-cléBordRogne jusqu’à
textsupérieur ou inférieurle bord du texte défini par la police (c’est la valeur à laquelle se résout la valeur par défaut auto)
capsupérieur uniquementle sommet des lettres capitales
exsupérieur uniquementla hauteur d’x (sommet des minuscules sans hampe)
alphabeticinférieur uniquementla ligne de base alphabétique

cap alphabetic correspond à la façon dont les designers mesurent généralement l’espace autour d’un titre ou d’un libellé : de la hauteur de capitale à la ligne de base. Utilisez ex alphabetic lorsque le texte est essentiellement en minuscules et que la hauteur d’x constitue le sommet visuel :

.lowercase-label {
  text-box: trim-both ex alphabetic;
}

Trois règles piègent la plupart des développeurs :

  • text-box-edge n’a aucun effet à elle seule. Rien n’est rogné tant que text-box-trim n’a pas une valeur autre que none.
  • Dans la propriété raccourcie text-box, omettre le mot-clé de rognage équivaut à trim-both, et omettre le bord équivaut à auto. Le mot-clé normal équivaut à none auto.
  • Ni text-box-trim ni text-box-edge ne sont héritées. Les définir sur body ne rogne pas les titres ou les boutons qu’il contient. Déclarez-les sur chaque élément, ou dans les styles de base de chaque composant.

Centrer le libellé d’un bouton avec text-box

Un bouton doté d’un padding identique en haut et en bas affiche souvent un libellé décentré. Le padding est bien égal, mais l’espace interne de la police au-dessus des capitales et sous la ligne de base ne l’est pas, et cette différence apparaît comme un padding supplémentaire d’un côté.

.button {
  padding: 0.75rem 1.25rem;
}

Rogner la boîte du libellé jusqu’à la hauteur de capitale et à la ligne de base fait du padding le seul espace entre le texte et le bord du bouton :

.button--trimmed {
  padding: 0.75rem 1.25rem;
  text-box: trim-both cap alphabetic;
}

Avec un libellé comme « Submit », l’espace au-dessus des capitales paraît désormais identique à l’espace sous la ligne de base. La spécification CSS Inline Layout permet d’appliquer text-box-trim aux conteneurs de bloc, aux conteneurs multicolonnes et aux boîtes en ligne, mais les navigateurs diffèrent sur ce point. D’après l’annonce d’intention de déploiement (intent to ship) de Mozilla, Firefox et Safari rognent les boîtes en ligne, mais pas Chromium. Le rognage n’a pas non plus d’effet sur un conteneur flex ou grid : appliquez donc display: inline-block au bouton, ou placez le rognage sur un élément de libellé à l’intérieur de celui-ci. Comme le bord inférieur est rogné jusqu’à la ligne de base, les jambages descendants de lettres comme g, p et y débordent dans le padding. C’est le résultat typographique attendu, et non un bug.

Prise en charge par les navigateurs et solution de repli

MDN classe text-box comme Baseline 2026, nouvellement disponible depuis août 2026, et précise que la propriété peut ne pas fonctionner sur des appareils ou des navigateurs plus anciens. Les navigateurs qui ne la prennent pas en charge ignorent la déclaration et affichent le texte avec l’espacement normal de la police. La solution de repli correspond donc à la mise en page non rognée : rien n’est cassé, c’est simplement moins précis. Si un design dépend des anciennes marges de compensation, conservez-les uniquement pour ces navigateurs à l’aide d’une requête de fonctionnalité @supports :

h1 {
  text-box: trim-both cap alphabetic;
}

@supports not (text-box: trim-both cap alphabetic) {
  h1 {
    /* Old per-font patch, kept only where text-box is unsupported */
    margin-block: -0.2em -0.15em;
  }
}

Conclusion

L’écart autour du texte résulte des métriques de la police et du demi-interlignage. Une marge négative ne fait que le masquer, et pour une seule police. Remplacez ces marges par text-box: trim-both cap alphabetic sur chaque composant de titre et de libellé, placez les éventuelles marges héritées derrière @supports not, et vérifiez le résultat avec votre police de repli comme avec votre police web.

FAQ

text-box-trim modifie-t-elle l'espacement entre les lignes d'un paragraphe de plusieurs lignes ?

Non. Sur un conteneur de bloc, text-box-trim n'agit que sur le haut de la première ligne et le bas de la dernière ligne. Le demi-interlignage entre les lignes renvoyées à la ligne reste inchangé : line-height continue donc de contrôler l'espacement à l'intérieur du paragraphe. Seuls les bords extérieurs du bloc se rapprochent de la hauteur de capitale et de la ligne de base.

Pourquoi ne pas simplement définir line-height: 1 pour supprimer l'espace superflu ?

Définir line-height: 1 ne modifie que l'interlignage. L'espace que la police réserve elle-même au-dessus des capitales et sous la ligne de base subsiste : les bords de la boîte ne s'alignent donc toujours pas sur la hauteur de capitale ni sur la ligne de base. Cela resserre également l'espacement entre les lignes renvoyées à la ligne. text-box-trim rogne uniquement les bords extérieurs selon les métriques de la police et laisse line-height libre de gérer la lisibilité.

Le rognage avec text-box affecte-t-il la mise en page des éléments environnants ?

Oui. text-box-trim rapproche les bords du contenu de l'élément des métriques choisies : l'élément occupe donc moins d'espace dans l'axe de bloc. Les marges, les espacements (gaps) flex et grid et les éléments voisins sont alors mesurés à partir du bord rogné, et non de l'espace réservé par la police. C'est pourquoi les tokens d'espacement deviennent visuellement exacts une fois le rognage appliqué, et pourquoi il est important de supprimer les anciennes marges négatives.

Comment détecter la prise en charge de text-box en JavaScript ?

Appelez CSS.supports('text-box', 'trim-both cap alphabetic'). La méthode renvoie true dans les navigateurs qui acceptent cette déclaration et false dans les autres. Elle effectue le même test que la règle @supports en CSS : vous pouvez donc l'utiliser pour décider à l'exécution s'il faut appliquer des marges de compensation, ou pour journaliser le chemin de rendu emprunté par un utilisateur.

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.