Pour une ligne horizontale d’images en ligne alignées sur la ligne de base, celle-ci se situe au bord inférieur de la marge de chaque image. Ce guide explique comment repérer cette coordonnée dans Chrome sur Mac, la vérifier avec un petit marqueur et déterminer quand cette méthode ne s’applique pas.

Pourquoi une ligne contenant uniquement des images a-t-elle une ligne de base ?

Une ligne composée uniquement d’images participe tout de même à la mise en page en ligne CSS. Un img affiché correctement est un élément remplacé : le navigateur met en page sa boîte selon les règles CSS au lieu de traiter son image comme du texte. WHATWG décrit ce comportement de rendu dans les règles de rendu des images de la norme HTML.

Dans une mise en page en ligne horizontale ordinaire, une image sans ligne de base textuelle intrinsèque utilise son bord inférieur de marge pour l’alignement sur la ligne de base. Ainsi, deux images alignées sur la ligne de base et de hauteurs différentes peuvent partager la même ligne de base alors que leurs bords supérieurs se trouvent à des hauteurs différentes. Cette règle concerne leurs boîtes ; elle n’examine pas le dessin qu’elles contiennent. Voir CSS 2, alignement vertical.

Trois limites différentes sont à prendre en compte :

Limite Signification Référence appropriée pour la ligne de base ?
Bord de l’image visible Endroit où s’arrêtent les pixels visibles de l’image Non ; le fichier peut contenir des zones transparentes
Bas de la boîte de bordure de l’image Le bas renvoyé par getBoundingClientRect() Oui, après prise en compte de la marge inférieure et vérification de l’alignement sur la ligne de base
Bas de la boîte de ligne Limite inférieure de la ligne CSS complète Non ; elle peut se prolonger sous la ligne de base

La police du parent et line-height restent importants même lorsqu’aucune lettre n’est visible. CSS décrit une contribution invisible fondée sur la police, appelée entreligne, qui aide à définir la hauteur et la profondeur minimales de la ligne. Cela explique pourquoi une image peut reposer sur la ligne de base alors que la ligne conserve un espace en dessous. La spécification CSS Inline Layout décrit ces métriques de police et ces limites de mise en page ; la version publiée consultée est un document de travail, donc il ne faut pas supposer que ses fonctionnalités les plus récentes sont prises en charge par tous les navigateurs.

Comment trouver la ligne de base sur une page existante ?

Commencez par une page que vous pouvez inspecter dans Chrome sur votre Mac. Faites un clic droit sur une image et choisissez Inspecter. Chrome ouvre le panneau Elements en sélectionnant cet élément ; le volet Styles affiche les règles CSS qui lui sont appliquées. Google décrit cette procédure dans Ouvrir les outils de développement Chrome.

Vérifiez les conditions suivantes avant de calculer une coordonnée :

  1. L’image participe au flux en ligne normal sur la ligne visée.
  2. Son alignement effectif est vertical-align: baseline.
  3. Le mode d’écriture est horizontal.
  4. Ni l’image ni ses ancêtres ne comportent de transformation ou de décalage de positionnement visuel qui affecte la mesure.
  5. Vous mesurez l’image elle-même, et non un conteneur autour d’elle qui aurait son propre comportement de ligne de base.

Ces conditions définissent le champ d’application du calcul. Par exemple, vertical-align: bottom aligne un élément sur le bas de la ligne, tandis que middle utilise la ligne de base du parent plus la moitié de sa hauteur d’x. Aucune de ces valeurs ne signifie que le bord inférieur de l’image indique la ligne de base du parent. MDN explique ces différences dans sa référence vertical-align.

Une fois ces conditions réunies, utilisez cette relation, en exprimant toutes les distances en pixels CSS :

baselineY = imageBorderBoxBottom + imageMarginBottom

getBoundingClientRect() fournit la position du bas de la boîte de bordure par rapport à la fenêtre d’affichage. Son rectangle inclut le remplissage et les bordures, qu’il ne faut donc pas ajouter une deuxième fois. Les marges se trouvent à l’extérieur de ce rectangle. MDN documente la géométrie renvoyée et son système de coordonnées dans Element.getBoundingClientRect().

À titre d’exemple purement illustratif, supposons que le bas de la boîte de bordure de l’image soit 240.5 et que sa marge inférieure soit 6. La ligne de base se trouve donc à 246.5 pixels CSS du haut de la fenêtre d’affichage. Si le haut de la boîte de bordure du conteneur est 200, cette ligne de base se trouve à 46.5 pixels CSS sous le bord supérieur de la bordure du conteneur. Il s’agit d’un décalage par rapport au bord de la bordure, et non automatiquement par rapport au bord de la zone de contenu.

