L'objectif de l'initiative Open UI est de permettre aux développeurs de créer plus facilement des expériences utilisateur de qualité. Pour ce faire, nous essayons de résoudre les problèmes les plus courants rencontrés par les développeurs. Pour ce faire, nous pouvons fournir de meilleurs composants et API intégrés à la plate-forme.
Les pop-ups, décrits dans Open UI comme des "popovers", constituent l'un de ces domaines problématiques.
Les pop-overs ont longtemps eu une réputation plutôt polarisée. Cela est en partie dû à la façon dont ils sont créés et déployés. Il n'est pas facile de créer un bon carrousel, mais il peut être très utile pour diriger les utilisateurs vers certains éléments ou leur faire découvrir le contenu de votre site, surtout s'il est utilisé avec goût.
Lorsque vous créez des pop-overs, vous devez souvent tenir compte de deux problèmes majeurs :
- Comment s'assurer qu'il est placé au-dessus du reste de votre contenu, à un emplacement approprié
- Comment le rendre accessible (compatible avec le clavier, sélectionnable, etc.)
L'API Popover intégrée a plusieurs objectifs, tous visant à permettre aux développeurs de créer facilement ce modèle. Voici quelques-uns de ces objectifs :
- Facilitez l'affichage d'un élément et de ses descendants au-dessus du reste du document.
- Rendez-le accessible.
- Ne pas nécessiter JavaScript pour les comportements les plus courants (fermeture légère, singleton, empilement, etc.).
Vous pouvez consulter la spécification complète des pop-ups sur le site OpenUI.
Compatibilité du navigateur
Où pouvez-vous utiliser l'API Popover intégrée maintenant ? Au moment de la rédaction de cet article, elle est compatible avec Chrome Canary derrière le commutateur "Experimental Web Platform features".
Pour activer ce flag, ouvrez Chrome Canary et accédez à chrome://flags. Activez ensuite le commutateur "Experimental Web Platform features".
Un test d'origine est également disponible pour les développeurs qui souhaitent tester cette fonctionnalité dans un environnement de production.
Enfin, un polyfill est en cours de développement pour l'API. N'oubliez pas de consulter le dépôt sur github.com/oddbird/popup-polyfill.
Pour vérifier si les pop-ups sont acceptés :
const supported = HTMLElement.prototype.hasOwnProperty("popover");
Solutions actuelles
Que pouvez-vous faire actuellement pour promouvoir votre contenu avant tout ? Si votre navigateur est compatible, vous pouvez utiliser l'élément HTML Dialog. Vous devez l'utiliser dans le formulaire "Modal". Pour l'utiliser, vous devez activer JavaScript.
Dialog.showModal();
Il existe des considérations d'accessibilité. Il est conseillé d'utiliser a11y-dialog, par exemple, si vous vous adressez aux utilisateurs de Safari dont la version est antérieure à 15.4.
Vous pouvez également utiliser l'une des nombreuses bibliothèques de pop-ups, d'alertes ou d'info-bulles disponibles. La plupart d'entre eux fonctionnent de manière similaire.
- Ajoutez un conteneur au corps pour afficher les pop-ups.
- Stylisez-le pour qu'il se trouve au-dessus de tout le reste.
- Créez un élément et ajoutez-le au conteneur pour afficher un pop-up.
- Masquez-le en supprimant l'élément popover du DOM.
Cela nécessite une dépendance supplémentaire et davantage de décisions pour les développeurs. Vous devrez également faire des recherches pour trouver une offre qui répond à tous vos besoins. L'API Popover vise à répondre à de nombreux scénarios, y compris les info-bulles. L'objectif est de couvrir tous ces scénarios courants, ce qui évite aux développeurs d'avoir à prendre une décision supplémentaire et leur permet de se concentrer sur la création de leurs expériences.
Votre premier pop-up
C'est tout ce dont vous avez besoin.
<div id="my-first-popover" popover>Popover Content!</div>
<button popovertoggletarget="my-first-popover">Toggle Popover</button>
Mais que se passe-t-il ici ?
- Vous n'avez pas besoin de placer l'élément popover dans un conteneur ou quoi que ce soit d'autre, car il est masqué par défaut.
- Vous n'avez pas besoin d'écrire de code JavaScript pour qu'il s'affiche. C'est l'attribut
popovertoggletargetqui s'en charge. - Lorsqu'il apparaît, il est promu au premier plan. Cela signifie qu'il est promu au-dessus de
documentdans la fenêtre d'affichage. Vous n'avez pas à gérerz-indexni à vous soucier de l'emplacement de votre pop-up dans le DOM. Il peut être profondément imbriqué dans le DOM, avec des ancêtres de clipping. Vous pouvez également voir quels éléments se trouvent actuellement au premier plan à l'aide des outils de développement. Pour en savoir plus sur la couche supérieure, consultez cet article.

