HTML

HTML5 : Les éléments <details> et <summary>

Parmi les nouveautés de HTML5 faisant écho à des applications existantes sur le web, les éléments <details> et <summary> ont le rôle de baliser un complément d'information.

Article par (Graphiste webdesigneuse, Strasbourg)
Créé le , mis à jour le (48273 lectures)
Tags : xhtml, html5, summary, details

Un résumé et des détails

Élément <details>

Cet élément permet de baliser un contenu quelconque (texte, image, listes, tableaux, formulaires, etc) ayant pour rôle d'apporter une information ou des détails supplémentaires. Ceux-ci ne doivent cependant pas être obligatoires pour poursuivre la bonne marche de l'application web ou la compréhension du document HTML.

Le navigateur pourra masquer ces informations par défaut, et les déployer à la demande de l'utilisateur (voir exemples visuels ci-après). Une icône pourra indiquer l'état de l'élément : déployé (visible) ou compacté : seul le résumé reste visible. Ce résumé, assimilable à un titre ou une légende, est apporté par <summary>.

Attribut open de l'élément <details>

Si cet attribut est présent, les détails sont exposés à l'utilisateur dès le chargement.

Attribut Valeurs Rôle
open open ou "" ou (vide) Spécifie la visibilité initiale de l'élément (visible ou non à l'utilisateur)

Élément <summary>

Cet élément sert d'intitulé à <details>, en cela il doit être pertinent. Sa fonction s'apparente à une légende ou un résumé donnant du sens au contenu de son parent. Seul <details> peut-être le parent de <summary>. Si <summary>n'est pas présent, il incombe au navigateur de déterminer le libellé de <details>.

Exemples pratiques retrouvés sur systèmes d'exploitation

L'intérêt de ces deux éléments fonctionnant de concert est de mimer ce que l'on retrouve déjà couramment avec les interfaces graphiques des systèmes d'exploitation. Un intitulé est présenté à l'utilisateur, résumant parfois un état, et permettant d'accéder - généralement après un clic - à d'autres informations détaillées.


Compatibilté navigateur des éléments <details> et <summary>

Navigateurs Versions
Chrome Chrome 12.0+
Chrome pour Android
Android Android Browser 4.0+
Safari Safari 6+
Safari iOS 6+
Blackberry Logo Blackberry 10+
Opera Opera 15
Opera Mobile 15

Un navigateur ne supportant pas ces éléments affichera leur contenu sans comportement particulier.

Utilisation classique

L'élément <details> contient l'élément <summary> lui servant d'intutilé ou de légende, à la suite de celui-ci nous retrouvons le contenu à afficher ou masquer. L'attribut open affichant par défaut le contenu. Pour une utilisation classique l'icône par défaut est une flèche : 

<details open>
   <summary>Caractéristiques techniques</summary>
   <table>
      <tr>
         <th>Nom</th>
         <th>Détails</th>
      </tr>
      <tr>
         <td>Matière</td>
         <td>Inox alimentaire</td>
      </tr>
      <tr>
         <td>Dimensions</td>
         <td>140x120 mm, hauteur 30 mm</td>
      </tr>
   </table>
</details>

L'élément <details> peut aussi contenir des éléments de formulaire.

<form>
   <label for="quantite">Quantité : </label>
   <input type="number" name="nombre" id="quantite">

   <details>
      <summary>Options possibles</summary>
      <fieldset>
      <legend>Choix de la couleur :</legend>
         <p>
         <input type="radio" id="d1" name="couleurs"><label for="d1">Gris</label>
         <input type="radio" id="d2" name="couleurs"><label for="d2">Rouge</label>
         <input type="radio" id="d3" name="couleurs"><label for="d3">Vert</label>
         <input type="radio" id="d4" name="couleurs"><label for="d4">Bleu</label>
         </p>
      <fieldset>
   </details>
   <input type="submit" value="Ajouter au panier">
</form>

Démonstration

Aperçu sous Chrome 16.0

Accessibilité

