Les dernières actualités d'Alsacreations.com
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
.
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.
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 :
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).
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 :
inert
,aria-hidden=true
et de tabindex="-1"
,<dialog>
(voir cette section pour les détails).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 :
<dialog>
(sauf exceptions)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);
}
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).
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".
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-ModalshowModal()
: Ouvre le dialog en Modalclose()
: Ferme le dialog et renvoie en option une valeurVoici 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éfautopen
aria-label
ou aria-labelledby
)echap
Selon son état (Modal ou non-Modal), d'autres caractéristiques s'ajoutent à la liste précédente.
Si le <dialog>
est "Modal" :
::backdrop
est applicable,inert
.Si le <dialog>
est "non-Modal" :
z-index
s'appliquent),::backdrop
ne s'applique pas,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 :
aria-modal="true"
),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>
: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;
}
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 !</div>
Les particularités d'un élément pourvu d'un attribut popover
sont :
::backdrop
est applicable,role
spécifique ne lui est affecté. Le choix dépend du type de composant (role="alert"
par exemple),echap
par défaut,Le comportement dismissible (jetable) dépend de la valeur associée à l'attribut popover
:
<div popover=auto>
, valeur par défaut si omise) : c'est le comportement idéal pour tooltip, menu déroulant, dropdown, datepicker,<div popover=manual>
) : parfait pour des notifications ou des alertes.: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 {
/*...*/
}
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 :
inert
)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.
Les images SVG sont désormais omniprésentes sur le web : illustrations, schémas, décoration, icônes, ce format vectoriel se prête bien à toutes sortes de formes simples car il est léger et étirable à l'infini produisant un beau résultat sur les écrans à forte densité de pixel (hdpi, retina...).
Si l'on peut en produire "à la main" à l'aide d'un éditeur de code, car il s'agit avant tout de XML, les images SVG sont souvent générées par des programmes de dessin/webdesign tels que Figma, Illustrator, Inkscape et divers. Ces programmes ne vont pas nécessairement réduire au maximum le poids de l'image, même si cela tend à s'améliorer. Ils n'hésiteront pas à ajouter des métadonnées inutiles ou des instructions de code superflues, provenant de la façon dont a été élaborée l'image (calques, précision des formes et des tracés).
Ainsi Figma proposera une petite fonctionnalité d'export bien pratique et rapide pour copier une forme ou un groupe en tant que code SVG. Celui-ci pourra être inclus de manière inline au code HTML.
La performance étant cruciale, et scrutée par les outils d'analyse, les robots d'indexation, il est courant de devoir faire attention non seulement au poids des images bitmap (jpeg, png, webp, avif) mais aussi à SVG, avec d'autres techniques compte tenu de sa spécificité vectorielle.
S'il y a quelques années, il fallait se pencher manuellement sur l'optimisation du code SVG, désormais bon nombre d'outils remplissent 99% des objectifs. La plupart étant listés par CSS Tricks : Tools for Optimizing SVG.
ð¤ Pour un traitement automatisé, on pourra prévoir dans un workflow de pojet web d'intégrer svgo durant un processus de compilation ou simplement en ligne de commande. En voici un exemple via Nodejs mais cette bibliothèque se retrouve dans d'autres situations (extension Sketch, Visual Studio Code, SublimeText, Atom... plugin postCSS, Gulp, Webpack, etc.).
pnpm add -g svgo
# Des images sélectionnées
svgo image1.svg image2.svg -o image1.min.svg image2.min.svg
# Tout un dossier (récursif)
svgo -f images/svg/icons/src -o images/svg/icons/dist
ð¨ Pour un export depuis Figma, on passe par une extension de la communauté Advanced SVG Export qui embarque l'algorithme de SVGO et dont les paramètres sont configurables.
ð Pour un traitement image par image quelle que soit la source, utilisons le fameux SVGOMG, version humainement graphique de SVGO, qui acceptera soit un fichier soit un copier-coller direct (encore plus pratique), puis affichera l'aperçu et la possibilité de ré-exporter ou re-copier le code source amélioré.
Si la plupart des options par défaut conviennent, détaillons celles qui rejoignent les principales techniques à retenir lorsqu'on intervient manuellement sur du SVG :
Exemple de chemin avec trop de précision :
<path d="M24 18.55C26.2 17.45 27.5 16.15 28 14.55C28.6 12.65 27.8 10.55 25.8 8.34996C24.1 6.34996 22.3 5.64996 20.5 6.14996C19 6.54996 17.6 7.84996 16.3 9.84996C15.2 11.55 14.3 13.65 13.7 15.75C13.1 17.85 13 19.35 13.3 20.25C14.2 20.55 15.6 20.55 17.8 20.25C20.1 20.15 22.2 19.55 24 18.55ZM12 9.44996C13.1 7.24996 13.4 5.44996 12.8 3.94996C12.1 2.04996 10.3 0.849963 7.40002 0.249963C4.90002 -0.350037 3.00002 0.149963 1.90002 1.64996C1.00002 2.84996 0.500025 4.64996 0.700025 7.14996C0.800025 9.24996 1.30002 11.35 2.20002 13.55C3.00002 15.55 3.70003 16.85 4.50003 17.45C5.40003 17.25 6.60003 16.25 8.10003 14.75C9.90003 12.95 11.1 11.25 12 9.44996ZM25.6 33.75C28 34.15 29.8 33.85 31.1 32.85C32.6 31.65 33.2 29.55 32.9 26.55C32.7 23.95 31.6 22.45 29.9 21.75C28.4 21.25 26.6 21.45 24.3 22.35C22.4 23.15 20.5 24.25 18.8 25.65C17.1 27.05 16.1 28.15 15.9 29.15C16.5 29.85 17.6 30.75 19.5 31.75C21.6 32.85 23.6 33.55 25.6 33.75Z" fill="#ACC737"/>
Le voici optimisé avec moins de précision sur les coordonnées, et un résultat visuel semblable :
<path d="M24 18.6c2.2-1.2 3.5-2.5 4-4 .6-2-.2-4-2.2-6.3-1.7-2-3.5-2.7-5.3-2.2-1.5.4-2.9 1.7-4.2 3.7-1.1 1.8-2 3.8-2.6 6-.6 2-.7 3.6-.4 4.4.9.4 2.3.4 4.5 0a14 14 0 0 0 6.2-1.6ZM12 9.4c1.1-2.2 1.4-4 .8-5.5C12.1 2 10.3 1 7.4.2 4.9-.4 3 .2 1.9 1.6 1 2.8.5 4.6.7 7.1c.1 2.1.6 4.3 1.5 6.5.8 2 1.5 3.3 2.3 3.8.9-.1 2.1-1.1 3.6-2.6A20 20 0 0 0 12 9.3Zm13.6 24.4c2.4.4 4.2 0 5.5-1 1.5-1.1 2.1-3.2 1.8-6.2-.2-2.7-1.3-4.2-3-4.9-1.5-.4-3.3-.3-5.6.7-1.9.8-3.8 1.9-5.5 3.3-1.7 1.4-2.7 2.4-2.9 3.4.6.8 1.7 1.6 3.6 2.6 2.1 1.2 4.1 1.8 6.1 2Z" fill="#ACC737"/>
<!-- -->
dans le code source, métadonnées de l'éditeur d'image qui aime y laisser sa trace, et même éléments cachés (hidden
) : tout ce qui ne se "voit" de toute façon pas en production, et ignoré par le navigateur.xmlns
n'est pas nécessaire si le code SVG est inline dans le code HTML.style=""
(ex : 2 carrés verts auront les mêmes propriétés) pour gagner de la place. En revanche l'option merge paths peut empêcher de conserver tous les tracés individuels pour agir sur chacun : cela dépendra beaucoup des règles externes CSS et du code JavaScript qui pourrait interagir avec le SVG attendu. Si vous écrivez des propriétés de style qui doivent s'appliquer sur un élément en particulier, nommé par une classe, et que cette classe est retirée, cela n'aura plus d'effet.<g>
) qui ne sont pas nécessaires au-delà de l'édition, il faut juste faire attention à préserver l'ordre de superposition des formes.<path>
avec des coordonnées minimales.Si vous examinez toutes les options listées par SVGOMG, vous imaginerez aisément tout ce qui peut être entrepris pour alléger une image SVG. Pour constater les effets avant/après sur le code source, consultez l'onglet Markup et activez/désactivez l'option Show original.
Une opération toutefois devra nécessiter une vérification et intervention manuelle : si votre SVG contient des images bitmap (non vectorielles), ce qui est tout à fait possible pour des effets non reproductibles en vectoriel (cela se remarquera à son poids global lourd et à la présence de code en base64) alors il faudra étudier la possibilité de les remplacer par de vraies formes simplifiées.
Utilisez SVGOMG.