Positionnement de l'ancrage

Lorsque vous placez un info-bulle ou un menu déroulant, vous souhaitez souvent le positionner par rapport à un autre élément de la page. Bien qu'il existe des méthodes utilisant le positionnement absolu pour obtenir cet effet, les exigences plus complexes ont historiquement recours au positionnement des éléments à l'aide de JavaScript.

Le positionnement d'ancrage CSS permet de positionner de manière déclarative un élément par rapport à un autre.

Éléments d'attache

Pour qu'un élément devienne une ancre, attribuez-lui une valeur anchor-name correspondant à une chaîne commençant par deux tirets. Il s'agit de l'identifiant que l'élément positionné utilisera pour trouver son ancrage. Il est utile de lui donner un nom descriptif. Vous pouvez même attribuer plusieurs noms d'ancres à un élément s'il doit être utilisé comme ancre de différentes manières.

Vous devrez définir quelques propriétés sur l'élément positionné pour qu'il puisse être rattaché. Tout d'abord, vous devez extraire l'élément du flux du document pour qu'il flotte, en définissant position: absolute ou position: fixed.

Ensuite, vous devrez définir l'ancrage auquel vous souhaitez vous attacher en définissant position-anchor sur le nom d'ancrage que vous avez défini sur l'ancrage.

Enfin, vous devez définir la position de l'ancrage. Vous en saurez plus sur position-area plus loin dans ce module.

#anchor {
   anchor-name: --my-anchor;
}

#positionedElement {
     position: absolute;
     position-anchor: --my-anchor;
     position-area: end;
}

Attaches implicites

Les popovers sont encore plus simples à ancrer. Lorsque vous ouvrez un popover à l'aide d'un bouton avec un popovertarget ou en définissant un source avec showPopover({source}), le popover a déjà une "ancre implicite" définie. Étant donné qu'un pop-over est déjà flottant avec position: fixed par défaut, il vous suffit de définir la position pour le positionner.

#anchor{}

#positionedElement {
  position-area: end;
  margin: unset;
}

Définir le champ d'application des ancres potentielles

Vous pouvez implémenter le positionnement d'ancrage dans un composant afin d'utiliser un modèle tel qu'un menu déroulant à plusieurs endroits. Si vous utilisez le même anchor-name plusieurs fois, comment vous assurez-vous que chaque élément positionné trouve le bon ancrage ?

Les solutions JavaScript consistent à ajouter des ID uniques à chaque ancre, puis à y faire référence à partir de l'élément positionné. Cette méthode devient vite fastidieuse. CSS propose une solution plus simple avec anchor-scope.

La propriété anchor-scope définit les noms d'ancres qui ne seront mis en correspondance qu'entre un élément et ses descendants. Il accepte une liste d'un ou plusieurs noms d'ancres ou le mot clé all pour limiter le champ d'application de tous les noms d'ancres définis.

Un anchor-scope est idéalement ajouté à un ancêtre de l'élément positionné et de l'élément d'ancrage qui ne contient pas d'autres éléments d'ancrage portant le même nom. Il s'agit souvent de la racine du composant réutilisable.

L'exemple suivant montre la différence que anchor-scope fait lorsqu'il est appliqué à des éléments répétés avec le même anchor-name. Dans l'exemple, tous les éléments <img> et les bannières d'images font référence au nom d'ancrage --image. Lorsque anchor-scope est appliqué aux éléments <li>, position-anchor: --image ne correspond qu'à l'élément <img> du même élément <li> que la bannière. Sinon, il correspond au dernier <img> affiché.

Positionnement

Maintenant que vous avez ancré l'élément à votre ancre, il est temps de le positionner. Le positionnement d'ancrage propose deux méthodes de positionnement : position-area et la fonction anchor().

position-area

La propriété position-area vous permet de positionner un élément autour de l'ancrage en spécifiant un ou deux mots clés. Cela couvre de nombreux cas d'utilisation courants et constitue souvent un bon point de départ.

Fonctionnement de position-area

position-area fonctionne en créant un bloc de contenu pour l'élément positionné dans une zone générée par les bords de l'ancre et le bloc de contenu d'origine de l'élément positionné.

Bien qu'il existe de nombreux mots clés pour position-area, ils peuvent être répartis en quelques catégories pour les rendre plus compréhensibles. Anchor-tool.com est un excellent outil pour explorer la syntaxe.

Mots clés physiques

