Niveau Niveau expert

Dialog, Modal, Popover : la synthèse

Articlecss

Publié par le (3525 lectures)

layer z-index modale popup popin dropdown

L'arrivée de l'attribut et de l'API HTML popover facilite la gestion de tous les éléments qui doivent s'afficher au-dessus du contenu d'une page Web (fenêtre modale, tooltip, menu déroulant, etc.).

Cette nouvelle fonctionnalité vient s'ajouter à certaines déjà existantes, au point où l'on ne sait plus forcément où donner de la tête entre les éléments dits "Dialog", "Modal", "Popover" ou autres "Overlay".

Tentons de rassembler toutes les caractéristiques globales et techniques de l'ensemble de ces notions afin d'y voir plus clair.

Cet article a pour objectif de poser les bases et de définir les différents termes en jeu. Dans un deuxième temps un article détaillé sera consacré à <dialog> et un autre à popover.

Tableau récapitulatif

Pour bien se rendre compte du nombre de fonctionnalités qui intéragissent, voici d'emblée un tableau récapitulatif des éléments que nous allons couvrir…

popover <dialog>
(modal)
<dialog>
(non modal)
<div role=dialog>
Overlay oui oui oui oui
Modal non oui non non
Inert non oui non non
Top layer oui oui non non
Focus trap non oui oui non
Dismissible echap ou manuel echap echap non
Commentaires Exclusif : ouvrir un popover ferme le précédent Masqué par défaut, visible avec l'attribut open Masqué par défaut, visible avec l'attribut open

Les différentes notions de ce tableau sont détaillées tout au long de cet article de synthèse : popover, <dialog>, overlay, modal, inert, top layer, focus trap, dismissible.

Overlay

Le terme "overlay" ne représente pas véritablement un composant mais une caractéristique. Un élément "overlay" est simplement un élément qui se place au-dessus d'autres éléments dans la page.

Tous les éléments au sein de cette liste sont des overlays :

  • une "fenêtre modale",
  • un menu déroulant,
  • une Tooltip,
  • une boîte de dialogue,
  • un Datepicker,
  • un Dropdown,
  • un Toaster,
  • une notification,
  • un bandeau cookie,
  • etc.

Dans cette même famille nous croiserons les termes de "pop-up" (nouvelle fenêtre au-dessus de la fenêtre actuelle du navigateur) et "pop-in" (élément au-dessus des autres éléments de la page, synonyme de "overlay", donc).

Modal et non-Modal

Selon les spécifications HTML, le terme "modal" ne désigne pas un composant en tant que tel, mais un ensemble de caractéristiques : un élément en overlay peut être "modal" ou "non-modal".

Un élément Modal est le seul à être interactif dans un document, il requiert toute l'attention de l'usager, tout le reste de la page doit être rendu inerte (inert) car aucune autre action ne doit être possible mis à part réagir à cet élément (fermer, accepter, refuser, abandonner, etc.).

Par exemple, un bandeau de recueil de données personnelles doit être consenti par l'utilisateur (obligation légale RGPD) sans quoi il ne devrait pas pouvoir accéder au site. C'est donc un élément de type Modal. Un autre exemple pourrait être celui d'une une modale "login/password" si l'accès au site nécessite une authentification.

Un élément non-Modal, à l'inverse, laisse la possibilité à l'utilisateur de continuer à interagir avec la page. C'est génaralement de cas des éléments tooltip, menu déroulant, dropdown, datepicker, notification, alerte, bandeau cookie.

inert

Un contenu inerte est un contenu avec lequel les utilisatrices et utilisateurs ne peuvent pas interagir. Il n'existe que visuellement, mais ne peut être atteint, cliqué, défilé ni consulté au moyen de technologies d'assistance.

Différentes techniques permettent de rendre une partie de page inerte :

  • L'attribut HTML inert,
  • L'ancienne technique via la combinaison de aria-hidden=true et de tabindex="-1",
  • Un polyfill JavaScript : https://github.com/WICG/inert,
  • L'élément <dialog> (voir cette section pour les détails).

compatibilité de l'attribut inert

Top layer

Top layer est une couche d'empilement au dessus de l'ensemble du document (existe depuis juin 2023). Cette couche n'est pas concernée par z-index ni par overflow: hidden. Les éléments s'empilent dans l'ordre d'apparition dans le Top layer.

Certains éléments sont placés automatiquement par défaut dans le top layer :

  • les éléments en fullscreen API
  • les éléments <dialog> (sauf exceptions)
  • les éléments avec l'attribut popover (sauf exceptions)

::backdrop

Ce pseudo-élement s'applique uniquement aux objets placés dans le top layer. Il permet d'apporter des styles visuels "sous" un overlay en obscurcissant la page par exemple.

/* Cette ombre n'est affichée que si l'élément */
/* est dans le Top layer */
dialog::backdrop {
  background: rgba(0,0,0,0.3);
}

compatibilité du sélecteur ::backdrop

Focus trap

Certains élément nécessitent que la navigation au clavier (touches Tab ou Shift + Tab) ne quitte pas le périmètre du composant : en atteignant le dernier élément focusable, on retourne en boucle au premier élément focusable au sein du composant.

C'est le comportement attendu et souhaité en accessibilité lorsque le composant est "modal" et que tout le reste du document est inerte.

Le focus trap doit toutefois être temporaire et disparaître quand le composant est quitté ou rejeté (dismissed).

