Compatibilité
A l’heure actuelle, le module Anchor positioning n’est pas encore supporté par tous les navigateurs. N’hésitez pas à consulter la compatibilité sur Caniuse.
Publié le :
Nouveau module CSS de positionnement d’ancrage qui permet d’attacher des éléments d’ensemble à des éléments d’ancrage. On peut alors définir la taille et la position en fonction de la taille et de l’emplacement de l’élément d’ancrage.
De plus, on peut spécifier un ensemble de positions alternatives dès lors que l’élément ancré déborde du bloc conteneur ou de l’écran. Cela permet au navigateur de toujours l’afficher de manière optimale.
Avant tout cela n’était pas possible sans JavaScript.
A l’heure actuelle, le module Anchor positioning n’est pas encore supporté par tous les navigateurs. N’hésitez pas à consulter la compatibilité sur Caniuse.
Voici quelques exemples de cas d’usage courant pour le module Anchor positioning :
Pour associer un élément d’ensemble à un élément d’ancrage, on utilise la propriété anchor-name, le nom doit être préfixé par 2 tirets comme pour les variables CSS .
.anchor {
anchor-name: --myAnchor;
width: fit-content;
}
Ensuite, nous devons convertir notre élément à positionner par ancrage.
Tout d’abord en lui donnant une position absolue ou fixe, puis il faut lui appliquer la référence de l’ancre avec la propriété position-anchor.
.anchor-positioned {
position: absolute;
position-anchor: --myAnchor;
}
Vous pouvez tester sur le lien de ce Codepen .
<button class="small anchor" type="button" >
<svg
aria-label="hidden"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
viewBox="0 0 24 24"
width="24"
height="24"
>
<path
fill="currentColor"
d="M10.6 7.6c-1.6.8-3 2.1-4.4 4-.2.3-.2.4 0 .6.1.1.2.1.4-.2l.1-.1c.2-.2.3-.4.6-.7 1-1.2 1.5-1.7 2.3-2.1.7-.4 1.3.2 1.1.9 0 .2-.1.4-.2.7-.1.1-.1.2-.1.3-.3.7-.5 1.2-.9 2.4v.1c-.1.3-.1.3-.3.7-.6 1.5-.9 2.4-1.3 3.4v.1c-.1.3-.1.4-.2.5-.4 1.1-.7 1.9-.8 2.6 0 .1 0 .1-.1.2-.1.4-.2.7-.2 1-.1.5 0 .9.1 1.3.2.4.6.7 1 .7.7.1 1.4.1 2.1 0l1-.3c1-.4 1.9-.9 2.8-1.7.8-.7 1.5-1.5 2.3-2.4.1-.1.1-.1.1-.2.2-.3.4-.5.4-.7 0-.2-.1-.4-.3-.4-.1 0-.2.1-.3.3-.1.1-.1.2-.2.2l-.6.6c-.3.4-.7.7-1.2 1.3-.3.3-.6.5-.9.7-.6.3-1.1-.1-1-.7 0-.4.1-.8.3-1.3.3-.9.6-1.6 1.2-3.2.3-.7.4-1 .5-1.4.4-1.1.7-2 1.1-2.9.4-1.1.6-1.9.7-2.7.1-.6-.1-1.2-.5-1.6-.4-.5-1.1-.7-1.8-.7-.8 0-1.8.2-2.8.7zM16.5.2c-1.5-.6-3.4.4-3.7 2.1-.2 1.2.2 2.2 1.1 2.6 1.8.8 3.9-.5 3.9-2.5.1-1.1-.4-1.9-1.3-2.2z"
></path>
</svg>
</button>
<div>
<span>Contenu positionné sur l'ancre</span>
</div> button {
anchor-name: --myAnchor;
}
button + div {
position: fixed;
position-anchor: --myAnchor;
padding: 1rem;
top: anchor(bottom);
left: anchor(50%);
background: var(--bl5);
} Il existe également un attribut anchor ( voir la doc ) qui permet de définir un élément d’ancrage pour un élément d’ensemble.
Mais attention, l’attribut anchor est encore expérimental et n’est pas encore supporté par tous les navigateurs. A ce jour, seul Chrome Canary le supporte.
<div class="anchor" id="example-anchor">⚓︎</div>
<div class="infobox" anchor="example-anchor">
<p>This is an information box.</p>
</div> Maintenant que nous avons lié nos éléments, nous avons besoin de gérer le positionnement par rapport à l’élément d’ancrage. Pour cela, il existe plusieurs manières de le faire :
anchor() ( voir la doc )justify-*)L’élément d’ancrage doit être visible dans le DOM (pas de display:none;)
sinon l’élément sera positionné par rapport à son ancêtre le plus
proche. Il est possible de gérer ce genre de cas avec du masquage conditionnel
et la propriété position-visibility
Comme nous l’avons précisé plus haut, l’élément ancré doit être en position absolue ou fixe. Normalement, ces positions sont censées se référer à la fenêtre.
Mais le système des ancres changent ce comportement pour se référer à l’élément d’ancrage.
La fonction anchor() va nous permettre de définir la position de l’élément ancré par rapport à l’élément d’ancrage.
anchor(<anchor-element> <anchor-side>, <length-percentage>)
La fonction anchor() renvoie une valeur de longueur, on peut donc utiliser
des fonctions de calculs comme calc() ou clamp() .
Parmi les valeurs courantes, on retrouve :
top, bottom, left, right pour les côtés de l’élémentcenter pour le centre de l’élémentEnsuite, les valeurs logiques selon l’axe de la propriété inset et le sens de lecture (writing-mode):
start, end pour les côtés en fonction du sens de lectureself-start, self-end pour laisser le navigateur gérer la position
Les exemples précédents utilisent une ancre implicite (on ne précise pas de nom) car on part du principe qu’il n’y aura qu’une ancre associée. Comme dans cet exemple :
.anchored {
/* top de l'élément ancré et bottom de l'ancre */
top: anchor(bottom);
/* left de l'élément ancré et 50% de l'ancre */
left: anchor(50%);
}
On peut aussi définir explicitement le nom de l’ancre soit par souci de maintenabilité soit pour gérer plusieurs ancres.
.anchored {
position: absolute;
top: anchor(--one bottom);
left: anchor(--one right);
right: anchor(--two left);
bottom: anchor(--two top);
}
Dans cet exemple, nous avons 2 ancres sur lesquelles nous positionnons notre élément. Les ancres étant en absolue et positionnées dans les coins de l’écran, si on redimentionne la fenêtre, l’élément ancré va s’étirer car il est tenu par les 2 ancres à la fois.
La fonction anchor() prévoit une valeur de fallback si l’élément d’ancrage n’est pas trouvé.
.anchored {
top: anchor(bottom, 50%);
}
On peut centrer un élément ancré sur lui-même avec la propriété justify-self et la valeur anchor-center.
En plus du positionnement directionnel par défaut issu du positionnement absolu, il existe un nouveau mécanisme de mise en page inclus
dans l’API d’ancrage, appelé zone d’encart.
La zone d’encart facilite le positionnement des éléments positionnés par rapport à leurs ancrages respectifs et fonctionne sur une grille à neuf cellules avec l’élément d’ancrage au centre.
La propriété à utiliser est inset-area qui peut prendre les valeurs suivantes :
Il existe une démo qui illustre parfaitement le concept de zone d’encart.
L’API de positionnement d’ancre permet également de définir la taille d’un élément ancré en fonction de la taille de son ancre avec la fonction anchor-size().
Une fois que l’on a défini la position de l’ancre, il est possible d’ajuster son comportement en fonction de sa proximité avec les bords du conteneur. En effet, il est primordial de s’assurer que les éléments ancrés s’affichent toujours de manière optimale pour l’utilisateur. Il sera même parfois préférable de masquer l’élément ancré si celui-ci déborde du conteneur et que son affichage n’a plus de sens.
Il existe des modes de basculement déjà prédéfinis pour les navigateurs, dans ce cas, il n’est pas utile de créer des déclarations de @position-try mais juste d’utiliser les bons mots-clés.
Ces valeurs inversent la position sur un ou deux axes si l’élement ancré déborde du conteneur.
flip-block : inverse la position sur l’axe blockflip-inline : inverse la position sur l’axe inlineflip-block flip-inline : inverse la position sur les 2 axes.anchor-positioned {
position-try-fallbacks: flip-block, flip-inline;
}
On peut donc spécifier plusieurs valeurs de secours, elles doivent séparées par des virgules et elles seront appliquées dans l’ordre.
Cette méthode est plus précise et permet de gérer les débordements de manière plus fine.
.anchor-positioned {
position: fixed;
position-anchor: --myAnchor;
inset-area: top left;
position-try-fallbacks:
top,
top right,
right,
bottom right,
bottom,
bottom left,
left;
}
On peut aller encore plus loin en définissant des fallbacks personnalisés.
Un peu comme on le ferait avec des media queries, on va utiliser la règle @position-try et la propriété position-try-fallbacks.
Cette fonctionnalité étant expérimentale, elle est sujette aux changements,
par exemple position-try-options a été renommée position-try-fallbacks.
Si vous souhaitez appliquer des transitions sur les basculements, vous devrez
obligatoirement utiliser les positionnements avec anchor() car à l’heure
actuelle, il n’est pas possible de le faire sur la propriété inset-area.
Cette propriété sert principalement à indiquer au navigateur quel fallback utiliser en fonction de ce que l’on souhaite dès l’affichage de l’élément ancré.
Par exemple, si l’on souhaite que l’élément ancré soit toujours visible, on peut utiliser la valeur most-height pour prioriser les positions qui maximisent la hauteur de l’élément ancré.
.anchor-positioned {
position-try-order: most-height;
}
Voici les valeurs possibles :
La plupart du temps lorsque l’affichage de l’élément ancré pose problème, on cherchera à adapter la position en fonction de l’espace disponible
comme on l’a vu avec @position-try.
Toutefois, dans certaines situations, on aimerait pouvoir masquer cet élément, par exemple dans un conteneur dans lequel on aurait un défilement
et qui contiendrait une tooltip d’information.
On peut le gérer avec le propriété position-visibility ( Voir la doc ) qui possède 3 valeurs :
Comme préciser au début de cet article, le module Anchor positioning n’est pas encore supporté par tous les navigateurs.
Vous pouvez détecter la compatibilité avec la règle @support et proposer une alternative.
@supports (anchor-name: --myanchor) {
/* Anchor styles here */
}
Il existe un polyfill pour les anciens navigateurs.
L’API ne définit pas nativement de relation sémantique entre l’élément d’ancrage et l’élément positionné. Toutefois, vous pouvez ajouter un attribut aria-details pour améliorer l’accessibilité.
<button class="anchor" aria-details="more-info">Get more info</div>
<div class="positioned" id="more-info">More info content</div>
Il ne sera pas nécessaire de le faire si vous utilisez le positionnement de l’ancrage avec l’attribut popover ou avec l’élément <dialog> car l’accessibilité est bien gérée.
En conclusion, le module Anchor positioning est une nouvelle fonctionnalité CSS qui permet de gérer le positionnement d’un élément par ancrage à un autre élément. Il offre une grande flexibilité pour le positionnement des éléments et permet de gérer des cas d’usage qui étaient jusqu’à présent réservés à JavaScript.
Tous les articles de CSS