English

Les soupes de div, les pavés d'or qui mènent à l'enfer numérique

Table des matières

Le symptôme invisible

Ouvre les outils de développement de n'importe quel site. Déplie le DOM. Compte les <div>.

Sur un site moyen, tu en trouveras des centaines. Pas forcément à la place des éléments sémantiques. La plupart des projets utilisent un <header>, quelques <button>, un <form>. Le problème est plus sournois : ce sont les <div> qui s'accumulent autour. Trois niveaux de wrappers pour centrer un bouton. Une <div class="content-wrapper"> qui double un <main> déjà présent. Une <div class="form-group"> là où un <fieldset> suffirait. Des <div> imbriquées dans des <div> imbriquées dans des <div>, pour porter des classes CSS que les éléments sémantiques auraient pu porter eux-mêmes.

Visuellement, tout fonctionne. Les couleurs sont là, la mise en page tient, les animations tournent. Le client est content. L'utilisateur qui voit l'écran ne remarque rien.

Mais la <div> ne dit rien. C'est un conteneur vide, sans rôle, sans sémantique, sans signification. Pour un lecteur d'écran, une <div> n'existe pas. Pour un moteur de recherche, c'est du bruit. Pour le navigateur, c'est un nœud de plus à construire, à peindre, à recycler.

Cet article détaille ce que chaque <div> inutile coûte. En accessibilité, en performance, en SEO, en GEO. Et montre quels éléments HTML existent déjà pour faire le travail.

Le HTML qui existe déjà

Le HTML compte plus de 100 éléments. La plupart des projets en utilisent une dizaine, et entourent chacun d'eux de <div> qui n'apportent rien. Voici les éléments que la <div> remplace ou étouffe le plus souvent, et ce qui se perd à chaque fois.

La structure de la page

Éléments sémantiques pour la structure de la page
Au lieu de…Utilise…Ce que tu gagnes
<div class="header"><header>Le lecteur d'écran saute directement au header
<div class="nav"><nav>Navigation identifiable, listée automatiquement
<div class="main"><main>Contenu principal, un seul par page
<div class="footer"><footer>Informations de pied de page
<div class="sidebar"><aside>Contenu complémentaire pouvant être retiré sans perdre d'informations
<div class="section"><section>Région thématique (landmark seulement si elle a un nom accessible)
<div class="article"><article>Contenu autonome, redistribuable

La plupart de ces éléments créent des landmarks, des points de repère que le lecteur d'écran annonce et que l'utilisateur peut atteindre en un raccourci clavier. Trois nuances : <header> et <footer> ne sont des landmarks qu'au niveau de la page (pas imbriqués dans un <article> ou une <section>), <section> n'en devient un que si elle porte un nom accessible (aria-label ou aria-labelledby), et <article> n'en est pas un, sa valeur est ailleurs : il délimite un contenu autonome que les technologies d'assistance savent annoncer. Chaque <div> qui les remplace supprime un repère. Et chaque <div> qui les enrobe ajoute un nœud vide entre l'utilisateur et l'information.

Les éléments interactifs

Éléments sémantiques interactifs
Au lieu de…Utilise…Ce que tu gagnes
<div onclick="..."><button>Focus clavier, rôle annoncé, Entrée + Espace natifs
<div class="link"><a href="...">Focus clavier, rôle annoncé, historique navigateur
<div class="input"><input>Validation native, autocomplete, types spécialisés
<div class="select"><select>Liste déroulante native, clavier, mobile optimisé

Une <div onclick> ne reçoit pas le focus clavier. Elle n'est pas annoncée comme bouton. Elle ne répond pas à Entrée ni à Espace. Pour la rendre fonctionnelle, il faut ajouter role="button", tabindex="0", un gestionnaire keydown, et un style de focus. Exactement le genre de bricolage ARIA qu'il vaut mieux éviter. Quatre attributs et du JavaScript pour réinventer ce que <button> fait en six caractères.

Les éléments oubliés

Éléments HTML souvent oubliés
ÉlémentCe qu'il faitCe qu'on retrouve à la place
<details> / <summary>Accordéon natif, aucun JS nécessaireUne <div> + JS + ARIA
<dialog>Modale native, piège de focus intégréUne <div> + overlay + JS + ARIA
<figure> / <figcaption>Image ou bloc avec légende associéeUne <div> + un <p> déconnectés
<time>Date/heure lisible par les machinesUn <span> sans sémantique
<address>Coordonnées de contactUne <div> ou un <p>
<mark>Texte mis en surbrillance (résultat de recherche)Un <span> avec du CSS
<fieldset> / <legend>Groupe de champs avec étiquetteDes <div> imbriqués
<blockquote> / <cite>Citation avec attributionUne <div> en italique
<abbr>Sigle avec titre completRien, ou un <span> avec un title
<code> / <pre>Code sourceUne <div> avec une police monospace
<dl> / <dt> / <dd>Liste de définition, glossaire, récapitulatif clé-valeurDes <div> avec des <span>

