Niveau Niveau expert

Le positionnement par ancre : anchor positioning

Tutorielcss

Publié par le (126 lectures)

position absolute positionnement infobulle ancre modale

Positionner en CSS a souvent été une mission hasardeuse. Flexbox et Grid ont grandement simplifié la tâche, mais il reste des cas où le positionnement précis d'un élément par rapport à un autre demeure un véritable casse-tête. C'est là qu'intervient le positionnement par ancre (anchor positioning), une nouvelle fonctionnalité CSS qui permet de placer visuellement n'importe quel élément par rapport à n'importe quel autre élément, sans avoir à se soucier de la structure du DOM.

Le positionnement par ancre va se révéler particulièrement utile pour :

  • Les info-bulles : afficher des informations supplémentaires lorsqu'on survole un élément.
  • Les menus contextuels : ouvrir un menu à côté d'un bouton ou d'une zone spécifique.
  • Les fenêtres modales : positionner un dialog (une modale) par rapport à un élément déclencheur.
  • Les étiquettes de formulaire : placer des messages d'erreur ou des indications près des champs concernés.

Exemple d'ancre et d'élément associé

⚠️ Attention : une ancre et un élément positionné éloignés dans le DOM vont poser des problèmes d'accessibilité, avec les lecteurs d'écran en particulier.

Compatibilité navigateurs (et @supports)

Voici le tableau de compatibilité pour le positionnement par ancre :

voir la légende associée
Support navigateurs pour CSS Anchor Positioning (source Can I Use)

Afin de permettre un support progressif, activez anchor-positioning via une détection de fonctionnalité @supports et fournissez une alternative simple.

@supports (anchor-name: --a) {
  /* ici les styles avec anchor-positioning */
}

Associer un élément à une ancre nommée

Le positionnement par ancre permet de lier un élément (appelé "élément positionné") à un autre élément (appelé "ancre") afin de positionner le premier relativement au second.

Pour définir une ancre, on se sert de la propriété anchor-name :

.mon-ancre {
  anchor-name: --nom-de-mon-ancre;
}

ℹ️ Notez la syntaxe spécifique de la valeur précédée d'un double trait d'union --, nécessaire pour cette propriété.

Puis, pour associer un élément et le positionner par rapport à cette ancre, on utilise position-anchor (sur un élément position: absolute|fixed) :

.element-positionne {
  position: absolute; /* ou fixed */
  position-anchor: --nom-de-mon-ancre;
}

À présent, l'élément positionné est aligné par rapport à l'ancre définie. Nous allons à présent pouvoir le placer précisément (avec anchor() ou position-area), mais aussi gérer les débordements avec position-try ou ses dimensions avec anchor-size().

ℹ️ Il est également possible d'associer un élément à une ancre à l'aide de l’attribut HTML anchor (voir un peu plus bas).

anchor() pour placer l'élément

La valeur-fonction anchor() permet de placer l'élément par rapport aux bords de l'ancre :

.element-positionne {
  position: absolute;
  position-anchor: --nom-de-mon-ancre; /* association */
  top: anchor(bottom); /* bord haut aligné sur le bas de l’ancre */
  left: anchor(left); /* bord gauche aligné sur la gauche de l’ancre */
}

Différents types de valeurs peuvent être utilisés avec anchor() :

  • Côtés physiques : top|right|bottom|left. Côtés logiques : start|end|self-start|self-end|inside|outside|center.
  • Compatible avec calc() : top: calc(anchor(bottom) + 10px).
  • Viser une autre ancre : top: anchor(--autre-ancre bottom, 50%) (2ᵉ valeur = fallback).

position-area pour (aussi) placer l'élément

Alternative à anchor(), la propriété position-area place l’élément dans une grille 3×3 centrée sur l’ancre.

.infobox {
  position: fixed;
  position-anchor: --ancre;
  position-area: top center; /* au-dessus, centré */
}

.toast {
  position-area: bottom span-all;
} /* toute la rangée du bas */

ℹ️ L'excellente ressource en ligne Anchor Tool permet de visualiser et tester facilement les positions d'ancrage.

anchor-size() pour définir la taille de l'élément

Cette propriété retourne une longueur basée sur la dimension de l’ancre et s'applique directement à l'élément associé.

Exemples :

.box {
  width: anchor-size(width);
} /* largeur = largeur de l'ancre */
.tooltip {
  margin-block-start: calc(anchor-size(height) / 4);
} /* marge = ¼ hauteur ancre */

position-try pour gérer les débordements

