Le DOM (Document Object Model) est la représentation de la page HTML que JavaScript voit. Pour rendre une page dynamique, il faut savoir sélectionner des éléments, lire leur contenu et le modifier. C'est la fondation de toute interactivité côté navigateur.
Quand le navigateur charge une page HTML, il en construit une représentation interne : un arbre d'objets, où chaque balise devient un nœud. Cet arbre est le DOM.
document
│
<html>
/ \
<head> <body>
│
<h1> <p> <button>
JavaScript peut lire et modifier cet arbre — et le navigateur met à jour l'affichage en conséquence. C'est ce qui rend les pages dynamiques.
L'objet global qui te donne accès à tout ça : document.
getElementByIdL'utilisation la plus simple et la plus rapide.
<p id="message">Salut !</p>
const p = document.getElementById("message");
Renvoie l'élément, ou null si aucun élément n'a cet id. Un id doit être unique dans la page.
querySelector / querySelectorAllPlus flexible : on utilise la syntaxe des sélecteurs CSS.
// Premier élément qui correspond
document.querySelector("#message"); // par id
document.querySelector(".surbrillance"); // par classe
document.querySelector("p"); // première balise <p>
document.querySelector("ul li.actif"); // sélecteur combiné
// Tous les éléments qui correspondent
document.querySelectorAll(".item"); // une NodeList (≈ tableau)
Quand utiliser quoi ?
getElementById — un seul élément précis, par son id. Le plus rapide.querySelector — un seul élément, sélecteur CSS quelconque.querySelectorAll — plusieurs éléments. Renvoie une NodeList qu'on parcourt comme un tableau.querySelector couvre 90% des cas dès qu'on dépasse les id.
Une fois qu'on a un élément, on peut accéder à son contenu :
const titre = document.querySelector("h1");
// Lire
console.log(titre.textContent); // le texte brut
console.log(titre.innerHTML); // le HTML interne (balises incluses)
// Modifier
titre.textContent = "Nouveau titre";
titre.innerHTML = "Titre <em>en italique</em>";
textContent ou innerHTML ?| Propriété | Effet |
|---|---|
textContent |
Texte brut. Les < et > deviennent du texte affiché. À privilégier. |
innerHTML |
Du HTML. Les balises sont interprétées. Puissant mais risqué si on injecte du texte venant de l'utilisateur (faille XSS). |
Règle simple : textContent par défaut. N'utilise innerHTML que si tu insères du HTML que tu as écrit toi-même, jamais du texte tapé par un utilisateur.
Les attributs HTML (src, href, alt, disabled…) sont accessibles directement sur l'élément.
const img = document.querySelector("#photo");
img.src = "chat.jpg";
img.alt = "Un chat";
img.width = 300;
Pour les attributs personnalisés (data-*), on passe par getAttribute / setAttribute :
const carte = document.querySelector(".carte");
carte.setAttribute("data-id", 42);
console.log(carte.getAttribute("data-id")); // "42"
Plutôt que de toucher au style directement, on bascule des classes définies dans le CSS — c'est plus propre et plus maintenable.
const bouton = document.querySelector("#valider");
bouton.classList.add("actif"); // ajoute la classe
bouton.classList.remove("actif"); // retire la classe
bouton.classList.toggle("actif"); // ajoute si absente, retire si présente
bouton.classList.contains("actif"); // true / false
/* dans le CSS */
.actif {
background-color: green;
color: white;
}
Pour la modification ponctuelle du style en JS (couleur en direct, transition…) voir l'article suivant sur le style.
Pour ajouter dynamiquement des éléments à la page :
// 1. Créer
const nouveauP = document.createElement("p");
nouveauP.textContent = "Paragraphe ajouté en JS";
nouveauP.classList.add("note");
// 2. Insérer dans le DOM
document.body.appendChild(nouveauP); // à la fin du body
Variantes :
parent.appendChild(enfant); // ajoute à la fin
parent.prepend(enfant); // ajoute au début
parent.insertBefore(enfant, autre); // insère avant un autre élément
enfant.remove(); // retire du DOM
<ul id="fruits"></ul>
const fruits = ["pomme", "banane", "cerise"];
const liste = document.getElementById("fruits");
for (let fruit of fruits) {
const li = document.createElement("li");
li.textContent = fruit;
liste.appendChild(li);
}
Trois fruits dans le tableau → trois <li> dans la page, sans toucher au HTML.
<input>Pour les formulaires, ce ne sont pas textContent ni innerHTML qu'on utilise, mais la propriété .value.
<input id="nom" type="text">
<button id="valider">OK</button>
const champ = document.getElementById("nom");
const bouton = document.getElementById("valider");
bouton.addEventListener("click", () => {
const saisie = champ.value;
console.log(`L'utilisateur a tapé : ${saisie}`);
});
.value fonctionne pour <input>, <textarea> et <select>. C'est la manière propre de récupérer une saisie utilisateur sur un vrai site (plutôt que prompt).
<head>
<script>
const titre = document.querySelector("h1");
titre.textContent = "Nouveau titre"; // ❌ titre est null !
</script>
</head>
<body>
<h1>Titre original</h1>
</body>
Le script s'exécute avant que <h1> n'existe dans le DOM → querySelector renvoie null → erreur en accédant à .textContent.
Deux solutions :
<script> à la fin du <body>, juste avant </body>. C'est le réflexe simple.DOMContentLoaded :document.addEventListener("DOMContentLoaded", () => {
const titre = document.querySelector("h1");
titre.textContent = "Nouveau titre";
});
document.getElementById("id"), querySelector("css"), querySelectorAll("css").textContent (sûr, par défaut) vs innerHTML (puissant, risqué)..src, .href, .value… ou getAttribute / setAttribute.classList.add / remove / toggle — préférer les classes CSS au style en dur.createElement + appendChild pour ajouter des éléments dynamiquement..value pour lire une saisie.<script> à la fin du <body> (ou utiliser DOMContentLoaded).