Robuste et accessible

  • Comme c’est basé sur une structure HTML de base (Hx et contenus), même si le JavaScript n’est pas chargé, la page marchera, c’est le miracle de l’amélioration progressive ;
  • C’est basé sur le Design Pattern ARIA pour les onglets, légèrement amélioré au passage ;
  • Pas de CSS/JavaScript injecté en ligne, le DOM reste propre, ce qui cool pour le responsive ou CSP.

C’est (hautement) personnalisable

  • Vous pouvez le styler comme vous voulez ;
  • Vous pouvez utiliser des transitions ou animations… comme vous voulez ;
  • Vous pouvez créer un namespace pour les classes générées si vous avez besoin de différents comportements 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

  • 31kb (développement, lisible par les humains) ;
  • ~8kb (minifié, lisible par des machines) ;
  • ~3kb minifié et gzippé (lisible par… des mutants ‽‽)

Comment ça marche

Voici le code pour démarrer. Ajoutez le script, les styles CSS, personnalisez-les si besoin, et ça sera ok.

<div class="js-carrousel relative">      
  <div class="js-carrousel__container mod--hidden" 
   data-carrousel-btn-previous-img="./left.svg"
   data-carrousel-btn-next-img="./right.svg"
   data-carrousel-btn-previous-text="Voir le contenu précédent"
   data-carrousel-btn-next-text="Voir le contenu suivant"
   data-carrousel-prefix-class="news"
   data-carrousel-span-text-class="invisible"
   data-carrousel-transition="slide"
   data-carrousel-existing-hx="h3">
          
    <div class="js-carrousel__content">
      <h3>Premier panneau</h3>
      <p>Ici le contenu.</p>
    </div><!--
 --><div class="js-carrousel__content">
      <h3>Deuxième panneau</h3>
      <p>Ici le contenu.</p>
    </div><!--
 --><div class="js-carrousel__content">
      <h3>Troisième panneau</h3>
      <p>Ici le contenu.</p>
    </div>
          
  </div>
</div>

Le script fera tout le restant du boulot et, à la volée :

  • Génèrera tous les ids, les attributs ARIA nécessaires et liera tout cela ;
  • Créera les boutons « Suivant » et « Précédent » ;
  • Génèrera la liste de contrôles ;
  • Ajoutera les classes (namespacées si demandé), pour vous permettre de styler selon vos besoins ;
  • Ajoutera tous les listeners, etc.

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 du carrousel</div> :

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

Comment l’utiliser

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

Ensuite, suivez les conventions données ci-dessus. Vous pouvez aussi copier/coller les styles du carrousel et des transitions.

Note importante : pour des questions d’accessibilité (pour VoiceOver), le script doit donner le focus à un hx (h2, h3, h4, etc.) dans les contenus du carrousel. Il est donc préférable d’avoir un hx pour chaque panneau du carrousel.

  • Si vous les avez mis, c’est génial, il faut le dire au script. Dans l’exemple ci-dessus, cela s’indique via data-carrousel-existing-hx.
    Et tous ces sous-titres seront repris dans la liste ol des contrôles.
  • Si vous n’en avez pas, ce n’est pas grave, dites au script quel niveau de hx il doit générer avec data-carrousel-hx="hx", et le script insèrera un hx class="invisible" pour vous dans chaque panneau du carrousel (vous pouvez les cacher « visuellement » si besoin est avec la classe invisible).
    Pour spécifier les titres, utilisez l’attribut data-carrousel-span-text="Panneau" et le script créera des titres pour chaque panneau du carrousel : « Panneau 1 », « Panneau 2 », etc. Et ces sous-titres seront repris dans la liste ol des contrôles.

Liste des attributs data-

  • data-carrousel-btn-previous-img : l’adresse de l’image utilisée dans le bouton « Précédent ».
  • data-carrousel-btn-previous-text : le texte du bouton « Précédent », qui sera mis dans l’attribut alt s’il y a une image spécifiée, et dans l’attribut title du bouton sinon.
  • data-carrousel-btn-next-img : l’adresse de l’image utilisée dans le bouton « Suivant ».
  • data-carrousel-btn-next-text : le texte du bouton « Suivant », qui sera mis dans l’attribut alt s’il y a une image spécifiée, et dans l’attribut title du bouton sinon.
  • data-carrousel-prefix-class : toutes les classes générées pour les styles seront préfixées, pour simplifier la création/maintenance des styles du carrousel.
  • data-carrousel-span-text-class : dans la liste des contrôles ol, chaque texte sera entouré par un span avec cette classe. Exemple, data-carrousel-span-text-class="yipikai" :
    <a  role="tab">
      <span class="yipikai">Une base robuste</span>
    </a>
  • data-carrousel-transition : la valeur de cet attribut sera ajoutée comme classe sur le conteneur du carrousel div class="js-carrousel__container". Et CSS fera la magie pour l’animer. Voir trois exemples de transitions dans la démo (« slide », « fade » et « none »).
  • data-carrousel-active-slide : mettez ici le numéro du panneau que vous voulez voir affiché par défaut pour votre carrousel.

