Accueil / Articles

Six fonctionnalités natives d’HTML qui remplacent les bibliothèques UI JavaScript courantes

Découvrez comment les popover, les détails exclusifs, les dialogues, le Declarative Shadow DOM, fetchpriority et datalist remplacent le JavaScript personnalisé, ainsi que les limites qui subsistent pour chacun d’eux.

Éditeur : REACTAPP.TOP6 min de lecture1277 mots

Sources: HTML Features in 2026 That Most Devs Don’t Know Exist

Pendant des années, HTML fournissait la structure tandis que JavaScript gérait tout le comportement : un modal nécessitait une bibliothèque React, une tooltip impliquait Popper.js ou Tippy, et les composants générés côté serveur exigeaient des scripts personnalisés. Entre-temps, le WHATWG HTML Living Standard ainsi que les moteurs de navigateur ont ajouté des éléments natifs qui couvrent de nombreux cas avec seulement quelques attributs, réduisant ainsi le code générique et la taille des fichiers tout en assurant par défaut une bonne accessibilité. Ce guide présente six de ces éléments, le markup requis pour chacun, ainsi que les cas où CSS ou JavaScript restent nécessaires. Vérifiez la compatibilité des navigateurs de votre public avant d’intégrer des solutions de fallback.

1. Popovers avec l’attribut popover

Les aides contextuelles et les menus impliquaient traditionnellement des luttes avec les contextes d’empilement z-index ainsi que la nécessité d’écrire manuellement des écouteurs pour les clics en dehors de l’élément. Avec l’API Popover, tout élément portant l’attribut popover est placé en premier plan lorsqu’il est ouvert, au-dessus de tout le contenu normal, indépendamment de sa valeur z-index. Un bouton dont l’attribut popovertarget indique l’id de l’élément permet de l’activer/désactiver :

<!-- The Trigger -->
<button popovertarget="my-menu">Toggle Menu</button>

<!-- The Popover Content -->
<div id="my-menu" popover>
  <p>I am natively managed! Press ESC or click outside to close me.</p>
</div>

Sans aucun JavaScript, on obtient :

  • Activation/désactivation déclarative : le bouton ouvre et ferme la fenêtre contextuelle.
  • Fermeture simple : un clic en dehors ou la touche Escape suffisent pour la fermer. Cela s’applique au mode par défaut popover="auto" ; avec popover="manual", c’est à l’utilisateur de décider du moment de la fermeture.
  • Aucune lutte d’empilement : la fenêtre contextuelle ouverte s’affiche en premier plan, au-dessus de tout le reste.

Deux limites : l’API contrôle la visibilité et le empilement, mais pas l’emplacement ; par conséquent, ancrer un menu à son déclencheur nécessite toujours du CSS (positionnement classique ou le positionnement par ancrage, moins largement supporté). De plus, un popover n’est pas modal et ne retient pas l’attention de l’utilisateur sur lui, il faut donc utiliser dialog pour les confirmations.

2. Accordeons exclusifs avec détails et nom

details et summary permettent depuis longtemps de créer des sections pliables sans JavaScript. La nouveauté récente : les éléments details partageant un name forment un groupe dans lequel seul l’un peut être ouvert, à l’instar d’un accordon classique.

<details name="faq">
  <summary>What is modern HTML?</summary>
  <p>A living standard evolving directly inside browser engines.</p>
</details>

<details name="faq">
  <summary>Do I still need JavaScript?</summary>
  <p>Much less of it than you used to!</p>
</details>

<details name="faq">
  <summary>Is this supported natively?</summary>
  <p>Yes, across all major modern browser engines.</p>
</details>

Ouvrir une question ferme tout autre élément ouvert ayant name="faq", sans nécessiter de listeners, d’hooks d’état ou de modification de classe. Les navigateurs ne prenant pas en charge name permettent simplement l’ouverture de plusieurs éléments, ce qui constitue un fallback fonctionnel.

3. Modaux accessibles avec dialog et ::backdrop

Les superpositions personnalisées en div échouent fréquemment aux audits d’accessibilité, car un modal correct doit conserver le focus à l’intérieur de lui-même, bloquer la page derrière et restituer le focus au déclencheur par la suite. L’élément dialog gère cela. Ci-dessous, un formulaire avec method="dialog" ferme le dialogue au clic sur n’importe quel bouton, et la value du bouton cliqué devient la returnValue du dialogue :

<dialog id="user-modal">
  <h2>Confirm Action</h2>
  <p>Are you sure you want to delete this repository?</p>

  <!-- A form inside a dialog with method="dialog" closes it automatically -->
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="confirm">Delete</button>
  </form>
</dialog>

<button onclick="document.getElementById('user-modal').showModal()">
  Open Modal
</button>

L’overlay atténué correspond au pseudo-élément ::backdrop, stylisé avec du CSS simple :

/* Styling the native browser backdrop */
dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
}

showModal() place la boîte de dialogue en premier plan, rend le reste de la page inerte, maintient le focus à l’intérieur et permet d’utiliser la touche Échap pour la fermer ; lors de la fermeture, les navigateurs actuels restituent le focus à l’élément qui était précédemment en focus. En revanche, show() l’ouvre de manière non modale sans ces protections. Dans React, appelez showModal() via un ref plutôt qu’avec un onclick inline.

