CSS Anchor Positioning & Popover API : Plus de JS pour les Popups en 2026
CSS Anchor Positioning : La « Proclamation d'Émancipation » pour les Développeurs Frontend
Chaque développeur frontend a connu cette douleur : utiliser JS pour calculer les positions de Tooltip, gérer le débordement des limites, écouter les événements scroll et resize... Maintenant, CSS peut gérer tout cela nativement.
Rétrospective historique : en 2016 nous utilisions Popper.js, en 2020 Floating UI, et en 2026 nous avons enfin le positionnement d'ancrage CSS natif. Après 10 ans, le positionnement des popups n'est plus un travail pour JS.
Évolution du Positionnement JS au Positionnement CSS
2016 jQuery offset() + calcul manuel
Recalcul à chaque scroll/resize
2020 Floating UI / Popper.js
Auto-flip, offset, détection des limites
Mais nécessite toujours init et destroy en JS
2024 CSS Anchor Positioning (Chrome 125+)
Positionnement déclaratif CSS pur
Le navigateur gère les limites et le défilement nativement
2026 Anchor Positioning + Popover API
Popups CSS pur : toggle sans JS, positionnement sans JS
Solution déclarative complète de popups
anchor-name et position-anchor
Utilisation de Base
<div class="card">
<button class="trigger">Plus d'Actions</button>
<div class="dropdown">Contenu du menu déroulant</div>
</div>
.trigger {
anchor-name: --my-anchor;
}
.dropdown {
position: fixed;
position-anchor: --my-anchor;
top: anchor(bottom);
left: anchor(left);
}
Référence de la Fonction anchor()
.tooltip {
position: fixed;
position-anchor: --trigger-anchor;
/* Relatif aux bords de l'ancre */
top: anchor(bottom);
bottom: anchor(top);
left: anchor(left);
right: anchor(right);
/* Points centraux de l'ancre */
left: anchor(50%);
top: anchor(50%);
/* Avec décalage */
top: calc(anchor(bottom) + 8px);
left: calc(anchor(left) - 4px);
}
position-area : Positionnement en Grille de Neuf Cases
Syntaxe de Neuf Cases
┌─────────────┬─────────────┬─────────────┐
│ top left │ top center│ top right │
│ │ │ │
├─────────────┼─────────────┼─────────────┤
│ center left │ center │ center right│
│ │ │ │
├─────────────┼─────────────┼─────────────┤
│ bottom left │bottom center│ bottom right│
│ │ │ │
└─────────────┴─────────────┴─────────────┘
.tooltip-below {
position-area: bottom center;
}
.tooltip-right {
position-area: center right;
}
.dropdown-below-left {
position-area: bottom left;
}
position-fallback et Stratégie de Fallback Multiniveau
Auto-Flip lors du Débordement des Limites
.dropdown {
position: fixed;
position-anchor: --trigger;
/* Préféré : sous l'ancre */
top: anchor(bottom);
left: anchor(left);
position-fallback: --dropdown-fallback;
}
@position-fallback --dropdown-fallback {
/* Fallback 1 : au-dessus de l'ancre */
@try {
bottom: anchor(top);
left: anchor(left);
}
/* Fallback 2 : sous l'ancre, aligné à droite */
@try {
top: anchor(bottom);
right: anchor(right);
}
/* Fallback 3 : au-dessus de l'ancre, aligné à droite */
@try {
bottom: anchor(top);
right: anchor(right);
}
}
Popover API : Couche de Popover Native
Utilisation de Base
<button popovertarget="my-popover">Ouvrir le Popover</button>
<div id="my-popover" popover>
<p>Ceci est du contenu de Popover natif</p>
<button popovertarget="my-popover" popovertargetaction="hide">Fermer</button>
</div>
[popover] {
position: fixed;
inset: unset;
margin: 0;
padding: 16px;
border: 1px solid #e5e7eb;
border-radius: 8px;
background: white;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}
Combinaison Popover + Anchor
<button class="menu-trigger" popovertarget="menu-popover">Menu</button>
<div id="menu-popover" popover class="menu-dropdown">
<a href="/profile">Profil</a>
<a href="/settings">Paramètres</a>
<a href="/logout">Déconnexion</a>
</div>
.menu-trigger {
anchor-name: --menu-anchor;
}
.menu-dropdown {
position-anchor: --menu-anchor;
position-area: bottom left;
margin: 4px;
}
anchor-size() : Auto-Dimensionnement Basé sur l'Élément d'Ancrage
.trigger {
anchor-name: --select-anchor;
}
.select-dropdown {
position: fixed;
position-anchor: --select-anchor;
top: anchor(bottom);
left: anchor(left);
/* La largeur du menu déroulant suit le bouton déclencheur */
width: anchor-size(width);
/* Ou définir une largeur minimale */
min-width: anchor-size(width);
}
Pratique : Composants UI Courants en CSS Pur
Tooltip
<span class="tooltip-trigger" tabindex="0">
Aide
<span class="tooltip-content" role="tooltip">Ceci est un tooltip d'aide</span>
</span>
.tooltip-trigger {
anchor-name: --tt-anchor;
position: relative;
cursor: help;
text-decoration: underline dotted;
}
.tooltip-content {
position: fixed;
position-anchor: --tt-anchor;
position-area: top center;
margin: 8px;
padding: 6px 10px;
background: #1f2937;
color: white;
border-radius: 4px;
font-size: 13px;
white-space: nowrap;
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
position-fallback: --tt-fallback;
}
.tooltip-trigger:hover .tooltip-content,
.tooltip-trigger:focus .tooltip-content {
opacity: 1;
}
@position-fallback --tt-fallback {
@try { position-area: bottom center; }
@try { position-area: center right; }
@try { position-area: center left; }
}
Menu Déroulant
<button class="dropdown-trigger" popovertarget="dd-menu">
Options ▾
</button>
<div id="dd-menu" popover class="dropdown-menu">
<button class="dropdown-item">Modifier</button>
<button class="dropdown-item">Copier</button>
<button class="dropdown-item">Supprimer</button>
</div>
.dropdown-trigger {
anchor-name: --dd-anchor;
}
.dropdown-menu {
position-anchor: --dd-anchor;
position-area: bottom left;
margin: 4px;
width: anchor-size(width);
min-width: 160px;
padding: 4px;
border-radius: 8px;
background: white;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
position-fallback: --dd-fallback;
}
.dropdown-item {
display: block;
width: 100%;
padding: 8px 12px;
border: none;
background: none;
text-align: left;
border-radius: 4px;
cursor: pointer;
}
.dropdown-item:hover {
background: #f3f4f6;
}
@position-fallback --dd-fallback {
@try { position-area: top left; }
}
Comparaison avec Floating UI/Popper.js
| Dimension | CSS Anchor + Popover | Floating UI |
|---|---|---|
| Dépendance JS | Zéro JS | 12Ko gzip |
| Performance | Natif navigateur | Calcul JS |
| Déclaratif | CSS déclaratif | JS impératif |
| Flip de limites | position-fallback | middleware flip() |
| Décalage | margin/anchor() | middleware offset() |
| Flèche | Pseudo-élément CSS | Élément SVG/HTML |
| Éléments virtuels | Non supporté | Supporté |
| Contenu dynamique | Auto-suivi | Nécessite update() |
| Support navigateurs | Chrome 125+ | Tous les navigateurs |
| Compatible SSR | Pleinement compatible | Nécessite JS client |
Quand Vous Avez Encore Besoin de Bibliothèques JS
Scénarios nécessitant encore Floating UI :
1. Besoin de supporter les anciens navigateurs (Safari < 17.5, Firefox < 131)
2. Besoin de positionnement d'éléments virtuels (suivi du curseur)
3. Besoin de chaînes de middleware complexes (autoUpdate, size, hide)
4. Exigences de wrapper déclaratif pour React/Vue
Scénarios où CSS Anchor fonctionne :
1. Tooltip, Dropdown, Popover et autres popups standards
2. Seulement besoin de supporter les navigateurs modernes
3. Poursuivre zéro dépendance JS
4. Scénarios sensibles aux performances
Compatibilité des Navigateurs et Polyfill
État du Support
| Navigateur | Anchor Positioning | Popover API |
|---|---|---|
| Chrome 125+ | ✅ | ✅ |
| Edge 125+ | ✅ | ✅ |
| Safari 17.5+ | ✅ | ✅ |
| Firefox 131+ | ✅ | ✅ |
| iOS Safari 17.5+ | ✅ | ✅ |
Solutions Polyfill
<script src="https://cdn.jsdelivr.net/npm/@oddbird/css-anchor-positioning@0.3.0/dist/css-anchor-positioning.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@oddbird/popover-polyfill@0.4.0/dist/popover.min.js"></script>
Combinaison avec @starting-style pour les Animations de Popup
[popover] {
opacity: 0;
transform: translateY(-8px) scale(0.95);
transition: opacity 0.2s, transform 0.2s, display 0.2s allow-discrete;
overlay: none;
}
[popover]:popover-open {
opacity: 1;
transform: translateY(0) scale(1);
overlay: auto;
}
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: translateY(-8px) scale(0.95);
}
}
Résumé
- CSS Anchor Positioning est la solution ultime pour le positionnement de popups — Zéro JS, déclaratif, natif du navigateur
- La Popover API rend le toggle de popups également sans JS — l'attribut popovertarget gère tout en une ligne
- position-fallback résout le débordement des limites — Plus de calculs JS pour le flip
- Tous les navigateurs majeurs le supportent en 2026 — Sûr pour la production
Après 10 ans, le positionnement des popups est enfin revenu là où il appartient : le CSS. Ce n'est pas une amélioration incrémentale — c'est un changement de paradigme, tout comme Flexbox a remplacé les mises en page en float.
Essayez ces outils exécutés localement dans le navigateur — aucune inscription requise →