- Vous bénéficiez de la fermeture légère prête à l'emploi. En d'autres termes, vous pouvez fermer le popover avec un signal de fermeture, par exemple en cliquant en dehors du popover, en naviguant au clavier vers un autre élément ou en appuyant sur la touche Esc. Rouvrez-le et essayez-le !
Quels sont les autres avantages des pop-overs ? Prenons un autre exemple. Prenons l'exemple de cette démo avec du contenu sur la page.
Ce bouton d'action flottant a un positionnement fixe avec un z-index élevé.
.fab {
position: fixed;
z-index: 99999;
}
Le contenu du popover est imbriqué dans le DOM, mais lorsque vous ouvrez le popover, il est placé au-dessus de l'élément à position fixe. Vous n'avez pas besoin de définir de styles.
Vous remarquerez peut-être également que le pop-over comporte désormais un pseudo-élément ::backdrop. Tous les éléments de la couche supérieure obtiennent un pseudo-élément ::backdrop stylable. Cet exemple applique un style à ::backdrop avec une couleur d'arrière-plan à canal alpha réduit et un filtre d'arrière-plan qui floute le contenu sous-jacent.
Mettre en forme un pop-over
Passons maintenant à la mise en forme du pop-over. Par défaut, un pop-over a une position fixe et une marge intérieure appliquée. Il comporte également display: none. Vous pouvez remplacer cette valeur pour afficher un pop-over. Mais cela ne le ferait pas passer au premier plan.
[popover] { display: block; }
Quelle que soit la façon dont vous promouvez votre popover, une fois que vous l'avez promu au premier plan, vous devrez peut-être le mettre en page ou le positionner. Vous ne pouvez pas cibler le calque supérieur et effectuer une action telle que
:open {
display: grid;
place-items: center;
}
Par défaut, un popover est mis en page au centre de la fenêtre d'affichage à l'aide de margin: auto. Toutefois, dans certains cas, vous pouvez vouloir être explicite sur le positionnement. Exemple :
[popover] {
top: 50%;
left: 50%;
translate: -50%;
}
Si vous souhaitez organiser le contenu de votre pop-up à l'aide de la grille CSS ou de flexbox, il peut être judicieux de l'encapsuler dans un élément. Sinon, vous devrez déclarer une règle distincte qui modifie display une fois le pop-over dans le calque supérieur. Si vous le définissez par défaut, il s'affichera par défaut et remplacera display: none.
[popover]:open {
display: flex;
}
Si vous avez essayé cette démo, vous remarquerez que le pop-up s'affiche et disparaît désormais. Vous pouvez faire apparaître et disparaître les popovers à l'aide du pseudo-sélecteur :open. Le pseudo-sélecteur :open correspond aux popovers qui sont affichés (et donc dans le calque supérieur).
Cet exemple utilise une propriété personnalisée pour déclencher la transition. Vous pouvez également appliquer une transition à l'élément ::backdrop du pop-over.
[popover] {
--hide: 1;
transition: transform 0.2s;
transform: translateY(calc(var(--hide) * -100vh))
scale(calc(1 - var(--hide)));
}
[popover]::backdrop {
transition: opacity 0.2s;
opacity: calc(1 - var(--hide, 1));
}
[popover]:open::backdrop {
--hide: 0;
}
Un conseil : regroupez les transitions et les animations sous une requête média pour le mouvement. Cela peut également vous aider à respecter vos délais. En effet, vous ne pouvez pas partager de valeurs entre popover et ::backdrop via une propriété personnalisée.
@media(prefers-reduced-motion: no-preference) {
[popover] { transition: transform 0.2s; }
[popover]::backdrop { transition: opacity 0.2s; }
}
Jusqu'à présent, vous avez vu comment utiliser popovertoggletarget pour afficher un pop-over. Pour la fermer, nous utilisons la méthode "Light dismiss". Toutefois, vous pouvez également utiliser les attributs popovershowtarget et popoverhidetarget. Ajoutons un bouton à un popover pour le masquer et modifions le bouton bascule pour utiliser popovershowtarget.
<div id="code-popover" popover>
<button popoverhidetarget="code-popover">Hide Code</button>
</div>
<button popovershowtarget="code-popover">Reveal Code</button>
Comme indiqué précédemment, l'API Popover couvre plus que notre notion historique de pop-ups. Vous pouvez créer des applications pour tous les types de scénarios, tels que les notifications, les menus, les info-bulles, etc.
Certains de ces scénarios nécessitent des schémas d'interaction différents. Interactions telles que le pointage. L'utilisation d'un attribut popoverhovertarget a été testée, mais n'est pas actuellement implémentée.
<div popoverhovertarget="hover-popover">Hover for Code</div>
L'idée est de pointer sur un élément pour afficher la cible. Ce comportement peut être configuré à l'aide de propriétés CSS. Ces propriétés CSS définiraient la durée pendant laquelle un pop-over réagit au survol et à l'arrêt du survol d'un élément. Le comportement par défaut testé consistait à afficher un pop-over après un 0.5s explicite de :hover. Il aurait ensuite besoin d'une fermeture légère ou de l'ouverture d'un autre popover pour se fermer (nous y reviendrons). Cela était dû à la durée de masquage du pop-over, qui était définie sur Infinity.
En attendant, vous pouvez utiliser JavaScript pour combler cette fonctionnalité.
let hoverTimer;
const HOVER_TRIGGERS = document.querySelectorAll("[popoverhovertarget]");
const tearDown = () => {
if (hoverTimer) clearTimeout(hoverTimer);
};
HOVER_TRIGGERS.forEach((trigger) => {
const popover = document.querySelector(
`#${trigger.getAttribute("popoverhovertarget")}`
);
trigger.addEventListener("pointerenter", () => {
hoverTimer = setTimeout(() => {
if (!popover.matches(":open")) popover.showPopover();
}, 500);
trigger.addEventListener("pointerleave", tearDown);
});
});
L'avantage de définir une fenêtre de survol explicite est de s'assurer que l'action de l'utilisateur est intentionnelle (par exemple, un utilisateur passe son pointeur sur une cible). Nous ne voulons pas afficher le pop-up à moins que ce soit leur intention.
Essayez cette démo où vous pouvez pointer la cible avec la fenêtre définie sur 0.5s.
Avant d'examiner quelques cas d'utilisation et exemples courants, passons en revue quelques points.
Types de pop-ups
Nous avons abordé le comportement d'interaction non JavaScript. Mais qu'en est-il du comportement des popovers dans leur ensemble ? Que faire si vous ne voulez pas de la fermeture légère ? Ou vous souhaitez appliquer un modèle singleton à vos pop-ups ?
L'API Popover vous permet de spécifier trois types de pop-ups qui se distinguent par leur comportement.
[popover=auto]/[popover] :
- Prise en charge de l'imbrication. Cela ne signifie pas seulement imbriqué dans le DOM. Un pop-over ancêtre est défini comme suit :
- associés par position DOM (enfant).
- associés par des attributs de déclenchement sur des éléments enfants tels que
popovertoggletarget,popovershowtarget, etc. - associés par l'attribut
anchor(API CSS Anchoring en cours de développement).
- Fermeture légère.
- L'ouverture ferme les autres pop-ups qui ne sont pas des pop-ups ancêtres. Testez la démo ci-dessous pour découvrir comment fonctionne l'imbrication avec les pop-ups ancêtres. Voyons comment les choses changent lorsque vous remplacez certaines instances
popoverhidetarget/popovershowtargetparpopovertoggletarget. - La fermeture légère d'une notification entraîne la fermeture de toutes les notifications, mais la fermeture d'une notification dans la pile n'entraîne la fermeture que de celles qui se trouvent au-dessus dans la pile.
[popover=manual] :
- Ne ferme pas les autres popovers.
- Pas de désactivation par la lumière.
- Nécessite une fermeture explicite via un élément de déclenchement ou JavaScript.
API JavaScript
Si vous avez besoin de mieux contrôler vos popovers, vous pouvez utiliser JavaScript. Vous obtenez à la fois une méthode showPopover et une méthode hidePopover. Vous pouvez également écouter les événements popovershow et popoverhide :
Afficher un pop-over
js
popoverElement.showPopover()
Masquer un pop-over :
popoverElement.hidePopover()
Écoutez si un popover est affiché :
popoverElement.addEventListener('popovershow', doSomethingWhenPopoverShows)
Écoutez l'affichage d'un pop-over et annulez-le :
popoverElement.addEventListener('popovershow',event => {
event.preventDefault();
console.warn(‘We blocked a popover from being shown’);
})
Écoutez si un pop-over est masqué :
popoverElement.addEventListener('popoverhide', doSomethingWhenPopoverHides)
Vous ne pouvez pas annuler la masquage d'un popover :
popoverElement.addEventListener('popoverhide',event => {
event.preventDefault();
console.warn("You aren't allowed to cancel the hiding of a popover");
})
Vérifiez si un pop-over se trouve dans le calque supérieur :
popoverElement.matches(':open')
Cela fournit une puissance supplémentaire pour certains scénarios moins courants. Par exemple, afficher un popover après une période d'inactivité.
Cette démo comporte des pop-ups avec des sons audibles. Nous aurons donc besoin de JavaScript pour lire l'audio. Lorsque l'utilisateur clique, nous masquons le pop-over, lisons l'audio, puis l'affichons à nouveau.
Accessibilité
L'accessibilité est au cœur de la conception de l'API Popover. Les mappages d'accessibilité associent le pop-over à son élément déclencheur, si nécessaire. Cela signifie que vous n'avez pas besoin de déclarer les attributs aria-* tels que aria-haspopup, à condition d'utiliser l'un des attributs de déclenchement comme popovertoggletarget.
Pour la gestion du focus, vous pouvez utiliser l'attribut autofocus pour déplacer le focus vers un élément à l'intérieur d'un popover. C'est la même chose que pour une boîte de dialogue, mais la différence se fait sentir lors du retour du focus, en raison de la fermeture légère. Dans la plupart des cas, la fermeture d'un popover replace le focus sur l'élément précédemment sélectionné. Toutefois, le focus est déplacé vers un élément sur lequel l'utilisateur a cliqué lors de la fermeture légère, s'il peut être sélectionné. Consultez la section sur la gestion de la mise au point dans l'explication.
Vous devrez ouvrir la version plein écran de cette démo pour la voir fonctionner.
Dans cette démo, l'élément sélectionné est entouré d'un contour vert. Essayez de parcourir l'interface avec votre clavier. Notez où la mise au point est renvoyée lorsqu'un pop-over est fermé. Vous avez peut-être aussi remarqué que le pop-over s'est fermé lorsque vous avez utilisé la touche de tabulation. C'est normal. Bien que les popovers gèrent la sélection, ils ne la piègent pas. La navigation au clavier identifie un signal de fermeture lorsque le focus quitte le pop-over.
Ancrage (en cours de développement)
En ce qui concerne les pop-ups, un modèle délicat à prendre en compte consiste à ancrer l'élément à son déclencheur. Par exemple, si une info-bulle est configurée pour s'afficher au-dessus de son déclencheur, mais que l'utilisateur fait défiler le document. Il est possible que l'info-bulle soit tronquée par la fenêtre d'affichage. Il existe des offres JavaScript actuelles pour y faire face, comme Floating UI. Ils repositionneront l'info-bulle pour vous éviter cela et s'appuieront sur l'ordre de position souhaité.
Cependant, nous souhaitons que vous puissiez le définir avec vos styles. Une API associée est en cours de développement en parallèle de l'API Popover pour résoudre ce problème. L'API CSS Anchor Positioning vous permettra d'ancrer des éléments à d'autres éléments, et ce, de manière à repositionner les éléments pour qu'ils ne soient pas coupés par la fenêtre d'affichage.
Cette démo utilise l'API Anchoring dans son état actuel. La position du bateau correspond à celle de l'ancrage dans la fenêtre d'affichage.
Voici un extrait du code CSS qui permet à cette démo de fonctionner. Aucun code JavaScript n'est requis.
.anchor {
--anchor-name: --anchor;
}
.anchored {
position: absolute;
position-fallback: --compass;
}
@position-fallback --compass {
@try {
bottom: anchor(--anchor top);
left: anchor(--anchor right);
}
@try {
top: anchor(--anchor bottom);
left: anchor(--anchor right);
}
}
Pour consulter les spécifications, cliquez ici. Un polyfill sera également disponible pour cette API.
Exemples
Maintenant que vous savez ce que les pop-ups ont à offrir et comment, examinons quelques exemples.
Notifications
Cette démo montre une notification "Copié dans le presse-papiers".
- Fuseau horaire :
[popover=manual]. - Afficher le pop-over d'action avec
showPopover. - Après un délai d'inactivité de
2000ms, masquez-le avechidePopover.
Notifications toast
Cette démo utilise la couche supérieure pour afficher des notifications de type toast.
- Un pop-over de type
manualsert de conteneur. - Les nouvelles notifications sont ajoutées au pop-over, qui s'affiche.
- Ils sont supprimés avec l'API Web Animations au clic et retirés du DOM.
- Si aucun toast n'est à afficher, le pop-over est masqué.
Menu imbriqué
Cette démo montre comment un menu de navigation imbriqué pourrait fonctionner.
- Utilisez
[popover=auto], car il autorise les popovers imbriqués. - Utilisez
autofocussur le premier lien de chaque menu déroulant pour naviguer au clavier. - C'est un candidat idéal pour l'API CSS Anchoring. Toutefois, pour cette démonstration, vous pouvez utiliser une petite quantité de JavaScript pour mettre à jour les positions à l'aide de propriétés personnalisées.
const ANCHOR = (anchor, anchored) => () => {
const { top, bottom, left, right } = anchor.getBoundingClientRect();
anchored.style.setProperty("--top", top);
anchored.style.setProperty("--right", right);
anchored.style.setProperty("--bottom", bottom);
anchored.style.setProperty("--left", left);
};
PRODUCTS_MENU.addEventListener("popovershow", ANCHOR(PRODUCT_TARGET, PRODUCTS_MENU));
N'oubliez pas que cette démo utilise autofocus. Vous devrez donc l'ouvrir en mode plein écran pour pouvoir naviguer au clavier.
Pop-over multimédia
Cette démo montre comment faire apparaître un élément multimédia.
- Utilise
[popover=auto]pour la fermeture légère. - JavaScript écoute l'événement
playde la vidéo et l'affiche. - L'événement
popoverhidedes pop-ups met la vidéo en pause.
Pop-ups de style wiki
Cette démo montre comment créer des info-bulles de contenu intégrées contenant des éléments multimédias.
- Fuseau horaire :
[popover=auto]. Si vous en affichez un, les autres sont masqués, car ils ne sont pas ancestraux. - Affiché sur
pointerenteravec JavaScript. - C'est un autre candidat idéal pour l'API CSS Anchoring.
Panneau de navigation
Cette démo crée un panneau de navigation à l'aide d'un pop-up.
- Utilise
[popover=auto]pour la fermeture légère. - Utilise
autofocuspour sélectionner le premier élément de navigation.
Gérer les arrière-plans
Cette démo montre comment gérer les arrière-plans de plusieurs pop-ups lorsque vous ne souhaitez qu'un seul ::backdrop visible.
- Utilisez JavaScript pour tenir à jour une liste des pop-overs visibles.
- Appliquez un nom de classe au pop-over le plus bas de la couche supérieure.
Pop-up de curseur personnalisé
Cette démo montre comment utiliser popover pour promouvoir un canvas au premier plan et l'utiliser pour afficher un curseur personnalisé.
- Mettez en avant
canvasau premier plan avecshowPopoveret[popover=manual]. - Lorsque d'autres popovers sont ouverts, masquez et affichez le popover
canvaspour vous assurer qu'il se trouve au premier plan.
Pop-over de feuille d'action
Cette démo montre comment utiliser un popover comme feuille d'actions.
- Affichez le popover par défaut en remplaçant
display. - La feuille d'actions s'ouvre avec le déclencheur du popover.
- Lorsque le pop-over s'affiche, il est promu au premier plan et traduit dans la vue.
- Vous pouvez utiliser la fermeture légère pour le faire revenir.
Pop-up d'activation du clavier
Cette démonstration montre comment utiliser un popover pour une UI de style palette de commandes.
- Utilisez cmd+j pour afficher le pop-over.
- Le
inputest sélectionné avecautofocus. - La zone de liste déroulante est un deuxième
popoverplacé sous l'entrée principale. - La fermeture légère ferme la palette si le menu déroulant n'est pas présent.
- Autre candidat pour l'API Anchoring
Pop-over temporisé
Cette démo montre un pop-up d'inactivité après quatre secondes. Il s'agit d'un modèle d'UI souvent utilisé dans les applications qui contiennent des informations sécurisées sur un utilisateur pour afficher une fenêtre modale de déconnexion.
- Utilisez JavaScript pour afficher le pop-over après une période d'inactivité.
- Réinitialisez le minuteur lorsque le pop-over s'affiche.
Économiseur d'écran
Comme dans la démo précédente, vous pouvez ajouter une touche de fantaisie à votre site et ajouter un économiseur d'écran.
- Utilisez JavaScript pour afficher le pop-over après une période d'inactivité.
- Fermez la fenêtre pour masquer et réinitialiser le minuteur.
Suivi du point d'insertion
Cette démo montre comment faire suivre un pop-over par un curseur de saisie.
- Affichez le pop-over en fonction de la sélection, de l'événement clavier ou de la saisie de caractères spéciaux.
- Utilisez JavaScript pour mettre à jour la position du pop-over avec des propriétés personnalisées à portée limitée.
- Ce modèle nécessite une réflexion approfondie sur le contenu affiché et l'accessibilité.
- On le voit souvent dans les interfaces utilisateur d'édition de texte et dans les applications où vous pouvez ajouter des tags.
Menu du bouton d'action flottant
Cette démo montre comment utiliser un popover pour implémenter un menu de bouton d'action flottant sans JavaScript.
- Promouvez un pop-up de type
manualavec la méthodeshowPopover. Il s'agit du bouton principal. - Le menu est un autre pop-over qui est la cible du bouton principal.
- Le menu s'ouvre avec
popovertoggletarget. - Utilisez
autofocuspour sélectionner le premier élément de menu affiché. - La fermeture légère ferme le menu.
- La rotation de l'icône utilise
:has(). Pour en savoir plus sur:has(), consultez cet article.
Et voilà !
Voilà une introduction aux popovers, qui seront disponibles prochainement dans le cadre de l'initiative Open UI. Utilisé à bon escient, il constituera un ajout fantastique à la plate-forme Web.
N'oubliez pas de consulter Open UI. L'explication du pop-up est mise à jour à mesure que l'API évolue. Cliquez ici pour accéder à la collection de toutes les démos.
Merci de votre visite !