Dismissible (jetable)

Certains overlay nécessitent de pouvoir être fermés de manière automatique (via touche echap ou au focus à l'extérieur du composant) et/ou de façon manuelle (en validant un bouton de soumission par exemple). Ce comportement se nomme "Dismissible".

Le menu déroulant sur Alsacréations

Dialog

Un Dialog est un composant de type overlay destiné à apporter une information à un usager et recueillir une interaction de sa part. Les spécifications proposent une API HTMLDialogElement ainsi qu'un élément natif <dialog> qui peut être "Modal" ou "non-Modal".

Le déclenchement se fait via l'API JavaScript :

  • show(): Ouvre le dialog en non-Modal
  • showModal(): Ouvre le dialog en Modal
  • close(): Ferme le dialog et renvoie en option une valeur

Voici un exemple concret :

<dialog id="modale">
  <p>Une modale de type Modal</p>
</dialog>
const modal = document.querySelector("#modale");
modal.showModal();

Les particularités de l'élément <dialog> sont :

  • role=dialog par défaut
  • Masqué par défaut, visible avec l'attribut open
  • Nécessite un nom accessible (aria-label ou aria-labelledby)
  • Focus trap : activé par défaut
  • Jetable (dismiss) via touche echap

Selon son état (Modal ou non-Modal), d'autres caractéristiques s'ajoutent à la liste précédente.

  • Si le <dialog> est "Modal" :

    • Il est placé dans le Top layer,
    • ::backdrop est applicable,
    • Tout le reste du document est rendu automatiquement inert.
  • Si le <dialog> est "non-Modal" :

    • Il n'est pas placé dans le Top layer (donc les règles de stacking context et de z-index s'appliquent),
    • ::backdrop ne s'applique pas,
    • Tout le reste du document est interactif.

Les spécifications d'accessibilité ARIA proposent un attribut role="dialog" pouvant être appliqué sur n'importe quel élément HTML autre que <dialog>, mais sachez que cela implique par défaut :

  • Que l'élement est "non-Modal" (peut le devenir avec aria-modal="true"),
  • Qu'il n'est pas dans le Top layer,
  • Qu'il ne rend pas le reste de page inerte,
  • Qu'il ne crée pas de Focus trap,
  • Qu'il n'est pas Jetable (dismiss) via touche echap.

En outre, sans API JavaScript showModal(), l'élément <dialog> est non-Modal :

<dialog id="dialog" open>
  <p>je suis non-modal</p>
</dialog>

compatibilité de l'élément dialog

:modal

La pseudo-classe :modal s'applique à tous les éléments à l'état Modal (par exemple un <dialog> ouvert avec l'API showModal()).

#modale:modal {
  background: hotpink;
}

compatibilité du sélecteur :modal

popover

Un popover est un overlay composé d'un attribut popover associé à un déclencheur :

<button popovertarget="tooltip">Ouvrir la tooltip</button>
<div popover id="tooltip">Choucroute et Saucisses de Strasbourg&nbsp;!</div>

Les particularités d'un élément pourvu d'un attribut popover sont :

  • L'élément est "non-Modal",
  • Il est placé dans le Top layer,
  • ::backdrop est applicable,
  • Aucun role spécifique ne lui est affecté. Le choix dépend du type de composant (role="alert" par exemple),
  • Jetable (dismiss) via touche echap par défaut,
  • Exclusif : il peut y en avoir plusieurs dans la page mais un seul dans l'état déployé à la fois.

Le comportement dismissible (jetable) dépend de la valeur associée à l'attribut popover :

  • light dismiss (<div popover=auto>, valeur par défaut si omise) : c'est le comportement idéal pour tooltip, menu déroulant, dropdown, datepicker,
  • manual dismiss (<div popover=manual>) : parfait pour des notifications ou des alertes.

compatibilité de l'attribut popover

:popover-open

La pseudo-classe CSS :popover-open représente un élément popover (c'est-à-dire un élément avec un attribut popover) qui est dans l'état ouvert.

:popover-open {
  /*...*/
}

compatibilité du sélecteur :popover-open

OK alors quand est-ce qu'on utilise quoi ?

Le nombre de possibilités offertes par les spécifications ne facilite pas le choix lorsqu'il s'agit d'intégrer un composant qui doit se placer au-dessus d'un contenu.

Entre les modales, les menus déroulants, les boîtes de dialogues et autres bandeaux d'alerte, il n'est guère aisé de piocher parmi <dialog>, popover ou une simple <div> en position abolute dopée avec JavaScript.

Les réponses aux deux questions suivantes sont déterminantes dans votre choix final :

  • L'utilisateur a-t-il le droit d'ignorer ce composant ?
    (si non, alors il s'agit sans aucun doute d'un élément "Modal" car tout le reste de la page doit devenir inert)
  • Le visuel attendu est-il une "modale" avec backdrop obscurci ?
    (si oui, là aussi nous aurons recours à un élément de type "Modal")

J'espère avoir éclairci la plupart des points d'ombres (même s'il en demeure sans doute) de ce vaste sujet des différents overlays. Pour finir, voici quelques articles de référence absolument indispensables pour en savoir plus.

Ressources

Commentaires

Salut, intéressant pour comprendre un peu mieux, merci.

Pour par exemple afficher une div qui contient du texte juste au-dessus de son bouton déclencheur, tu utilises quoi ?

Merci.

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.