Vous pouvez utiliser les mots clés physiques top, left, bottom, right et center. Par exemple, position-area: top right placera l'élément positionné au-dessus et à droite de l'ancrage. Ces mots clés ont également des équivalents pour les axes physiques : y-start, x-start, y-end et x-end.

Mots clés logiques

Vous pouvez également utiliser les mots clés logiques block-start, block-end, inline-start et inline-end. Par exemple, position-area: block-end inline-start placera l'élément positionné sous et à gauche de l'ancrage dans les langues comme l'anglais, ou après l'ancrage sur l'axe de bloc et avant l'ancrage sur l'axe en ligne dans le mode d'écriture du document. center peut également être utilisé avec un mot clé logique.

Vous pouvez également omettre l'axe si vous spécifiez des mots clés logiques, avec l'axe de bloc en premier et l'axe en ligne en second. position-area: start end est identique à position-area: block-start inline-end ou même à position-area: inline-end block-start.

S'étendre sur plusieurs zones de grille

Jusqu'à présent, vous avez peut-être remarqué que ces options ne vous permettent de placer l'élément positionné que dans un seul espace de grille. L'ajout du préfixe span aux propriétés physiques ou logiques ajoute l'espace de grille central adjacent. position-area: span-top right sera positionné à droite de l'ancrage, et du bas de l'ancrage au haut du bloc de contenu d'origine de l'élément positionné.

position-area: block-end span-inline-end est une zone de position courante pour un menu déroulant.

Le mot clé span-all s'étend sur trois lignes ou colonnes.

Mot clé unique

Si vous ne définissez qu'un seul mot clé, l'autre axe est défini automatiquement. Cette fonctionnalité fonctionne en grande partie comme vous l'attendez, mais il peut être utile de comprendre comment elle fonctionne.

Si le mot clé fourni est clair concernant son axe, l'autre axe est calculé comme span-all. Cela signifie que position-area: bottom équivaut à position-area: bottom span-all. L'élément positionné se trouvera sous l'ancrage et disposera de toute la largeur du bloc de contenu.

En revanche, si le mot clé n'indique pas clairement un axe, il est répété. position-area: start équivaut à start start et est placé en haut à gauche de l'ancrage dans les langues qui se lisent de gauche à droite.

Fonction anchor()

Pour les cas d'utilisation plus avancés, position-area peut ne pas répondre à vos besoins. La fonction anchor() vous permet de définir des propriétés d'encart individuelles en fonction de la position d'un autre élément. Cela correspond à une longueur CSS, ce qui signifie que vous pouvez l'utiliser dans des calculs et avec d'autres fonctions CSS. Vous pouvez également attacher différents côtés à différentes ancres.

La fonction anchor() prend un nom d'ancrage et un côté d'ancrage. Si votre élément possède une ancre par défaut, définie avec position-anchor ou implicitement, par exemple avec un pop-up, vous pouvez omettre le nom de l'ancre.

.positionedElement {
  block-start: anchor(--my-anchor start);
  /*  OR  */
  position-anchor: --my-anchor;
  block-start: anchor(start);
}

Valeurs de remplacement

Si aucune ancre n'est trouvée pour une fonction anchor(), l'intégralité de la déclaration ne sera pas valide. Cela peut se produire si l'ancrage est affiché après l'élément positionné ou s'il n'existe pas d'élément avec un anchor-name correspondant. Pour gérer ce problème, vous pouvez définir une durée ou un pourcentage de remplacement.

.positionedElement {
   block-start: anchor(--my-anchor, 100px)
}

Dans l'exemple précédent, la valeur de gauche de l'élément positionné est ancrée à --focused-anchor, mais ce anchor-name n'existe que lorsque le premier bouton est pointé ou sélectionné. Étant donné qu'une fonction anchor() est résolue en longueur, vous pouvez utiliser une autre ancre comme solution de repli. Si nous n'avions pas fourni de remplacement, l'élément positionné ne le serait pas.

Mots clés côté ancre

La valeur du côté d'ancrage choisit le bord de l'ancrage à positionner. Comme pour position-area, la valeur du côté d'ancrage accepte plusieurs types de syntaxe.

Type Valeurs Description
Physique top, left, bottom, right

Les mots clés physiques correspondent à un côté spécifique de l'ancrage, mais ne peuvent être utilisés que sur le même axe que l'encart de l'élément positionné que vous définissez.

Par exemple, top: anchor(bottom) positionne le haut de l'élément en bas de l'ancrage, mais left: anchor(top) ne fonctionnera pas.

Côté inside, outside