Propriété raccourcie de position-try-order et position-try-fallbacks, la propriété position-try permet de définir des options de repli appliquées automatiquement quand l’élément déborde (de la fenêtre ou du contenant).

Deux approches complémentaires :

  • Mots-clés intégrés (flip-inline, flip-block, top|right|bottom|left, etc.).
  • Options personnalisées nommées via @position-try --nom { … } pouvant définir position-area, des anchor() d’inset, margins, tailles, *-self: anchor-center, etc.

Exemple 1 — fallbacks intégrés (sans @position-try custom)

.tooltip {
  /* Essaie d’abord de “miroiter” horizontalement (gauche<->droite) si ça déborde,
     sinon tente en bas, puis en haut autour de l’ancre. */
  position-try: flip-inline, bottom, top;
}

Exemple 2 — fallbacks custom via @position-try

/* Option custom : place la tooltip sous l’ancre avec un espace de 8px */
@position-try --try-bottom {
  top: anchor(bottom);
  margin-top: 8px;
}

/* Option custom : place la tooltip à gauche de l’ancre avec un espace de 8px */
@position-try --try-left {
  position-area: left;
  margin-right: 8px;
}

/* Choisit l’option maximisant la hauteur disponible :
   on tente d’abord --try-left, puis --try-bottom si besoin. */
.tooltip {
  position-try: most-height --try-left, --try-bottom;
}
voir la légende associée
Menu déroulant avec solutions de repli (voir sur Codepen)

Ancres multiples

Il est tout à fait possible d'associer plusieurs ancres à un même élément. Pour ce faire, affectez plusieurs noms d'ancre à l'élément.

.anchor {
  anchor-name: --anchor1, --anchor2;
}
.element1 {
  position-anchor: --anchor1;
  left: anchor(--anchor1 left);
}

.element2 {
  position-anchor: --anchor2;
  left: anchor(--anchor2 right);
}

Exemple concret : une info-bulle (tooltip)

L’API Popover fournit une méthode simple pour créer un info-bulle et de la positionner à son ancre. Nous allons cette fois les associer via l’attribut HTML anchor puis la positionner en CSS.

<button id="tooltip-button" popovertarget="tooltip" aria-describedby="tooltip">En savoir plus</button>
<div id="tooltip" popover anchor="tooltip-button" class="info-bulle">Je suis une info-bulle !</div>
.info-bulle[popover] {
  margin: 0;
  inset: auto;
}

.info-bulle {
  position-area: right; /* à droite de l’ancre */
  position-try: flip-inline, bottom, top; /* miroirs et repli */
  max-inline-size: 28ch;
}

[popover]::backdrop {
  background-color: hsl(0 0% 0% / 60%);
}
voir la légende associée
Exemple d'info-bulle présente sur l'outil Spätzi

HTML vs CSS : quelle association choisir ?

Voici un comparatif rapide entre l’attribut HTML anchor et la paire CSS anchor-name + position-anchor.

Aspect Attribut HTML anchor CSS anchor-name + position-anchor
Association Déclarative dans le markup, sans CSS côté élément positionné Définie côté CSS, via un nom d’ancre
Multiples ancres Une seule « default anchor » par élément Autant de noms que nécessaire, y compris dynamiquement
Lisibilité Intention explicite dans le HTML, idéal avec Popover Centralisation côté CSS, pratique pour thèmes/variantes
Portée DOM Indépendante de la hiérarchie (pas besoin de parent commun) Idem (pas de contrainte DOM)

Recommandations rapides :

  • Utilisez l’attribut anchor quand vous contrôlez le code (ex. composants avec Popover).
  • Préférez la voie CSS quand vous avez des scénarios multi-ancres, des variantes de thème, ou peu d’accès au HTML.

En résumé global

Pour finir ce (long) tutoriel, voici un petit mémo pour retenir les étapes-clés de ce nouveau mode de positionnement :

  1. Associez un élément à son ancre via anchor-name: --nom; sur l’ancre et position-anchor: --nom; sur l’élément positionné (ou via l’attribut HTML anchor="id-de-l-ancre")
  2. Placez-le à votre guise avec anchor() ou position-area,
  3. En bonus, attribuez des dimensions à l’élément positionné avec anchor-size().
  4. En bonus encore, gérez les débordements avec position-try (ou @position-try pour des scénarios personnalisés)

Ressources

Outils/démos personnelles

Commenter

Vous devez être inscrit et identifié pour utiliser cette fonction.

Connectez-vous (déjà inscrit)

Oubli de mot de passe ? Pas de panique, on va le retrouver

Pas encore inscrit ? C'est très simple et gratuit.