Dans cet exemple, le groupe de boutons radio est entouré d'un élément <fieldset> (et donc précédé d'un élément <legend> pertinent), comme le demande la Technique WCAG 2.0 H71: Providing a description for groups of form controls using fieldset and legend elements (voir les critères 11.5 à 11.7 du référentiel Accessiweb 2.1 pour les critères de succès WCAG 2.0 et tests RGAA correspondants).

C'est cet élément fieldset qui est entouré d'un élément <details> (et précédé d'un élément <summary>). Une variante de l'exemple où figurerait seulement les 5 boutons radio et leurs étiquettes ainsi que les éléments summary et details aurait été plus courte mais sans fieldset ni legend, la fonction des boutons radio n'est plus explicitée, en particulier dans les lecteurs d'écran actuels.

Concernant l'accessibilité générale des éléments <details> et <summary> ceux-ci ne sont pas accessibles au clavier car il n'est pas possible d'atteindre le marqueur (icône) via la tabulation dans le navigateur l'implémentant début 2012. HTML5 Doctor aborde le sujet, se référer à son article sur ces éléments.

Aller plus loin

Combinaison multiple

Plusieurs blocs <details> peuvent être imbriqués les uns dans les autres, cette pratique reste tout à fait valide.

Modifier le style de l'icône

Il n'y a pas de convention actuellement définie et reconnue par tous les navigateurs pour accéder aux propriétés CSS. Néanmoins avec le moteur WebKit et la pseudo-classe ::-webkit-details-marker vous pouvez modifier l'icône (en forme de flèche par défaut). Le sélecteur details[open], permet de styler l'icône lorsque <details> est déployé.

summary::-webkit-details-marker {
   color:#ADCA48;
   background:#ADCA48;
}

details[open] summary::-webkit-details-marker {
   color:#eaeaea;
   background:#eaeaea;
   outline: 2px solid #ADCA48;
}

Démonstration

Aperçu sous Chrome 16.0

Il est également possible de changer l'icône par défaut à l'aide de la  pseudo-classe :after

summary::-webkit-details-marker {
   display: none
}

summary:after {
   content: "+";
   color: #ADCA48;
   float: left;
   font-size: 1.5em;
   font-weight: bold;
   margin: -5px 5px 0 0;
   padding: 0;
   text-align: center;
   width: 20px;
}

details[open] summary:after {
   content: "-";
}

Démonstration

Aperçu sous Chrome 16.0

Alternative en JavaScript

Voici une alternative basée sur jQuery pour les navigateurs n'implémentant pas encore les éléments <details> et <summary>. Il est important de savoir que ces éléments peuvent être utilisés quelle que soit la prise en charge. Si l'effet est déjà fonctionnel avec des éléments neutres <div> et un complément en JavaScript, il sera profitable de s'orienter vers <details> et <summary> pour les navigateurs qui les supportent nativement, et de continuer à exploiter la version en JavaScript pour les autres.

Tout d'abord faites appel à votre script dans lequel vous intégrerez la fonction permettant d'afficher/masquer les éléments et la dernière version de jQuery en les insérant juste avant la balise de fermeture </body>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
  <script src="details-summary.js"></script>
</body>

Dans votre fichier details-summary.js, il vous faudra vous assurer que la page est chargée, une fois celle-ci prête il est important de vérifier que le navigateur n'implémente pas les éléments <details> ou <summary> afin de ne pas lancer le script si tel est le cas :

$(document).ready(function() {
 if (!('open' in document.createElement('details'))) {

Une fois la condition validée, pour chaque élément <details> on affiche "son" <summary> à l'aide de la méthode show(). Pour procéder à la détection, l'utilisation de Modernizr peut être plus avantageuse.

Et lorsque l'on clique sur l'élément <summary> une fonction permet d'afficher ou masquer les frères de celui-ci, c'est-à-dire le contenu. Puis on ajoute ou enlève la classe open à l'élément <details> ainsi que la classe html5_details.

    $("details").each(function() {
      $(this).find("summary").show().click(function() {
        $(this).siblings().toggle();
        $(this).parent('details').toggleClass('open');
      });

Avant de fermer la fonction, il reste encore à masquer le contenu si l'attribut open n'est pas présent au sein de la balise <details>. On stocke dans une variable l'attribut open. On vérifie s'il est absent, si tel est le cas, on masque les enfants de <details> excepté <summary> que l'on affiche. 

      var opened = $(this).attr("open");
      if(opened==undefined) {
        $(this).children().hide();
        $(this).children("summary").show();
      }
    });

  // Fermeture de la condition et de $(document).ready
  }
});

Le script établit le comportement dynamique, mais cela n'est pas suffisant pour la présentation : il faut encore ajouter l'icône et cela se passe du côté de la feuille de styles CSS. Rien de plus simple, grâçe à la pseudo-classe ::before et à la classe .open :

.html5_details > summary::before {
  content:"►"; margin-right:"5px";
}
.html5_details.open > summary::before {
  content:"▼"
}

Démonstration

Vous obtenez ainsi le même affichage que par défaut.

Il existe d'autres alternatives :

Propriétés des éléments

<details>

Propriété Détails
Modèles de contenu autorisés Un élément <summary> optionnel, suivi par du contenu de flux
Parents autorisés Tout élément pouvant contenir des éléments de flux, à l'exception de <a> et <button>
Omission de balise Les balises ouvrantes et fermantes sont obligatoires
Style par défaut details { display:block; }

<summary>

Propriété Détails
Modèles de contenu autorisés Contenu de phrasé.
Parents autorisés <details>
Omission de balise Les balises ouvrantes et fermantes sont obligatoires
Style par défaut summary { display:block; }

Ressources en ligne

Commentaires

Victor BRITO a dit le

En ce qui concerne la compatibilité entre navigateurs, tu aurais pu préciser qu'aucun navigateur à part ceux mentionnés ne prenait encore en charge ces deux éléments HTML 5.

holeraw a dit le

Je suppose que le comportement de ces éléments dans un form est identique.
Les données avec le details ouvert ou fermé seront les mêmes ?

Okko a dit le

@Victor : En toute logique ceux qui sont présents dans le tableau sont les seuls à prendre en charge ces éléments :) Et les absents non.