Le mot clé inside correspond au même côté que la propriété inset, et le mot clé outside correspond au côté opposé sur le même axe.

Par exemple, inset-block-start: anchor(inside) fait référence au côté block-start de l'ancrage, et inset-inline-end: (outside) fait référence au côté inline-start de l'ancrage.

Logique start, end, self-start, self-end

Les mots clés logiques font référence aux côtés de l'ancrage en fonction du mode d'écriture de l'élément positionné avec self-start et self-end, ou avec le mode d'écriture du bloc de contenu de l'élément positionné avec start et end.

Pourcentage 0 % à 100 %

Une valeur de pourcentage place l'élément positionné le long de l'axe, du début à la fin de l'ancrage sur l'axe spécifié. 0% se trouve du côté start de l'ancrage, et 100% se trouve du côté de l'extrémité de l'ancrage. center équivaut à 50%. Si vous utilisez un pourcentage sur un encart côté fin tel que bottom, il n'est pas inversé. 0% reste le côté start de l'ancrage.

Cet exemple montre comment une valeur de pourcentage va toujours du début à la fin sur l'axe spécifié :

Utiliser anchor()

Comme anchor() est une longueur, il est très flexible. Vous pouvez manipuler la valeur avec des fonctions CSS telles que max() et calc().

Une limite est que vous ne pouvez utiliser les fonctions anchor() que sur les propriétés d'encart.

L'exemple précédent ajoute un arrière-plan derrière le panneau de détails ouvert, qui s'anime en douceur lorsqu'un autre panneau est ouvert et s'étend pour inclure un panneau de détails sur lequel le curseur est placé. Pour ce faire, il utilise min() pour choisir la longueur la plus petite entre deux ancres.

#indicator{
/*  Use the smaller of the 2 values:  */
  inset-block-start: min(
/*   1. The start side of the default anchor, which is the open `<details>` element  */
    anchor(start),
/*   2. The start side of the hovered `<details>` element.    */
    anchor(--hovered start,
/*     If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used.   */
       var(calc(1px * infinity)))
  );
}

L'exemple utilise également calc() pour ajouter un espace intégré autour du panneau ouvert.

Utiliser la taille de l'ancrage

Vous pouvez également utiliser la fonction anchor-size() pour utiliser les dimensions de l'ancrage pour la taille, la position ou la marge de votre élément positionné.

anchor-size() accepte un nom d'ancrage ou utilise l'ancrage par défaut. Par défaut, il utilise la taille de l'ancrage sur l'axe sur lequel il est utilisé. Par conséquent, width: anchor-size() renvoie la largeur de l'ancrage. Vous pouvez également utiliser l'autre axe en spécifiant la longueur souhaitée, avec les mots clés physiques width et height ou les mots clés logiques block, inline, self-block et self-inline.

Gérer le dépassement

Vous avez créé un composant de menu déroulant et utilisé le positionnement d'ancrage pour le placer où vous le souhaitez. Mais ensuite, vous déplacez le menu de l'autre côté de l'écran ou vous l'utilisez pour un menu utilisateur, et le nom de l'utilisateur est très long. Soudain, votre menu déroulant disparaît de l'écran. Et maintenant ?

Le positionnement d'ancres CSS dispose d'un système intégré qui vous permet de créer rapidement un ensemble robuste de solutions de secours lorsque votre élément positionné se retrouve en dehors de son bloc de conteneur.

Options de remplacement

La règle position-try-fallbacks accepte une liste d'options de remplacement. Lorsque la position par défaut déborde, chaque option est essayée dans l'ordre jusqu'à ce qu'une position ne déborde pas.

Vous pouvez utiliser n'importe quelle valeur position-area comme option de remplacement. Dans cet exemple, dans les modes d'écriture de gauche à droite comme l'anglais, l'élément positionné tentera d'être positionné en bas de l'ancrage, en s'étendant sur les colonnes du centre et de droite. Si le contenu dépasse, il tentera de se positionner en bas de l'ancrage, en s'étendant sur les colonnes de gauche et du centre. Si le contenu déborde également, la position revient à la position par défaut, même si elle déborde.

.positioned-element {
  position-area: block-end span-inline-end;
  position-try-fallbacks: block-end span-inline-start;
}

Il existe également plusieurs mots clés flip- qui gèrent les cas de remplacement courants. flip-block et flip-inline essaient d'inverser l'élément sur les axes de bloc et en ligne. Ils peuvent également être combinés avec flip-block flip-inline pour inverser les deux axes. La valeur flip-start inverse l'élément positionné par rapport à une ligne diagonale allant des coins de début à ceux de fin de l'ancrage.