Mesurez une autre image répondant aux critères sur la même ligne pour vérifier le résultat. Son bord inférieur de marge doit indiquer la même ligne de base, même si sa hauteur diffère. En cas de désaccord, inspectez l’alignement, les conteneurs, le positionnement ou les retours à la ligne avant de modifier le CSS. Conservez les valeurs fractionnaires pendant la comparaison.

Comment vérifier le résultat avec un marqueur de ligne de base ?

Un outil de diagnostic utile est un bloc en ligne vide, de largeur, hauteur, marges, remplissage et bordures nuls, aligné sur la ligne de base. Comme il ne contient aucune boîte de ligne dans le flux, sa ligne de base est son bord inférieur de marge. Toutes ces dimensions étant nulles, ce bord coïncide avec sa position verticale mesurée. Cela découle de la règle CSS 2 concernant la ligne de base des blocs en ligne.

Le programme complet suivant, à exécuter dans la console, crée une démonstration temporaire avec deux images rectangulaires neutres et un marqueur. Il utilise une racine fantôme pour isoler les styles internes de l’exemple des sélecteurs ordinaires de la page. Exécutez-le dans un document en mode standard, sans transformation appliquée au document ou au corps. Il mesure uniquement sa propre ligne synthétique, et non le contenu d’une page existante.

Ouvrez la Console avec Command + Option + J, comme indiqué dans les raccourcis des outils de développement Chrome, puis exécutez le programme. Aucune bibliothèque à installer ni aucun fichier image externe ne sont nécessaires. L’exemple génère ses rectangles à l’aide de l’API Canvas standard.

(async () => {
  if (document.compatMode !== "CSS1Compat") {
    throw new Error("Use a standards-mode document for this demonstration.");
  }

  const host = document.createElement("div");
  host.style.cssText =
    "all:initial;position:fixed;top:16px;left:16px;" +
    "z-index:2147483647;background:white;padding:16px;" +
    "color:#222;font:16px/1.5 sans-serif;";
  const root = host.attachShadow({ mode: "open" });
  const label = document.createElement("div");
  label.textContent = "Sample A and Sample B";
  const row = document.createElement("div");
  row.style.cssText =
    "display:block;position:relative;width:280px;" +
    "margin:0;padding:0;border:0;white-space:nowrap;" +
    "writing-mode:horizontal-tb;font:16px/24px sans-serif;" +
    "background:#eee;";
  const close = document.createElement("button");
  close.textContent = "Remove demonstration";
  close.addEventListener("click", () => host.remove());
  root.append(label, row, close);
  document.body.append(host);

  try {
    const images = [];
    const samples = [
      { label: "Sample A", height: 32, color: "#777" },
      { label: "Sample B", height: 48, color: "#aaa" }
    ];

    for (const sample of samples) {
      const canvas = document.createElement("canvas");
      canvas.width = 64;
      canvas.height = sample.height;
      const context = canvas.getContext("2d");
      if (!context) throw new Error("A 2D canvas context is required.");
      context.fillStyle = sample.color;
      context.fillRect(0, 0, canvas.width, canvas.height);

      const image = document.createElement("img");
      image.alt = sample.label;
      image.width = 64;
      image.height = sample.height;
      image.style.cssText =
        "display:inline;vertical-align:baseline;" +
        "margin:0 12px 0 0;padding:0;border:0;";
      image.src = canvas.toDataURL("image/png");
      row.append(image);
      images.push(image);
    }

    await Promise.all(images.map(image => image.decode()));
    if (!host.isConnected) return;

    const marker = document.createElement("span");
    marker.style.cssText =
      "display:inline-block;vertical-align:baseline;" +
      "width:0;height:0;margin:0;padding:0;border:0;" +
      "font-size:0;line-height:0;";
    row.append(marker);

    const baselineY = marker.getBoundingClientRect().bottom;
    const rowTop = row.getBoundingClientRect().top;
    console.table(images.map(image => ({
      sample: image.alt,
      imageBottom: image.getBoundingClientRect().bottom,
      markerBaseline: baselineY,
      baselineFromRowTop: baselineY - rowTop
    })));

    const guide = document.createElement("div");
    guide.style.cssText =
      "position:absolute;left:0;right:0;height:1px;" +
      "background:#222;pointer-events:none;";
    guide.style.top = `${baselineY - rowTop}px`;
    row.append(guide);
  } catch (error) {
    host.remove();
    throw error;
  }
})();

Le programme attend le décodage des deux images avant de les mesurer. La méthode HTMLImageElement.decode() documentée renvoie une promesse et peut échouer si le décodage échoue ; dans ce cas, le programme supprime son panneau temporaire et signale l’erreur.

