Robuste and accessible

  • C’est basé sur une structure HTML5 (balise dialog) plus ARIA ;
  • La navigation au clavier est supportée, basée sur le Design Pattern ARIA pour les modales ;
  • Pas de CSS/JavaScript injecté en ligne, le DOM reste propre, ce qui cool pour le responsive/CSP.

C’est (hautement) personnalisable

  • Vous pouvez le styler/animer comme vous voulez ;
  • Vous pouvez créer un namespace pour les classes générées si vous avez besoin de différents styles dans la même page ;
  • Chaque aspect du script peut être personnalisé, si vous transpilez le script en ES5, ce sera compatible IE9+.

Libre et sous une license permissive

  • Pas de problème : c’est placé sous licence MIT, donc c’est libre, open-source et vous pouvez faire ce que vous voulez avec, incluant une utilisation commerciale. Cette note de permission doit être incluse dans toutes les copies complètes ou partielles du script.
  • Cependant, il n’est pas interdit de me dire que vous l’avez utilisé, ou de m’envoyer un petit « merci ». ;)

Léger

  • 18kb (développement, lisible par les humains) ;
  • ~6,2kb (minifié, lisible par des machines) ;
  • ~2kb minifié et gzippé (lisible par… des mutants ‽‽)

Comment ça marche

Simplement, quand vous activez une modale :

  1. le script entoure tout le content de la page dans une div id="js-modal-page" ;
  2. il ajoute la classe noscroll sur l’élément body (pour enlever le scroll avec CSS si besoin) ;
  3. ensuite il insère un élément dialog à la fin de la page ;
  4. il met le focus clavier dans la modale et piège le focus clavier dedans ;
  5. quand vous voulez fermer la modale, le focus clavier est redonné à l’élément qui avait ouvert la modale.

Vous pouvez fermer la modale avec la touche Esc, ou en utilisant Entrée ou Espace si vous êtes sur le bouton de fermeture.

Les utilisateurs de souris peuvent cliquer en dehors de la modale pour la fermer (cette option peut être désactivée si besoin est).

Si vous n’activez jamais de modale, ce ne sera nulle part dans le code.

Comment l’utiliser

Télécharger le script

Vous pouvez utilisez la commande npm : npm i van11y-accessible-modal-window-aria.
Vous pouvez aussi utiliser Bower : bower install van11y-accessible-modal-window-aria.

Option et attributs

En premier lieu, mettez class="js-modal" sur le bouton ou le lien qui doit activer le script. Ensuite, voici tous les attributs :

  • Attribut data-modal-prefix-class : va préfixer toutes les classes CSS des éléments.
  • Attribut data-modal-text : le contenu de la modale (sera mis dans un élément p).
  • Attribut data-modal-content-id : l’id du contenu (caché) dans votre page qui sera mis dans votre modale (si data-modal-text n’est pas présent).
  • Attribut data-modal-title : le titre de la modale.
  • Attribut data-modal-close-text : le texte du bouton de fermeture de la modale.
  • Attribut data-modal-close-title : l’attribut title (infobulle) du bouton de fermeture de la modale.
  • Attribut data-modal-background-click="disabled" : bloque la possibilité de cliquer en dehors de la modale pour la fermer.
  • Attribut data-modal-close-img : le chemin vers une image valide pour le bouton de fermeture.
  • Attribut data-modal-focus-toid : l’id de l’élément dans la modale auquel vous souhaitez donner le focus, quand elle est lancée (bouton de fermeture si non spécifié).
  • Attribut data-modal-describedby-id : ajoute aria-describedby=<la valeur de l’attribut> à l’élément dialog.

Si vous en avez besoin, ajoutez class="js-modal-close" sur un élément du contenu de la modale, cela déclenchera un click sur le bouton de fermeture.

Souvenez-vous qu’il existe des démos, ce sera plus simple à comprendre : Démo d’une fenêtre modale accessible

Le script est lancé au chargement de la page. Si vous avez besoin de l’exécuter sur du contenu généré en AJAX, vous pourrez utiliser par exemple sur <div id="newContent">la source de la modale</div> :

van11yAccessibleModalWindowAria(document.getElementById('newContent')[, addListeners]);
addListeners est un booléen facultatif (par défaut à true) pour ajouter les listeners de la modale (nécessaires une seule fois normalement).

Styles minimum

Voici le minimum vital de styles pour que cela marche (sans attribut data-modal-prefix-class) :