@holeraw : Oui tout à fait, tu peux effectuer le test en sélectionnant un des boutons radio.

gc-nomade a dit le

ah super,
perso, j'aurais préférer trouver le lien sur cet article dans le topic : http://forum.alsacreations.com/topic-2-59756-... plutôt que via mon mobile et twitter ;)

Torifan a dit le

Lorsque le contenu n'est pas déployé, est ce que Google risque de pénaliser à cause du texte caché ?

Vincent_ a dit le

Petite précision non négligeable ... selon qu'on habite le nord ou le sud de l'Alsace,nos spécialités se prononce différemment ! "mannele" dans le nord ou "mannala" dans le sud. Typiquement, à la Saint-Nicolas il est de coutume de se faire une soirée "mannala" oba". Au repas on se prépare un bol de lait, cacao ou café, et l'on mange des "mannala" nature ou coupés en deux et tartinés de confiture ou Mettwurst et des mandarines ... un repas sucré salé ... un vrai régal, une belle tradition ...

Felipe a dit le

@Vincent_ : les gérants d'Alsacreations.fr sont 2 et c'est à part égale 67/68 ;) L'auteure de l'article n'est pas originaire d'Alsace mais vit à Strasbourg comme tous mes collègues et moi-même, c'est donc "mannele" ;) Pour dew et sur blup.fr ce sera certainement différent :)
EDIT: j'aime bien ta date d'inscription !

Okko a dit le

@Torifan : Les robots de Google ne font que "lire" l'HTML, le contenu masqué est présent dans le code source de la page. Et Google ne sait pas que le contenu n'est pas déployé puisque tout se gère via CSS ou Javascript. De plus, pour que Google pénalise, le contenu doit être du SPAM et/ou être dénoncé. Et quand bien même vous êtes signalé et que vous ne spammez pas, la personne de Google se rendra vite compte qu'il n'y a aucun problème :)

AkaiKen a dit le

Un peu dommage qu'on ne puisse pas mettre de titre dans le <summary>, ça aurait été sympa, pour faire une sorte de table des matières interactive.
Article fort intéressant et bien écrit, by ze way, j'aime beaucoup le js non intrusif tout simple, qui permet d'émuler le comportement, merci !