4. Composants Web générés côté serveur avec Shadow DOM déclaratif

Auparavant, le Shadow DOM nécessitait du JavaScript côté client (element.attachShadow({ mode: 'open' })), de sorte que les composants Web générés côté serveur ou statiquement n’avaient pas de balisage encapsulé avant l’exécution des scripts, ce qui provoquait des affichages non stylisés et des changements de mise en page. Le Shadow DOM déclaratif résout ce problème : un template contenant shadowrootmode à l’intérieur de l’élément hôte décrit l’arbre d’ombre en HTML :

<user-card>
  <template shadowrootmode="open">
    <style>
      /* Styles here stay encapsulated inside this component */
      h3 { color: #3b82f6; font-family: sans-serif; }
    </style>

    <h3>Jane Doe</h3>
    <p>Senior Frontend Engineer</p>
  </template>
</user-card>

Le parseur convertit le modèle en une racine d’ombre sur user-card avant l’affichage, de sorte que les styles et le markup ciblés apparaissent dès la première mise à l’écran. Précaution : cela ne se produit qu’au cours du parsing HTML. Le markup inséré ultérieurement via innerHTML ne crée pas de racine d’ombre ; l’insertion dynamique nécessite des API telles que setHTMLUnsafe(), il convient donc de vérifier la compatibilité actuelle.

5. Priorisation des ressources critiques avec fetchpriority

loading="lazy" ainsi que async/defer ne permettent pas de déterminer quelles ressources initiales sont les plus importantes. Lorsqu’il y a plusieurs images en haut de la page, l’image principale située derrière votre Largest Contentful Paint (LCP) doit avoir la priorité sur les badges et les icônes. fetchpriority fournit cette indication au planificateur réseau :

<!-- Critical LCP Image: Load this immediately! -->
<img src="hero-banner.webp" fetchpriority="high" alt="Product Hero">

<!-- Lower priority images -->
<img src="avatar.webp" fetchpriority="low" alt="User avatar">

<!-- Critical JavaScript bundle -->
<script src="app.js" fetchpriority="high"></script>

Cela peut améliorer les Core Web Vitals sans toucher à la logique de l’application. Il s’agit d’une suggestion, pas d’une instruction, et marquer de nombreux ressources comme high annule l’avantage. De plus, ne chargez jamais en différé l’image LCP.

6. Suggestions natives avec datalist

De nombreux projets ajoutent un composant d’autocomplétion lourd uniquement pour suggérer des valeurs tout en permettant un texte libre. datalist fait cela nativement : reliez-le via l’attribut list de l’élément d’entrée, et ses options deviennent des suggestions.

<label for="framework">Choose or type a framework:</label>
<input list="frameworks" id="framework" name="framework" placeholder="e.g. Next.js">

<datalist id="frameworks">
  <option value="Next.js"></option>
  <option value="SvelteKit"></option>
  <option value="Nuxt.js"></option>
  <option value="Astro"></option>
  <option value="Remix"></option>
</datalist>

Le navigateur affiche et filtre la liste, gère la navigation au clavier et respecte l’apparence de la plateforme. Le compromis réside dans le contrôle : le stylisme est minimal, le comportement diffère selon les navigateurs et les appareils mobiles, et des options avancées sont impossibles. Idéal pour des champs simples de type « choisir ou taper » ; un combobox personnalisé nécessite néanmoins un composant.

Fonctionnalité native versus l’ancienne approche

  • Aides contextuelles et menus : utilisation de popover à la place d’une bibliothèque de positionnement, ainsi que gestion des clics en dehors de l’élément et du raccourci Escape (le positionnement lui-même provient toujours de CSS).
  • Accordeons : éléments details partageant un name plutôt que de la logique d’état et de basculement en JavaScript.
  • Modaux : utilisation de dialog avec showModal() et ::backdrop à la place d’une superposition personnalisée nécessitant une gestion manuelle du focus.
  • Composants générés côté serveur encapsulés : utilisation de template shadowrootmode plutôt que d’appels à attachShadow() réservés au client uniquement.
  • Priorités de chargement : utilisation de fetchpriority à la place de techniques manuelles de préchargement ou d’un ordre de chargement déterminé par des scripts.
  • Suggestions d’entrée : utilisez datalist plutôt qu’un widget d’autocomplétion personnalisé pour les cas simples.
  • Pour une vue d’ensemble plus large des fonctionnalités de la plateforme qui peuvent remplacer les dépendances, consultez notre article sur les APIs natives du navigateur remplaçant les packages npm populaires.

    Points clés

    • Les navigateurs intègrent désormais des fonctionnalités qui nécessitaient auparavant des bibliothèques, souvent avec un gestionnaire de focus et la possibilité de fermer avec la touche Escape.
    • Le natif ne signifie pas complet : les popovers nécessitent du CSS pour leur positionnement, datalist offre peu de possibilités de personnalisation visuelle, et le Declarative Shadow DOM ne fonctionne qu’au moment du parsing.
    • Au préalable d’ajouter une dépendance UI, vérifiez si un élément ou un attribut suffit à répondre réellement aux besoins sur les navigateurs que vous prenez en charge.

    Lectures complémentaires