/* Pour les brontobrowsers */
dialog {
  display: block;
  border: 0;
}
/* enlève le scroll de la page quand la modale est ouverte */
.no-scroll {
  overflow: hidden;
}
/* l’overlay couvre tout */
.modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  z-index: 666;
}
/* modale */
.modal {
  position: fixed;
  left: 25%;
  right: auto;
  top: 15%;
  width: 50%;
  background: #fff;
  z-index: 667;
}

Des exemples de styles

Voici les styles (non préfixés) utilisés pour la démo, j’ai utilisé data-modal-prefix-class="simple" et data-modal-prefix-class="simple-animated" pour namespacer, donc chaque classe commencera par .simple-/.simple-animated- :

dialog {
  display: block;
  border: 0;
}
/* enlève le scroll de la page quand la modale est ouverte */
.no-scroll {
  overflow: hidden;
}
/* l’overlay couvre tout */
.simple-modal-overlay,
.simple-animated-modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background: #fff;
  opacity: .8;
  z-index: 666;
  cursor: pointer;
}
.simple-modal-overlay[data-background-click="disabled"],
.simple-animated-modal-overlay[data-background-click="disabled"] {
  cursor: auto;
}
.simple-animated-modal-overlay  {
  animation: fadewhite ease .5s 1 normal ;
}

@keyframes fadewhite {
  0% {
    opacity: 0;
  }
  100% {
    opacity: .8;
  }
}
/* modales */
.simple-modal,
.simple-animated-modal {
  position: fixed;
  left: 15%;
  top: 5%;
  width: 70%;
  max-height: 98vh;
  border: 2px solid #000; 
  background: #fff;
  z-index: 667;
  padding: 2em;
  right: auto;
  overflow: auto;
}
.simple-modal-close,
.simple-animated-modal-close {
  float: right;
  background: #128197;
  border-radius: 1em;
  color: #fff;
  border: 0;
  font: inherit;
  padding: .25em .5em;
  cursor: pointer;
}
.simple-modal-close:focus,
.simple-modal-close:hover,
.simple-modal-close:active {
  outline: 1px dotted #fff;  
}
.simple-modal-close:hover,
.simple-modal-close:active {
  background: #4d287f;
}

.simple-animated-modal {
  animation: apparition ease .5s 1 normal ;
}

@keyframes apparition {
  0% {
    opacity: 0;
    max-height: 0;
    width: 0;
    left: 50%;
  }
  100% {
    opacity: 1;
    max-height: 100%;
    width: 70%;
    left: 15%;
  }
}

/* ça peut être adapté facilement avec des media-queries pour tablettes/mobiles */

/* pour cet exemple : tablettes */
@media (max-width: 55.625em) {

  .simple-modal,
  .simple-animated-modal {
    left: 5%;
    top: 5%;
    height: 90%;
    width: 90%;
  }
  
}

/* pour cet exemple : mobile */
@media (max-width: 44.375em) {

  .simple-modal,
  .simple-animated-modal {
    left: 1%;
    top: 1%;
    width: 98%;
    height: 98%;
  }

}

Autre exemple de styles

Voici les styles (non préfixés) utilisés pour le troisième exemple de la démo, j’ai utilisé data-modal-prefix-class="simple-left" pour namespacer, donc chaque classe commencera par .simple-left-:

/* Pour les bouses */
dialog {
  display: block;
  border: 0;
}
/* enlève le scroll de la page quand la modale est ouverte */
.no-scroll {
  overflow: hidden;
}

/* un autre exemple */
/* modale pour le bouton «c’est si facile» */
.simple-left-modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background: #fff;
  opacity: .8;
  z-index: 666;
  cursor: pointer;
}
.simple-left-modal-overlay[data-background-click="disabled"] {
  cursor: auto;
}

.simple-left-modal-overlay {
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background: rgba(0, 0, 0, .8);
  opacity: .8;
  z-index: 666;
  cursor: pointer;
}

.simple-left-modal {
  left: auto;
  right: 0;
  top: 0;
  bottom: 0;
  height: 100%;
  z-index: 667;
  position: fixed;
  width: 40em;
  max-width: 100%;
  padding: 0 1em 1em 1em;
  font-size: 1em;
  border: 0;
  overflow: auto;
  background-color: #aaa ; /* fallback CSS IE9 */
  background-image:
      -webkit-linear-gradient(
        top,
        #128197 3em,
        #f7f7f7 3em
      );  background-image:
      linear-gradient(
        to bottom,
        #128197 3em,
        #f7f7f7 3em
      );
  background-attachment: local;
}
.simple-left-modal-close {
  position: absolute;
  top: .5em;
  right: 0;
  background: transparent;
  color: #fff;
  border: 0;
  cursor: pointer;
}
.simple-left-modal-title {
  color: #fff;
  font-size: 1.5em;
}