Chapitre 3
Chapitre 03 — HTML : HyperText Markup Language
Chapitre 03 — HTML : HyperText Markup Language
Chapitre 03 — HTML : Cours Complet
1. Histoire et Évolution du HTML
1.1 Les Origines : SGML
Le HTML trouve ses racines dans le SGML (Standard Generalized Markup Language, ISO 8879:1986), un métalangage de balisage conçu pour la structuration de documents. SGML est extrêmement puissant mais complexe — sa spécification fait plus de 500 pages. Tim Berners-Lee, au CERN en 1989, avait besoin d'un format plus simple pour partager des documents scientifiques hypertextes.
Diagramme en cours de génération...
1.2 HTML 1.0 → HTML 4.01
- HTML 1.0 (1991-1993) : 18 balises, pas de standard formel
- HTML 2.0 (RFC 1866, 1995) : Premier standard IETF, formulaires basiques
- HTML 3.2 (1997) : Tables, applets, scripts, feuilles de style
- HTML 4.0 (1997) : Séparation structure/présentation, CSS encouragé, frames
- HTML 4.01 (1999) : Dernière révision majeure du W3C pendant 15 ans
1.3 La Guerre des Standards : XHTML vs HTML5
En 2000, le W3C pousse XHTML 1.0 (XML strict) pour forcer des documents bien formés. Mais l'approche XML est impopulaire auprès des développeurs. En 2004, Apple, Mozilla et Opera quittent le W3C et forment le WHATWG (Web Hypertext Application Technology Working Group), qui commence à travailler sur ce qui deviendra HTML5.
Le WHATWG Living Standard est aujourd'hui la spécification de référence unique.
2. HTML Sémantique
2.1 Qu'est-ce que le HTML Sémantique ?
Le HTML sémantique consiste à utiliser des balises qui décrivent le sens du contenu, pas son apparence.
| Balise | Rôle | Usage typique |
|---|---|---|
<header> | En-tête (section ou page) | Logo, navigation, titre |
<nav> | Navigation principale | Menus, tables des matières |
<main> | Contenu principal unique | Contenu central de la page |
<article> | Contenu autonome | Article de blog, commentaire |
<section> | Section thématique | Regroupement logique |
<aside> | Contenu tangentiel | Sidebar, notes, publicités |
<footer> | Pied de page | Copyright, liens, infos |
2.2 Pourquoi le HTML Sémantique ?
SEO : Google privilégie le contenu structuré. Les balises sémantiques aident les crawlers à comprendre la hiérarchie et la pertinence du contenu. Les rich snippets (étoiles, prix, recettes) n'existent que grâce au balisage sémantique.
Accessibilité : Les lecteurs d'écran utilisent les landmarks ARIA dérivés du HTML sémantique pour naviguer. Un utilisateur de NVDA ou JAWS peut sauter de <nav> à <main> à <footer> sans toucher la souris.
Maintenabilité : Un code sémantique est auto-documenté. Un développeur qui lit <article> comprend immédiatement qu'il s'agit d'un contenu autonome.
2.3 Structure Type d'un Document
<body>
<header>
<nav>
<ul>
<li><a href="/">Accueil</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header><h1>Mon Article</h1></header>
<section>
<h2>Introduction</h2>
<p>Contenu...</p>
</section>
<footer>Publié le 01/01/2026</footer>
</article>
<aside>
<h2>Articles connexes</h2>
<ul>...</ul>
</aside>
</main>
<footer>
<p>© 2026 Mon Site</p>
</footer>
</body>
3. Accessibilité Web : WCAG et ARIA
3.1 WCAG (Web Content Accessibility Guidelines)
Les WCAG sont organisés en 4 principes (POUR) :
| Principe | Description | Exemple |
|---|---|---|
| Perceivable | Perceptible | Alternatives textuelles, sous-titres |
| Operable | Utilisable | Navigation clavier, pas d'épilepsie |
| Understandable | Compréhensible | Langage clair, comportement prévisible |
| Robust | Robuste | Compatibilité avec les technologies d'assistance |
Trois niveaux de conformité : A (minimum), AA (standard légal), AAA (expert).
3.2 ARIA (Accessible Rich Internet Applications)
ARIA ne modifie pas le comportement d'un élément, seulement sa représentation dans l'arbre d'accessibilité.
Règles d'or ARIA :
- Ne pas utiliser ARIA si le HTML natif suffit :
<button>><div role="button"> - Les attributs ARIA doivent être dynamiquement maintenus :
aria-expandeddoit changer avec l'état - Ne pas cacher des éléments focusables :
aria-hidden="true"sur un élément focusable le rend invisible mais focusable → bug
<!-- Mauvais usage -->
<div role="button" onclick="submit()">Envoyer</div>
<!-- Bon usage -->
<button type="submit" aria-busy="false">Envoyer</button>
3.3 Landmarks
Les landmarks sont des régions de la page que les lecteurs d'écran exposent pour la navigation rapide. Le HTML sémantique les génère automatiquement :
| Rôle ARIA | Élément HTML | Usage |
|---|---|---|
banner | <header> (contexte body) | En-tête du site |
navigation | <nav> | Bloc de navigation |
main | <main> | Contenu principal |
complementary | <aside> | Contenu complémentaire |
contentinfo | <footer> (contexte body) | Infos de pied de page |
region | <section> (avec label) | Section thématique |
4. Formulaires HTML5
4.1 Nouveaux Types d'Input
HTML5 a introduit des types d'input qui améliorent l'expérience mobile et la validation :
<input type="email"> <!-- Validation email côté navigateur -->
<input type="url"> <!-- Validation URL -->
<input type="tel"> <!-- Clavier téléphone sur mobile -->
<input type="number"> <!-- Stepper, validation numérique -->
<input type="range"> <!-- Slider -->
<input type="date"> <!-- Date picker natif -->
<input type="color"> <!-- Color picker -->
<input type="search"> <!-- Champ de recherche (UI différente) -->
4.2 Validation Native
La validation native utilise des attributs sans JavaScript :
<form novalidate>
<label for="email">Email :</label>
<input
type="email"
id="email"
name="email"
required
minlength="5"
maxlength="100"
pattern="[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}"
/>
<span class="error" aria-live="polite"></span>
<button type="submit">Envoyer</button>
</form>
<script>
const form = document.querySelector('form');
const email = document.getElementById('email');
const errorSpan = document.querySelector('.error');
email.addEventListener('input', () => {
if (email.validity.valid) {
errorSpan.textContent = '';
errorSpan.hidden = true;
} else {
errorSpan.textContent = email.validationMessage;
errorSpan.hidden = false;
}
});
form.addEventListener('submit', (e) => {
if (!form.checkValidity()) {
e.preventDefault();
// Focus sur le premier champ invalide
form.querySelector(':invalid')?.focus();
}
});
</script>
4.3 Constraint Validation API
L'API expose ValidityState sur chaque élément de formulaire :
const state = input.validity;
// state.valueMissing → required non rempli
// state.typeMismatch → type email/URL invalide
// state.patternMismatch → regex non respectée
// state.tooLong → dépasse maxlength
// state.tooShort → ne fait pas minlength
// state.rangeUnderflow → valeur < min
// state.rangeOverflow → valeur > max
// state.stepMismatch → pas aligné sur step
// state.badInput → entrée non convertible
// state.customError → setCustomValidity() défini
// state.valid → tout est bon
Méthodes clés : checkValidity(), reportValidity(), setCustomValidity(message).
5. Attributs Globaux
Les attributs globaux s'appliquent à (presque) tous les éléments HTML :
| Attribut | Rôle |
|---|---|
class | Sélection CSS / JS |
id | Identifiant unique (ancre, target) |
lang | Langue du contenu (accessibilité, traduction) |
dir | Direction du texte (ltr, rtl, auto) |
hidden | Élément non affiché (display: none natif) |
inert | Élément inerte (ni cliquable, ni focusable, ni accessible) |
data-* | Données personnalisées accessibles via dataset |
slot | Attribution à un slot Shadow DOM |
spellcheck | Correction orthographique |
translate | Traduction automatique (yes/no) |
tabindex | Ordre de tabulation |
aria-* | Accessibilité |
role | Rôle ARIA |
inert : Le Nouvel Attribut Puissant
inert (supporté partout depuis 2022) rend un élément et ses descendants totalement inactifs :
- Pas de focus (ni clavier, ni programmatique)
- Pas de clics
- Pas d'événements
- Invisible dans l'arbre d'accessibilité
<!-- Modal pattern avec inert -->
<div id="modal-backdrop" inert>
<dialog open>
<h2>Modal</h2>
<button>Fermer</button>
</dialog>
</div>
6. HTML Templates et Shadow DOM
6.1 L'Élément <template>
Le <template> contient du HTML inactif (ni rendu, ni chargé) qui peut être instancié en JavaScript :
<template id="card-template">
<article class="card">
<img src="" alt="" loading="lazy">
<h3 class="card-title"></h3>
<p class="card-description"></p>
</article>
</template>
<script>
class CardList extends HTMLElement {
connectedCallback() {
const data = JSON.parse(this.getAttribute('data-items') || '[]');
const template = document.getElementById('card-template');
const fragment = template.content.cloneNode(true);
// Remplir le template...
this.appendChild(fragment);
}
}
</script>
6.2 Shadow DOM
Le Shadow DOM encapsule le style et la structure d'un composant :
class MonWidget extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host { display: block; border: 1px solid #ccc; padding: 1rem; }
:host([theme="dark"]) { background: #333; color: white; }
::slotted(p) { margin: 0; }
</style>
<slot name="title">Titre par défaut</slot>
<slot></slot>
`;
}
}
customElements.define('mon-widget', MonWidget);
Modes Open vs Closed
- open :
element.shadowRootaccessible depuis l'extérieur (testable, inspectable) - closed :
element.shadowRootretournenull(ne JAMAIS utiliser — casse l'accessibilité, le testing)
6.3 <slot> : Projection de Contenu
Les slots permettent de projeter du contenu de l'hôte dans le Shadow DOM :
<mon-widget>
<h2 slot="title">Mon Titre</h2>
<p>Contenu projeté dans le slot par défaut</p>
</mon-widget>
7. Web Components : Standard du Web
Les Web Components reposent sur 3 technologies :
Diagramme en cours de génération...
7.1 Lifecycle des Custom Elements
class MonElement extends HTMLElement {
constructor() {
super(); // Toujours appeler super() en premier
// Initialisation des états, Shadow DOM
}
// Appelé quand l'élément est ajouté au DOM
connectedCallback() {
// Setup : event listeners, fetching data
}
// Appelé quand l'élément est retiré du DOM
disconnectedCallback() {
// Cleanup : removeEventListener, annuler requêtes
}
// Appelé quand un attribut observé change
attributeChangedCallback(name, oldValue, newValue) {
// Réagir aux changements d'attributs
}
// Déclarer les attributs à observer
static get observedAttributes() {
return ['open', 'disabled', 'value'];
}
}
7.2 Bonnes Pratiques Web Components
- Toujours définir
observedAttributespour queattributeChangedCallbackfonctionne - Utiliser les
getters/setterspour synchroniser propriétés et attributs - Éviter
closedShadow DOM (casse l'accessibilité et le test) - Définir les Custom Elements avec des noms kebab-case (obligatoire)
- Ne pas étendre les éléments natifs (extends est déprécié)
8. SEO Meta : Open Graph, Twitter Cards, Schema.org
8.1 Open Graph (OG)
<meta property="og:title" content="Titre de la page">
<meta property="og:description" content="Description pour les réseaux sociaux">
<meta property="og:image" content="https://example.com/image.jpg">
<meta property="og:url" content="https://example.com/page">
<meta property="og:type" content="article">
<meta property="og:locale" content="fr_FR">
8.2 Twitter Cards
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@monsite">
<meta name="twitter:title" content="Titre">
<meta name="twitter:description" content="Description">
<meta name="twitter:image" content="https://example.com/image.jpg">
8.3 Schema.org avec JSON-LD
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Titre de l'article",
"author": {
"@type": "Person",
"name": "Jean Dupont"
},
"datePublished": "2026-07-28",
"description": "Résumé de l'article"
}
</script>
8.4 Structure de Données avec microdata
<article itemscope itemtype="https://schema.org/Article">
<h1 itemprop="headline">Titre</h1>
<p itemprop="description">Description</p>
<span itemprop="author" itemscope itemtype="https://schema.org/Person">
<span itemprop="name">Jean Dupont</span>
</span>
</article>
9. Performance des Scripts et Ressources
9.1 async vs defer
Diagramme en cours de génération...
<!-- BLOCKING : mauvais -->
<script src="heavy.js"></script>
<!-- ASYNC : ordre non garanti, exécution dès chargement -->
<script async src="analytics.js"></script>
<!-- DEFER : exécution ordonnée après parse HTML -->
<script defer src="app.js"></script>
<script defer src="vendor.js"></script>
9.2 Resource Hints
<!-- Preload : charger une ressource critique immédiatement -->
<link rel="preload" href="fonts/inter-var.woff2" as="font" crossorigin>
<!-- Prefetch : charger une ressource pour la page suivante -->
<link rel="prefetch" href="/blog/page-2.html">
<!-- Preconnect : établir connexion anticipée -->
<link rel="preconnect" href="https://api.example.com">
<!-- DNS-Prefetch : fallback pour navigateurs anciens -->
<link rel="dns-prefetch" href="https://api.example.com">
<!-- Prerender : pré-rendre toute la page suivante (lourd) -->
<link rel="prerender" href="/blog/page-2.html">
10. Bonnes Pratiques et Structure
10.1 Checklist de Base
-
<!DOCTYPE html>HTML5 - Attribut
langsur<html>(ex:<html lang="fr">) -
<meta charset="UTF-8">en premier dans<head> -
<meta name="viewport" content="width=device-width, initial-scale=1"> - Structure sémantique : header → main → footer
- Navigation accessible avec
<nav>etaria-current="page" - Images avec
altdescriptif (oualt=""pour décoratives) - Titres hiérarchiques : h1 → h2 → h3 (pas de sauts)
- Formulaires avec
<label>associé - Boutons =
<button>, pas<div>ou<a> - Liens avec texte descriptif (pas "cliquez ici")
- Validation HTML via W3C Validator
10.2 Erreurs des Juniors
Div-itis : L'utilisation excessive de <div> au lieu d'éléments sémantiques.
<!-- Junior -->
<div class="header">
<div class="nav">
<div class="nav-item">Accueil</div>
</div>
</div>
<!-- Senior -->
<header>
<nav>
<ul>
<li><a href="/">Accueil</a></li>
</ul>
</nav>
</header>
Mauvais nesting : Les éléments de bloc dans les éléments inline, les boutons dans les liens, etc.
<!-- INVALIDE : <p> ne peut pas contenir <div> -->
<p>Texte <div>bloc</div></p>
<!-- VALIDE -->
<div><p>Texte</p></div>
Oubli de l'attribut alt : Image sans alternative textuelle = inaccessible.
<!-- Mauvais : image décorative sans alt -->
<img src="decorative-bg.jpg">
<!-- Correct : alt vide pour décorative -->
<img src="decorative-bg.jpg" alt="" role="presentation">
<!-- Correct : alt descriptif pour image informative -->
<img src="logo.png" alt="Logo de l'entreprise Acme Inc.">
Heading skips : Sauter des niveaux de titre (h1 → h3).
<!-- Mauvais : h1 → h3 (skipping h2) -->
<h1>Titre principal</h1>
<h3>Sous-section</h3>
<!-- Correct -->
<h1>Titre principal</h1>
<h2>Sous-section</h2>
Boutons non focusables ou sans rôle :
<!-- Mauvais : pas focusable, pas accessible -->
<div onclick="submit()">Envoyer</div>
<!-- Correct -->
<button type="submit">Envoyer</button>
11. Standards et Validation
11.1 Living Standard vs W3C
Depuis 2021, le WHATWG Living Standard est la norme unique. Le W3C a cessé de publier des versions snapshot. Les navigateurs implémentent le Living Standard.
11.2 Validité HTML
Utiliser le W3C Validator :
# Linter HTML avec HTML-validate
npx html-validate src/**/*.html
# Vérification avec Nu HTML Checker
curl -H "Content-Type: text/html; charset=utf-8" \
--data-binary @index.html \
https://validator.w3.org/nu/?out=json
11.3 Polyfills et Progression
Pour les fonctionnalités modernes dans les navigateurs anciens :
<script>
if (!('inert' in HTMLElement.prototype)) {
// Charger le polyfill inert
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/wicg-inert@3/dist/inert.min.js';
document.head.appendChild(script);
}
</script>
12. Internationalisation (i18n)
<html lang="fr" dir="ltr">
<head>
<meta charset="UTF-8">
</head>
<body>
<!-- Attribut lang sur chaque élément de langue différente -->
<p>Ceci est en français.</p>
<p lang="en">This is in English.</p>
<!-- Attr dir pour les langues RTL -->
<p lang="ar" dir="rtl">مرحبا بالعالم</p>
</body>
</html>
Résumé
Le HTML moderne est puissant et expressif. La sémantique, l'accessibilité et la performance ne sont pas optionnelles — ce sont des piliers du développement web professionnel. Un ingénieur front-end maîtrise :
- La structure sémantique du document
- L'accessibilité (WCAG AA minimum)
- Les formulaires (validation native + API)
- Les Web Components (Custom Elements + Shadow DOM)
- Le SEO technique (Open Graph, Schema.org)
- La performance (async/defer, preload)
- L'internationalisation