innerHTML en JavaScript : remplacer le contenu HTML d'un élément

innerHTML lit ou remplace le contenu HTML d'un élément : ce que l'écriture détruit au passage, le risque d'injection, et les solutions plus sûres.
3 min de lecture
Believemy logo

Remplir une zone de la page avec plusieurs éléments tient parfois en une ligne. C'est la promesse d'innerHTML, et la raison de sa popularité.

C'est aussi la propriété qui provoque le plus de dégâts silencieux, du champ vidé sans raison à la faille de sécurité ouverte sans le savoir.


Définition

innerHTML représente le contenu HTML d'un élément sous forme de chaîne. En lecture, elle rend le balisage des enfants. En écriture, le navigateur analyse la chaîne fournie, en construit des nœuds, et remplace tout le contenu existant.

JAVASCRIPT
const liste = document.querySelector("#panier");

liste.innerHTML = "<li>Clavier</li><li>Souris</li>";
console.log(liste.children.length);   // 2
console.log(liste.innerHTML);

La différence avec textContent est essentielle : ce dernier traite la chaîne comme du texte brut, les balises apparaissant alors telles quelles à l'écran.


Ce que l'écriture détruit

L'affectation ne modifie pas les nœuds existants, elle les jette et en fabrique de nouveaux. Tout ce qui était attaché aux anciens disparaît avec eux.

  • Les écouteurs posés par addEventListener() sur les enfants sont perdus.
  • Les champs de formulaire reviennent à leur valeur d'origine, y compris le texte déjà saisi.
  • Le focus et la position de défilement sont réinitialisés.

L'écriture element.innerHTML += "..." aggrave le cas : elle relit tout le contenu, le concatène, puis reconstruit l'ensemble. Sur une boucle de cent éléments, le travail est refait cent fois.


Le risque d'injection

Insérer une chaîne venue d'un visiteur revient à laisser cette personne écrire du HTML dans la page. C'est la faille dite d'injection de script, et elle permet de lire un jeton de session ou d'envoyer des données ailleurs.

JAVASCRIPT
const message = '<img src="x" onerror="alert(1)">';

zone.innerHTML = message;      // le code s'exécute
zone.textContent = message;    // le texte s'affiche, sans danger
Bon à savoir

Une balise <script> insérée par innerHTML ne s'exécute pas, c'est exact. Ce n'est pas une protection : les attributs d'événement comme onerror ou onload, eux, fonctionnent parfaitement.


Les alternatives

ÉcritureQuand l'employer
textContentDès qu'il s'agit de texte, donc la plupart du temps
insertAdjacentHTMLAjouter du balisage sans reconstruire l'existant
createElementConstruire des éléments dont on garde la référence


Questions fréquentes

Question

Est-ce plus rapide que de créer les éléments un à un ?

Pour une grosse insertion en une seule fois, l'analyse d'une chaîne est souvent compétitive. L'avantage s'inverse dès que la propriété est réécrite en boucle, et createElement() garde une référence sur chaque élément, ce qui évite de le rechercher ensuite.


Question

Comment ajouter sans tout reconstruire ?

insertAdjacentHTML reçoit une position et une chaîne, et insère sans toucher aux nœuds voisins. Les quatre positions acceptées sont beforebegin, afterbegin, beforeend et afterend, la dernière plaçant le contenu juste après l'élément.


Question

Comment insérer du HTML de façon sûre ?

La règle tient en une phrase : n'insérez que du balisage que vous avez écrit, jamais une chaîne venue d'un formulaire ou d'une interface. Les bibliothèques d'interface règlent la question autrement, React échappant le texte par défaut et réclamant une propriété au nom volontairement dissuasif pour insérer du HTML brut, un mécanisme détaillé dans la formation React.

Termes connexes

Découvrez notre glossaire JavaScript

Tous les mots de JavaScript expliqués simplement : mots-clés, objets natifs, méthodes, erreurs et concepts. Définitions claires et exemples qui tournent, pour apprendre et pour se dépanner.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.