Comment (bien) le styler

Dans cet exemple, j’ai utilisé data-carrousel-prefix-class="news", donc toutes les classes générées commenceront par .news-carrousel.

/* ------------------ styles exemples ------------------ */
.relative { position: relative; }
.mod--hidden { overflow: hidden; }

.invisible {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}

.news-carrousel__container {
  white-space: nowrap;
}
.news-carrousel__control__list {
  position: absolute;
  list-style-type: none;
  top: 100%;
  right: 0;
  left: 0;
  margin-top: -0.5em;
  padding-left: 0;
  text-align: center;
}
.news-carrousel__control__list__item {
  display: inline-block;
  margin: 0 .5em;
}
.news-carrousel__control__list__link {
  display: inline-block;
  width: 1em;
  height: 1em;
  background: #fff;
  border: 1px solid #148297;
  border-radius: 1em;
  cursor: pointer;
}

.news-carrousel__button-container {
  position: absolute;
}
.news-carrousel__button__previous {
  top: 50%;
  margin-top: -18px;
  left: 0;
  margin-left: -35px;
}
.news-carrousel__button__next {
  top: 50%;
  margin-top: -18px;
  right: 0;
  margin-right: -35px;
}
.news-carrousel__button__button {
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
}

/* seulement pour exemple minimaliste */
.carrousel__content[aria-hidden=true] {
  display: none;
}
/* ------------------ Règles d’état ------------------ */
.news-carrousel__control__list__link:focus,
.news-carrousel__control__list__link:hover,
.news-carrousel__control__list__link:active,
.news-carrousel__control__list__link[aria-selected=true] {
  background: #148297;
}
.news-carrousel__control__list__link:focus,
.news-carrousel__control__list__link:hover,
.news-carrousel__control__list__link:active {
  outline: 2px dotted #4d287f;
}

Comment (bien) styler les transitions

Voici 3 examples de transitions :

/* ------------------ transition slide ------------------ */
.slide .carrousel__content {
  display: inline-block;
  vertical-align: top;
  visibility: visible;
  width: 100%;
  position: relative;
  transition: visibility 0s ease, transform .5s ease-in;
  transition-delay: 0;
  white-space: normal;
}

[data-carrousel-active-slide="1"].slide > .carrousel__content {
  transform: translateX(0);
}
[data-carrousel-active-slide="2"].slide > .carrousel__content {
  transform: translateX(-100%);
}
[data-carrousel-active-slide="3"].slide > .carrousel__content {
  transform: translateX(-200%);
}
[data-carrousel-active-slide="4"].slide > .carrousel__content {
  transform: translateX(-300%);
}
[data-carrousel-active-slide="5"].slide > .carrousel__content {
  transform: translateX(-400%);
}
[data-carrousel-active-slide="6"].slide > .carrousel__content {
  transform: translateX(-500%);
}
[data-carrousel-active-slide="7"].slide > .carrousel__content {
  transform: translateX(-600%);
}
[data-carrousel-active-slide="8"].slide > .carrousel__content {
  transform: translateX(-700%);
}
[data-carrousel-active-slide="9"].slide > .carrousel__content {
  transform: translateX(-800%);
}

[data-carrousel-active-slide].slide > [aria-hidden="true"].carrousel__content {
  visibility: hidden;
  transition-delay: .5s, 0s;
}


/* ------------------ transition fade ------------------ */
.fade .carrousel__content {
  -webkit-animation: fadein 1s;
  animation:         fadein 1s;
  white-space: normal;
}
.fade .carrousel__content[aria-hidden=true] {
  -webkit-animation: fadeout 1s;
  animation:         fadeout 1s;
}
.fade .carrousel__content[aria-hidden=true] {
  display: none;
}

@keyframes fadeout {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes fadein {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}



/* ------------------ transition none ------------------ */
.none .carrousel__content {
  white-space: normal;
}
.none .carrousel__content[aria-hidden=true] {
  display: none;
}

Raccourcis claviers

La navigation au clavier est possible (et même appréciée), voici les raccourcis clavier :

Si le focus clavier est sur les « boutons » (pas « suivant » et « précédent », sur la liste de contrôle) :

  • Utilisez Haut/Gauche pour voir le panneau précédent du carrousel ;
  • Utilisez Bas/Droite pour voir le panneau suivant du carrousel ;
  • Utilisez Home pour voir le premier panneau du carrousel (où que vous soyiez sur la liste de contrôle) ;
  • Utilisez End pour voir le dernier panneau du carrousel (où que vous soyiez sur la liste de contrôle).

Si le focus est dans un des panneaux du carrousel :

  • Utilisez Ctrl Haut pour remettre le focus sur le bouton de contrôle du panneau correspondant.

Bonus

Panneau ouvert par défaut

Vous pouvez utiliser sur js-carrousel__container l’attribut data-carrousel-active-slide="le numéro du panneau". Exemple : data-carrousel-active-slide="2" affichera le deuxième panneau par défaut. Dans la démo du carrousel, le troisième exemple montre cette option.