Chacun de ces éléments porte une sémantique que le navigateur, le lecteur d'écran, le moteur de recherche et le LLM exploitent. Chaque <div> qui les remplace efface cette sémantique.

Anatomie d'une soupe

Prenons une page courante : un header, une navigation, un contenu avec un titre, un footer. Le HTML sémantique est là — mais enfoui.

real-world.html
<!-- Ce à quoi ressemblent la plupart des codebases -->
<div class="page-wrapper">
  <div class="top-container">
    <header>
      <div class="header-inner">
        <div class="logo-wrapper">
          <a href="/">Logo</a>
        </div>
        <div class="nav-wrapper">
          <nav>
            <div class="nav-inner">
              <div class="menu-item"><a href="/">Accueil</a></div>
              <div class="menu-item"><a href="/about">À propos</a></div>
            </div>
          </nav>
        </div>
      </div>
    </header>
  </div>
  <div class="content-container">
    <div class="content-inner">
      <main>
        <div class="title-wrapper">
          <h1>Bienvenue</h1>
        </div>
        <div class="text-block">
          <p>Premier paragraphe.</p>
        </div>
        <div class="text-block">
          <p>Deuxième paragraphe.</p>
        </div>
      </main>
    </div>
  </div>
  <div class="footer-container">
    <footer>
      <div class="footer-inner">
        <p>© 2026</p>
      </div>
    </footer>
  </div>
</div>
semantic.html
<!-- La même page, sans le bruit -->
<header>
  <a href="/">Logo</a>
  <nav>
    <ul>
      <li><a href="/">Accueil</a></li>
      <li><a href="/about">À propos</a></li>
    </ul>
  </nav>
</header>
<main>
  <h1>Bienvenue</h1>
  <p>Premier paragraphe.</p>
  <p>Deuxième paragraphe.</p>
</main>
<footer>
  <p>© 2026</p>
</footer>

Le premier exemple n'est pas une caricature. C'est ce que produisent la plupart des projets. Des éléments sémantiques noyés dans des couches de wrappers CSS. Le <header> est là, le <main> est là, le <h1> est là. Mais entre l'utilisateur et ces repères, il y a 15 nœuds de <div> qui ne disent rien.

Le second fait la même chose en 10 lignes. Zéro <div>. Les éléments sémantiques portent eux-mêmes leurs styles.

Ce que ça change pour un lecteur d'écran

Les navigateurs modernes sont intelligents : ils filtrent les <div> sans sémantique de l'arbre d'accessibilité pour réduire le bruit. Un <div class="wrapper"> autour d'un <button> n'empêche pas le lecteur d'écran de trouver le bouton.

Mais si le navigateur les ignore, c'est bien qu'ils ne servent à rien. Tout ce qu'une <div> wrapper fait, porter une classe, recevoir un display: flex, définir une marge, un élément sémantique le fait aussi. Un <nav class="main-nav"> accepte les mêmes propriétés CSS qu'un <div class="nav-wrapper">. Un <header> peut être un conteneur flex exactement comme une <div class="header-container">. Le navigateur ne fait pas la différence côté rendu. Mais il fait la différence côté accessibilité.

Et ce filtre ne résout pas le fond du problème. Ce qui manque dans une soupe de <div>, ce ne sont pas les nœuds en trop, ce sont les repères en moins.

71,6 % des utilisateurs de lecteurs d'écran naviguent par titres. 31,8 % utilisent fréquemment les landmarks. Ce sont les deux méthodes principales pour se repérer dans une page. J'en parle en détail dans Les lecteurs d'écran ne lisent pas comme toi.

Quand une <div class="section-title"> remplace un <h2>, c'est un titre qui disparaît de la liste de navigation. Quand une <div class="sidebar"> remplace un <aside>, c'est un landmark qui n'existe plus. L'utilisateur perd un raccourci vers l'information et il n'y a aucun moyen de le savoir sans inspecter le code.

Une étude de 2007 portant sur 100 utilisateurs aveugles a mesuré qu'ils perdent en moyenne 30,4 % de leur temps à cause de situations frustrantes, toutes causes confondues, et la structure confuse des pages en est la première. Des repères manquants, des contenus mal étiquetés, des structures imprévisibles.

Tu peux voir l'arbre d'accessibilité toi-même : dans Chrome, ouvre les DevTools → onglet Elements → panneau Accessibility. C'est une radiographie de ce que ton HTML dit vraiment, indépendamment de ce qu'il montre.

Ce que ça coûte