Vous pouvez également créer une option de secours personnalisée avec @position-try. Cela vous permet de définir les marges et l'alignement, et même de modifier l'ancrage.

@position-try --menu-below {
  position-area: bottom span-right;
  margin-top: 1em;
}

#positioned-element {
  position-try: --menu-below;
}

flip-block et flip-inline peuvent être ajoutés aux options de remplacement @position-try pour créer une variante.

#positioned-element {
  position-try: --menu-below, flip-inline --menu-below;
}

Dans l'exemple précédent, le navigateur suit ces étapes et s'arrête dès qu'il trouve une solution qui ne provoque pas de dépassement.

  1. L'élément est placé avec position-area: end, en bas à droite de l'ancrage.
  2. Si le contenu dépasse la taille de l'élément, celui-ci est placé avec l'option de remplacement personnalisée nommée --bottom-span-right, qui le place avec position-area: bottom span-right, avec une marge supplémentaire en dessous.
  3. Si le contenu dépasse la taille de l'élément, celui-ci est placé avec flip-inline --bottom-span-right, qui combine l'option de remplacement personnalisée avec flip-inline, qui est essentiellement position-area: bottom span-left.
  4. Si le contenu dépasse la limite, l'élément est placé à l'aide de l'option de remplacement personnalisée --use-alternate, qui le place sous une ancre complètement différente.
  5. Si le contenu déborde, l'élément revient à son emplacement d'origine, avec position-area: end, même si l'on sait que le contenu déborde.

Ordre de remplacement

Par défaut, lorsque la position initiale déborde, le navigateur essaie chaque option de position-try-fallbacks jusqu'à ce qu'il trouve une position qui ne déborde pas. Vous pouvez ignorer ce comportement avec position-try-order pour tester chaque option de remplacement et utiliser celle qui offre le plus d'espace sur un axe spécifié.

Vous pouvez spécifier l'axe à l'aide des mots clés logiques most-block-size et most-inline-size, ou des mots clés physiques most-height et most-width.

position-try-order et position-try-fallbacks peuvent être combinés avec le raccourci position-try, en commençant par l'ordre.

Défilement

Lorsqu'un utilisateur fait défiler une page, il s'attend à ce qu'elle se déplace de manière fluide. Pour ce faire, les navigateurs limitent l'utilisation du positionnement d'ancrage lors du défilement.

Bien que vous puissiez associer un élément positionné à des ancres dans différents conteneurs de défilement, l'élément ne se déplacera qu'en réponse au défilement de l'une des ancres. Il s'agit de l'ancrage par défaut, qui est soit l'ancrage implicite d'un pop-over, soit la valeur de position-anchor.

Vous remarquerez que l'élément positionné reste visible même lorsque l'ancrage n'est plus visible. Pour masquer l'élément positionné lorsque l'ancrage est masqué, définissez position-visibility: anchors-visible. Cela s'applique non seulement lorsque l'ancrage est défilé au-delà de la limite, mais aussi s'il est masqué d'une autre manière, par exemple avec visibility: hidden.

Vérifier que vous avez bien compris

Quelles sont les valeurs valides pour le côté dans anchor() ?

inside
Bonne réponse !
25%
Bonne réponse !
25px
Pas tout à fait. Bien qu'une longueur telle que 25px puisse être utilisée comme valeur de remplacement, seuls les pourcentages peuvent être utilisés pour le côté.
block-start
Incorrect
start
Bonne réponse !

Quelles sont les valeurs valides pour position-area ?

top
Bonne réponse !
block-end inline-end
Bonne réponse !
block-start block-end
Pas tout à fait. Vous ne pouvez définir qu'une seule colonne ou ligne sur chaque axe.

Quelles propriétés sont compatibles avec la fonction anchor() ?

top
Bonne réponse !
margin-left
Pas tout à fait.
inset-block-start
Bonne réponse !
transform
Pas tout à fait.

Que se passe-t-il si plusieurs ancres ont le même anchor-name ?

L'élément positionné est dupliqué et rattaché à chaque correspondance.
Pas tout à fait.
L'élément positionné est rattaché au premier élément du document.
Pas tout à fait.
L'élément positionné est rattaché au dernier élément du document.
Bonne réponse !
L'élément positionné est rattaché à l'ancrage le plus proche.
Pas tout à fait.