HTML HyperText Markup Language
Toutes les balises, attributs et exemples essentiels pour structurer vos pages web.
Structure minimale requise pour toute page HTML5. Le <!DOCTYPE html> indique au navigateur d'utiliser le mode standard HTML5.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Titre de la page</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>Bonjour monde !</h1>
<script src="script.js"></script>
</body>
</html>
Les commentaires ne sont pas affichés dans le navigateur. Utiles pour documenter ou désactiver temporairement du code.
<!-- Ceci est un commentaire sur une ligne -->
<!--
Ceci est un commentaire
sur plusieurs lignes
-->
<h1> à <h6>6 niveaux de titres. Un seul <h1> par page (important pour le SEO). Les titres définissent la hiérarchie du contenu.
<h1>Titre principal (unique sur la page)</h1>
<h2>Titre de section</h2>
<h3>Sous-section</h3>
<h4>Sous-sous-section</h4>
<h5>Titre de niveau 5</h5>
<h6>Titre de niveau 6</h6>
<p>, saut de ligne <br>, séparateur <hr><p> est un bloc de texte. <br /> force un retour à la ligne dans un même bloc. <hr /> trace une ligne de séparation horizontale.
<p>Ceci est un paragraphe de texte.</p>
<p>Première ligne.<br />Deuxième ligne dans le même paragraphe.</p>
<hr />
<p>Texte après la ligne de séparation.</p>
| Balise | Rendu | Signification |
|---|---|---|
<strong> | texte | Important — gras sémantique |
<em> | texte | Emphase — italique sémantique |
<u> | texte | Souligné (non-sémantique, préférer CSS) |
<s> | Barré — texte non pertinent | |
<mark> | texte | Texte surligné (mise en valeur) |
<small> | texte | Texte plus petit (mentions légales) |
<sub> | H2O | Indice (exposant bas) |
<sup> | x2 | Exposant (exposant haut) |
<abbr> | HTML | Abréviation avec infobulle au survol |
<cite> | titre œuvre | Titre d'une œuvre citée |
<q> | citation courte | Citation courte inline avec guillemets auto |
<blockquote> | — | Citation longue en bloc |
<p>Ce mot est <strong>important</strong> et celui-ci est <em>en italique</em>.</p>
<p>Le prix <s>50€</s> est maintenant <mark>30€</mark>.</p>
<p>Formule : H<sub>2</sub>O, exposant : x<sup>2</sup></p>
<p><abbr title="Cascading Style Sheets">CSS</abbr> gère le style.</p>
<blockquote cite="https://example.com">
Ceci est une longue citation provenant d'une source externe.
</blockquote>
<code> <pre> <kbd><code> pour afficher du code inline. <pre> préserve les espaces et sauts de ligne. <kbd> représente une touche clavier.
<p>Utilisez <code>console.log()</code> pour déboguer.</p>
<pre>
function hello() {
return "monde";
}
</pre>
<p>Appuyez sur <kbd>Ctrl</kbd> + <kbd>C</kbd> pour copier.</p>
<a> — tous les usages| Attribut | Valeur | Description |
|---|---|---|
href | URL / #id / chemin | Destination du lien |
target | _blank / _self | Où ouvrir le lien (nouvel onglet / même onglet) |
rel | noopener noreferrer | Sécurité avec target="_blank" |
download | nom-fichier | Force le téléchargement au lieu d'ouvrir |
title | texte | Infobulle au survol |
<!-- Lien externe (sécurisé) -->
<a href="https://google.com" target="_blank" rel="noopener noreferrer">Google</a>
<!-- Lien interne -->
<a href="about.html">À propos</a>
<!-- Ancre (scroll vers un id) -->
<a href="#contact">Aller au contact</a>
<!-- Email -->
<a href="mailto:hello@exemple.fr">Envoyer un email</a>
<!-- Téléphone -->
<a href="tel:+33612345678">06 12 34 56 78</a>
<!-- Téléchargement -->
<a href="fichier.pdf" download="mon-fichier.pdf">Télécharger le PDF</a>
<!-- Cible de l'ancre -->
<section id="contact">...</section>
<img>L'attribut alt est obligatoire pour l'accessibilité et le SEO. Laisser vide (alt="") pour les images décoratives.
| Attribut | Description |
|---|---|
src | Chemin ou URL de l'image |
alt | Texte alternatif (obligatoire) |
width / height | Dimensions en px (évite le layout shift) |
loading="lazy" | Chargement différé (performance) |
srcset | Images responsives (plusieurs tailles) |
sizes | Taille d'affichage selon le viewport |
<!-- Image simple -->
<img src="photo.jpg" alt="Description de l'image" width="800" height="600" />
<!-- Image responsive avec srcset -->
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
alt="Photo responsive"
loading="lazy"
/>
<!-- Image avec légende -->
<figure>
<img src="graphique.png" alt="Graphique des ventes 2024" />
<figcaption>Évolution des ventes sur l'année 2024</figcaption>
</figure>
<!-- Image décoractive (pas d'alt textuel) -->
<img src="decoration.svg" alt="" />
<picture> — images adaptatives avancéesPermet de servir différents formats (WebP, AVIF) ou différentes images selon les breakpoints. Le navigateur choisit la première source compatible.
<picture>
<!-- Format moderne (si supporté) -->
<source srcset="image.avif" type="image/avif" />
<source srcset="image.webp" type="image/webp" />
<!-- Image mobile -->
<source srcset="image-mobile.jpg" media="(max-width: 600px)" />
<!-- Fallback obligatoire -->
<img src="image.jpg" alt="Description" />
</picture>
<ul>, ordonnée <ol> et de définitions <dl><!-- Liste non ordonnée (puces) -->
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<!-- Liste ordonnée (numérotée) -->
<ol>
<li>Ouvrir le terminal</li>
<li>Taper npm install</li>
<li>Lancer npm start</li>
</ol>
<!-- Attributs de <ol> -->
<ol start="5" reversed type="A">
<li>Item E (part de 5 en descendant, lettres)</li>
<li>Item D</li>
</ol>
<!-- Liste de définitions -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language — structure des pages web</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets — mise en forme</dd>
</dl>
<!-- Liste imbriquée -->
<ul>
<li>Frontend
<ul>
<li>HTML</li>
<li>CSS</li>
</ul>
</li>
<li>Backend</li>
</ul>
| Balise | Rôle |
|---|---|
<table> | Conteneur du tableau |
<caption> | Titre du tableau (accessibilité) |
<thead> | En-tête du tableau |
<tbody> | Corps principal |
<tfoot> | Pied de tableau |
<tr> | Ligne (table row) |
<th> | Cellule d'en-tête (gras, centré) |
<td> | Cellule de données |
colspan="n" | Fusionner n colonnes |
rowspan="n" | Fusionner n lignes |
scope="col/row" | Portée de l'en-tête (accessibilité) |
<table>
<caption>Résultats des élèves</caption>
<thead>
<tr>
<th scope="col">Nom</th>
<th scope="col">Note</th>
<th scope="col">Mention</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>18/20</td>
<td>Très bien</td>
</tr>
<tr>
<td>Bob</td>
<td colspan="2">Absent</td> <!-- Fusionne 2 colonnes -->
</tr>
</tbody>
<tfoot>
<tr>
<td>Moyenne</td>
<td>15/20</td>
<td>—</td>
</tr>
</tfoot>
</table>
<form> — attributs essentiels| Attribut | Valeurs | Description |
|---|---|---|
action | URL | URL de destination des données |
method | GET / POST | Méthode HTTP d'envoi |
enctype | multipart/form-data | Obligatoire pour l'upload de fichiers |
novalidate | — | Désactive la validation HTML native |
autocomplete | on / off | Active/désactive l'autocomplétion |
<form action="/submit" method="POST" autocomplete="on">
<!-- Label lié à l'input via for/id -->
<label for="prenom">Prénom</label>
<input type="text" id="prenom" name="prenom" required placeholder="Votre prénom" />
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" cols="40"></textarea>
<!-- Regroupement de champs -->
<fieldset>
<legend>Genre</legend>
<label><input type="radio" name="genre" value="h" /> Homme</label>
<label><input type="radio" name="genre" value="f" /> Femme</label>
</fieldset>
<button type="submit">Envoyer</button>
<button type="reset">Réinitialiser</button>
</form>
<!-- Formulaire avec upload de fichier -->
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="avatar" accept="image/*" />
<button type="submit">Uploader</button>
</form>
| Attribut | Exemple | Description |
|---|---|---|
required | — | Champ obligatoire |
minlength | minlength="3" | Longueur minimale (texte) |
maxlength | maxlength="100" | Longueur maximale (texte) |
min | min="0" | Valeur minimale (nombre/date) |
max | max="100" | Valeur maximale |
pattern | pattern="[0-9]{5}" | Regex de validation |
disabled | — | Désactive le champ (non envoyé) |
readonly | — | Lecture seule (envoyé quand même) |
autofocus | — | Focus automatique au chargement |
<input type="text" required minlength="2" maxlength="50" autofocus />
<input type="number" min="18" max="99" />
<input type="text" pattern="[A-Z]{3}[0-9]{2}" title="3 lettres + 2 chiffres" />
<input type="text" value="Non modifiable" readonly />
<input type="text" value="Désactivé" disabled />
<input type="…">| Type | Description | Exemple de valeur |
|---|---|---|
text | Texte libre | "John" |
password | Texte masqué | "••••••" |
email | Adresse email (validé) | "a@b.com" |
number | Nombre (avec flèches) | 42 |
tel | Numéro de téléphone | "0612345678" |
url | URL (validée) | "https://…" |
search | Champ de recherche (croix) | "CSS flexbox" |
date | Sélecteur de date | "2024-01-15" |
time | Sélecteur d'heure | "14:30" |
datetime-local | Date + heure | "2024-01-15T14:30" |
month | Mois et année | "2024-01" |
week | Semaine | "2024-W03" |
range | Curseur (slider) | 0–100 |
color | Sélecteur de couleur | "#ff0000" |
checkbox | Case à cocher | true/false |
radio | Bouton radio (choix unique) | "option1" |
file | Upload de fichier | — |
hidden | Valeur cachée envoyée au serveur | "csrf-token" |
submit | Bouton de soumission | — |
reset | Réinitialise le formulaire | — |
button | Bouton générique (JS) | — |
<input type="text" name="nom" placeholder="Votre nom" />
<input type="email" name="email" placeholder="email@exemple.fr" />
<input type="password" name="mdp" minlength="8" />
<input type="number" name="age" min="0" max="120" step="1" />
<input type="tel" name="tel" pattern="[0-9]{10}" />
<input type="url" name="site" placeholder="https://" />
<input type="date" name="naissance" />
<input type="time" name="heure" min="09:00" max="18:00" />
<input type="range" name="volume" min="0" max="100" value="50" />
<input type="color" name="couleur" value="#58a6ff" />
<input type="file" name="avatar" accept="image/png, image/jpeg" multiple />
<!-- Checkbox -->
<label>
<input type="checkbox" name="cgu" value="accepte" required />
J'accepte les CGU
</label>
<!-- Radio -->
<label><input type="radio" name="plan" value="gratuit" checked /> Gratuit</label>
<label><input type="radio" name="plan" value="premium" /> Premium</label>
<!-- Caché -->
<input type="hidden" name="csrf_token" value="abc123xyz" />
<button>Préférer <button> à <input type="submit"> car il accepte du HTML à l'intérieur. Le type par défaut est submit si dans un formulaire.
<!-- Dans un formulaire -->
<button type="submit">Envoyer</button>
<button type="reset">Réinitialiser</button>
<button type="button" onclick="maFonction()">Cliquez ici</button>
<!-- Avec icône -->
<button type="button">
🔍 Rechercher
</button>
<!-- Désactivé -->
<button type="submit" disabled>Indisponible</button>
<select><!-- Select simple -->
<label for="pays">Pays</label>
<select id="pays" name="pays" required>
<option value="">-- Choisir un pays --</option>
<option value="fr" selected>France</option>
<option value="be">Belgique</option>
<option value="ch">Suisse</option>
</select>
<!-- Avec groupes -->
<select name="langage">
<optgroup label="Frontend">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
</optgroup>
<optgroup label="Backend">
<option value="php">PHP</option>
<option value="node">Node.js</option>
</optgroup>
</select>
<!-- Sélection multiple -->
<select name="competences" multiple size="4">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="react">React</option>
</select>
<datalist>Différent de <select> : l'utilisateur peut saisir librement ET bénéficier de suggestions. Lier via list sur l'input et id sur le datalist.
<label for="ville">Ville</label>
<input type="text" id="ville" name="ville" list="villes" placeholder="Tapez votre ville..." />
<datalist id="villes">
<option value="Paris">
<option value="Lyon">
<option value="Marseille">
<option value="Bordeaux">
<option value="Nantes">
</datalist>
<textarea><label for="bio">Biographie</label>
<textarea
id="bio"
name="bio"
rows="6"
cols="50"
minlength="10"
maxlength="500"
placeholder="Parlez-nous de vous..."
required
></textarea>
<!-- Resize contrôlé via CSS -->
<style>
textarea { resize: vertical; } /* none | both | horizontal | vertical */
</style>
Les balises sémantiques donnent du sens à la structure pour les moteurs de recherche et les lecteurs d'écran. Éviter d'utiliser des <div> partout.
| Balise | Rôle |
|---|---|
<header> | En-tête de page ou de section (logo, nav) |
<nav> | Navigation principale |
<main> | Contenu principal (unique par page) |
<section> | Section thématique avec un titre |
<article> | Contenu autonome (post, carte produit) |
<aside> | Contenu annexe (sidebar, publicité) |
<footer> | Pied de page ou de section |
<time> | Date/heure machine-lisible |
<address> | Coordonnées de contact |
<figure> | Contenu illustratif (image, diagramme) |
<figcaption> | Légende du <figure> |
<details> | Contenu repliable (accordéon natif) |
<summary> | Titre visible du <details> |
<dialog> | Boîte de dialogue / modale native |
<!-- Schéma d'une page typique -->
<header>
<nav>
<a href="/">Accueil</a>
<a href="/blog">Blog</a>
</nav>
</header>
<main>
<section>
<h2>Nos articles</h2>
<article>
<h3>Titre de l'article</h3>
<time datetime="2024-03-15">15 mars 2024</time>
<p>Contenu...</p>
</article>
</section>
<aside>
<h2>Articles récents</h2>
<!-- Liens vers d'autres articles -->
</aside>
</main>
<footer>
<address>
Contact : <a href="mailto:contact@site.fr">contact@site.fr</a>
</address>
</footer>
<!-- Accordéon natif -->
<details>
<summary>Cliquez pour voir plus</summary>
<p>Contenu caché qui se révèle au clic.</p>
</details>
<!-- Modale native -->
<dialog id="maModale">
<p>Contenu de la modale</p>
<button onclick="document.getElementById('maModale').close()">Fermer</button>
</dialog>
<button onclick="document.getElementById('maModale').showModal()">Ouvrir la modale</button>
<video>| Attribut | Description |
|---|---|
src | Source directe (ou utiliser <source>) |
controls | Affiche les contrôles natifs du navigateur |
autoplay | Lecture automatique (nécessite muted) |
muted | Coupe le son (requis pour autoplay) |
loop | Lecture en boucle |
poster | Image affichée avant la lecture |
preload | auto / metadata / none |
width / height | Dimensions |
<!-- Vidéo simple -->
<video src="film.mp4" controls width="800" poster="thumbnail.jpg">
Votre navigateur ne supporte pas la vidéo HTML5.
</video>
<!-- Vidéo avec plusieurs formats -->
<video controls width="800" poster="thumbnail.jpg" preload="metadata">
<source src="film.webm" type="video/webm" />
<source src="film.mp4" type="video/mp4" />
<track src="sous-titres.vtt" kind="subtitles" srclang="fr" label="Français" />
Votre navigateur ne supporte pas la vidéo HTML5.
</video>
<!-- Vidéo en fond (autoplay) -->
<video autoplay muted loop playsinline>
<source src="background.mp4" type="video/mp4" />
</video>
<audio><audio controls>
<source src="musique.ogg" type="audio/ogg" />
<source src="musique.mp3" type="audio/mpeg" />
Votre navigateur ne supporte pas l'audio HTML5.
</audio>
<iframe>Intègre une autre page ou ressource externe. L'attribut sandbox limite les capacités de l'iframe pour la sécurité.
<!-- Carte Google Maps -->
<iframe
src="https://maps.google.com/maps?q=Paris&output=embed"
width="600"
height="450"
loading="lazy"
allowfullscreen
referrerpolicy="no-referrer-when-downgrade"
></iframe>
<!-- Vidéo YouTube -->
<iframe
width="560"
height="315"
src="https://www.youtube.com/embed/ID_VIDEO"
title="Titre de la vidéo"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
allowfullscreen
></iframe>
<!-- Sandbox sécurisé (restreint) -->
<iframe
src="page-externe.html"
sandbox="allow-scripts allow-same-origin"
></iframe>
<head> essentielles<head>
<!-- Encodage (obligatoire, en premier) -->
<meta charset="UTF-8" />
<!-- Responsive (obligatoire) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Compatibilité IE (legacy) -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- SEO -->
<title>Titre de page — Max 60 caractères</title>
<meta name="description" content="Description courte de la page, max 160 caractères pour le SEO." />
<meta name="keywords" content="html, css, développement web" />
<meta name="author" content="Votre Nom" />
<meta name="robots" content="index, follow" />
<!-- Open Graph (partage Facebook, LinkedIn) -->
<meta property="og:title" content="Titre pour les réseaux sociaux" />
<meta property="og:description" content="Description pour les réseaux sociaux." />
<meta property="og:image" content="https://exemple.fr/image.jpg" />
<meta property="og:url" content="https://exemple.fr/page" />
<meta property="og:type" content="website" />
<!-- Twitter Cards -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Titre Twitter" />
<meta name="twitter:description" content="Description Twitter." />
<meta name="twitter:image" content="https://exemple.fr/image.jpg" />
<!-- Favicon -->
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- Feuille de style CSS -->
<link rel="stylesheet" href="style.css" />
<!-- Police Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" />
<!-- Script en head (defer = attend le DOM) -->
<script src="script.js" defer></script>
<!-- async = chargement parallèle, exécution dès prêt -->
<script src="analytics.js" async></script>
<!-- Redirection automatique -->
<meta http-equiv="refresh" content="5; url=https://exemple.fr" />
<!-- Couleur de la barre mobile -->
<meta name="theme-color" content="#58a6ff" />
</head>
| Attribut | Exemple | Description |
|---|---|---|
id | id="mon-id" | Identifiant unique sur la page |
class | class="btn btn-primary" | Classes CSS (plusieurs séparées par espaces) |
style | style="color: red;" | Style inline (déconseillé, préférer CSS) |
title | title="Infobulle" | Infobulle au survol |
lang | lang="fr" | Langue du contenu |
dir | dir="rtl" | Direction du texte (ltr/rtl) |
hidden | hidden | Cache l'élément (display:none) |
tabindex | tabindex="0" | Ordre de tabulation (0=naturel, -1=exclu) |
data-* | data-id="42" | Données personnalisées accessibles via JS |
contenteditable | contenteditable="true" | Rend l'élément éditable dans le navigateur |
draggable | draggable="true" | Rend l'élément glissable (drag & drop) |
spellcheck | spellcheck="false" | Active/désactive la vérification orthographique |
aria-label | aria-label="Fermer" | Label pour les lecteurs d'écran |
aria-hidden | aria-hidden="true" | Cache aux lecteurs d'écran |
role | role="button" | Rôle ARIA pour l'accessibilité |
<!-- data-* : accès via JavaScript -->
<div id="produit" data-id="42" data-category="chaussures" data-price="89.99">
Baskets Air Max
</div>
<script>
const el = document.getElementById('produit');
console.log(el.dataset.id); // "42"
console.log(el.dataset.category); // "chaussures"
console.log(el.dataset.price); // "89.99"
</script>
<!-- Accessibilité ARIA -->
<button
type="button"
aria-label="Fermer la fenêtre"
aria-expanded="false"
onclick="toggleMenu(this)"
>
✕
</button>
<!-- Élément éditable -->
<div contenteditable="true" spellcheck="true">
Cliquez pour modifier ce texte directement.
</div>
<!-- Caché mais gardé dans le DOM -->
<div hidden>Ce contenu est invisible mais existe dans le DOM.</div>
Aucun résultat pour votre recherche.