En réalité, rares sont les sites construits uniquement en <div>. La plupart utilisent quelques éléments sémantiques. Un <header> ici, un <button> là. Le problème est plus insidieux : ce sont les <div> qui s'accumulent autour, à l'intérieur, entre les éléments utiles. Trois niveaux de wrappers pour un bouton. Une <div class="form-group"> là où un <fieldset> suffirait. Une <div class="content"> qui double un <main> déjà présent.

Le site ne s'effondre pas. Il fonctionne. Mais chaque <div> superflue dilue la sémantique, alourdit le DOM et ajoute du bruit sur quatre fronts.

Accessibilité

Un lecteur d'écran navigue par repères : titres, landmarks, liens, boutons. Dans une soupe de <div>, il n'y a aucun repère. L'utilisateur doit parcourir chaque nœud du DOM, un par un, de haut en bas. Sur une page de 200 nœuds, c'est l'équivalent de lire un livre sans table des matières, sans chapitres et sans numéros de pages.

Les éléments interactifs en <div> sont invisibles au clavier. Un utilisateur qui ne peut pas utiliser la souris, et ils sont nombreux, ne peut tout simplement pas interagir avec ton site.

Performance

Chaque <div> superflue est un nœud supplémentaire dans le DOM. Plus le DOM est profond, plus le navigateur met de temps à calculer les styles, le layout et le rendu. Google Lighthouse déclenche un avertissement au-delà de 800 éléments et une erreur au-delà de 1 400, avec une profondeur maximale recommandée de 32 niveaux. D'après le Web Almanac 2022, le 90e percentile des pages web approche déjà les 2 000 éléments (1 832 sur mobile, 2 023 sur desktop), pour une médiane à 653.

Et chaque <div> interactive faite maison embarque du JavaScript que l'élément natif n'aurait pas eu besoin. Un <dialog> natif ouvert avec showModal() gère le piège de focus tout seul. Une <div> modale a besoin d'un script, d'un overlay, et de plusieurs gestionnaires d'événements. Plus de code, plus de poids, plus de bugs.

SEO

Google utilise la sémantique HTML pour comprendre la structure d'une page. Un <h2> est un titre. Un <nav> est une navigation. Un <article> est un contenu autonome. Une <div> n'est rien. Google peut s'en sortir sans sémantique, mais le HTML sémantique lui facilite le travail.

Les featured snippets, les résultats enrichis, les extraits en position zéro, tous s'appuient sur une structure que Google peut interpréter sans ambiguïté. Une hiérarchie de titres claire, des listes, des tableaux. Plus la structure est explicite, plus Google a de matière pour générer ces résultats.

GEO

Les LLM ne classent pas des pages. Ils sélectionnent des passages à citer. Et pour découper une page en passages, ils s'appuient sur la structure : titres, sections, articles, listes. Sans ces repères, le LLM voit un flux de texte indifférencié. Plus difficile à segmenter, plus difficile à citer, plus facile à ignorer.

Un <h2> délimite un sujet. Un <ul> structure une énumération. Un <article> isole un contenu autonome. Une <div> ne fait rien de tout ça. Et quand le LLM doit choisir entre une page structurée et une soupe de <div>, le résultat est prévisible.

J'en parle en détail dans Comment le GEO force l'accessibilité web : les moteurs génératifs favorisent les contenus structurés, sourcés et lisibles par les machines. La soupe de <div> est l'exact opposé.

Quatre axes, un seul symptôme. La soupe de <div> n'est pas un problème d'accessibilité. C'est un problème de qualité qui se manifeste partout.

Pour voir ce que ça donne concrètement, j'ai pris une vraie card produit d'un site e-commerce. 87 éléments dont 27 <div>, 17 <span>, 5 <i>, et seulement 6 balises sémantiques, et je l'ai réécrite sans aucune <div>. Même rendu, zéro compromis visuel. Le détail étape par étape est dans Autopsie d'une card produit.

Alors, quand utiliser une <div> ?

Un seul cas est dans la spécification : à l'intérieur d'un <dl>, une <div> peut grouper une paire <dt> / <dd>. C'est le seul endroit où la <div> apporte une structure que le HTML ne fournit pas autrement. Le GOV.UK Design System l'utilise dans son composant Summary List, et c'est un des rares exemples où la <div> est la bonne réponse.

En dehors de ce cas, chaque <div> est un aveu : je ne sais pas faire autrement. Pas « il n'existe rien d'autre » — parce qu'il existe toujours quelque chose. Un <header>, un <main>, un <footer>, un <section>, un <fieldset>, un <ul>, un <figure>. Plus de 100 éléments, chacun avec un rôle, un comportement et une sémantique. L'élément HTML qui convient existe. Il suffit de le chercher.

La <div> n'est pas un ennemi. C'est un raccourci. Et chaque raccourci a un coût. En accessibilité, en performance, en SEO, en GEO. Ce coût, tu le connais maintenant.

Sources