Les deux images ont une marge inférieure nulle ; leurs valeurs imageBottom devraient donc correspondre à markerBaseline. Le fin guide horizontal indique cette coordonnée. L’arrière-plan de la ligne permet aussi de distinguer la ligne de base de tout espace restant en dessous. Sélectionnez Supprimer la démonstration lorsque vous avez terminé.

Pour une expérience contrôlée, remplacez la marge inférieure des images de l’exemple par 6px au lieu de 0 dans le style de l’image. Le bas de leur boîte de bordure devrait alors se trouver six pixels CSS au-dessus de la ligne de base marquée. Appliquez la formule précédente pour retrouver la coordonnée commune. Vous disposez ainsi de deux références indépendantes dans l’exemple : le bord de marge de l’image et le marqueur vide.

Quand cette méthode nécessite-t-elle une autre approche ?

Un marqueur est un ajout de diagnostic ; il mesure donc la mise en page qui en résulte. En insérer un dans un paragraphe existant quelconque peut créer une possibilité de retour à la ligne ou modifier la mise en page d’une autre manière. Privilégiez le calcul à partir de l’image existante lorsque ses conditions préalables sont réunies. Si vous insérez un marqueur dans du contenu réel, vérifiez que les mêmes images restent sur la même ligne et que leur position n’a pas changé.

Situation Étape suivante appropriée
Les images utilisent l’alignement top, bottom ou middle Inspectez cette règle d’alignement ; n’appliquez pas telle quelle la formule pour les images alignées sur la ligne de base
L’image se trouve dans un conteneur bloc en ligne Inspectez la ligne de base du conteneur, qui peut provenir de sa dernière ligne de contenu
Les images occupent plusieurs lignes après retour à la ligne Déterminez séparément la ligne de base de chaque ligne
Le parent utilise une mise en page flex ou en grille Inspectez les règles d’alignement de cette mise en page avant de traiter la rangée comme une ligne en ligne
Le document utilise une écriture verticale Utilisez les règles de ligne de base adaptées au mode d’écriture plutôt qu’une coordonnée y du bord inférieur
L’image ne s’est pas chargée correctement Déterminez son état de rendu avant de la traiter comme une boîte d’image affichée

La dernière condition est importante, car WHATWG décrit différents modes de rendu pour les images affichées, les images en attente et le texte alternatif. Une image défectueuse qui affiche son libellé peut donc nécessiter une interprétation différente de celle d’une image rendue correctement que vous vouliez mesurer. Voir les règles de rendu des images HTML.

Évitez de déduire une ligne de base commune simplement parce que plusieurs rectangles d’image ont des coordonnées supérieures similaires. Des images de hauteurs différentes peuvent partager une ligne de base tout en ayant des sommets différents. À l’inverse, des sommets alignés ne prouvent pas un alignement sur la ligne de base. Vérifiez quelles boîtes participent à la même ligne et quelle règle d’alignement s’applique.

Les API de mesure du texte ou les bibliothèques de mise en forme peuvent-elles fournir la réponse ?

Les méthodes de géométrie du navigateur utilisées ici renvoient des rectangles, et non un champ dédié à la ligne de base. Range.getClientRects() peut aider à inspecter les zones occupées par une plage, mais les rectangles renvoyés ne donnent pas directement la coordonnée de la ligne de base. MDN décrit cette interface dans Range.getClientRects().

Les métriques de texte Canvas répondent à une autre question : comment un texte dessiné sur Canvas se rapporte à la ligne de base de texte sélectionnée dans le contexte Canvas. Par exemple, actualBoundingBoxAscent et actualBoundingBoxDescent décrivent les limites de l’encre du texte par rapport à cette référence. Elles ne permettent pas de localiser directement une rangée d’images DOM existante. Voir la documentation TextMetrics de MDN.

Une bibliothèque de mise en forme du texte a également une responsabilité plus restreinte que la mise en page des lignes du navigateur. Le manuel de HarfBuzz indique qu’elle met en forme des séquences de texte et fournit des informations sur la disposition des glyphes, tandis que les retours à la ligne des paragraphes et la justification ne relèvent pas de ses fonctions. Installer HarfBuzz ne permet donc pas de mesurer une ligne d’images uniquement dans un navigateur. Son champ d’application documenté permet d’établir cette limite.

Pour une ligne horizontale composée uniquement d’images, vérifiez d’abord qu’elles sont dans le flux en ligne normal et alignées sur la ligne de base. Relevez ensuite le bas de la boîte de bordure d’une image répondant aux critères et ajoutez sa marge inférieure. Utilisez le marqueur de taille nulle dans une mise en page contrôlée si vous avez besoin d’une vérification visuelle, et réévaluez le contexte de mise en forme dès que ces deux références ne concordent pas.

Sources