Structure de base
Squelette HTML5
Essentiel

Structure minimale requise pour toute page HTML5. Le <!DOCTYPE html> indique au navigateur d'utiliser le mode standard HTML5.

HTML
<!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>
Commentaires HTML

Les commentaires ne sont pas affichés dans le navigateur. Utiles pour documenter ou désactiver temporairement du code.

HTML
<!-- Ceci est un commentaire sur une ligne -->

<!--
  Ceci est un commentaire
  sur plusieurs lignes
-->
Titres & Paragraphes
Titres <h1> à <h6>
SEO

6 niveaux de titres. Un seul <h1> par page (important pour le SEO). Les titres définissent la hiérarchie du contenu.

HTML
<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>
Paragraphe <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.

HTML
<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>
Mise en forme du texte
Balises sémantiques de texte
BaliseRenduSignification
<strong>texteImportant — gras sémantique
<em>texteEmphase — italique sémantique
<u>texteSouligné (non-sémantique, préférer CSS)
<s>texteBarré — texte non pertinent
<mark>texteTexte surligné (mise en valeur)
<small>texteTexte plus petit (mentions légales)
<sub>H2OIndice (exposant bas)
<sup>x2Exposant (exposant haut)
<abbr>HTMLAbréviation avec infobulle au survol
<cite>titre œuvreTitre d'une œuvre citée
<q>citation courteCitation courte inline avec guillemets auto
<blockquote>Citation longue en bloc
HTML
<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 & préformaté — <code> <pre> <kbd>

<code> pour afficher du code inline. <pre> préserve les espaces et sauts de ligne. <kbd> représente une touche clavier.

HTML
<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>
Liens
Balise <a> — tous les usages
Navigation
AttributValeurDescription
hrefURL / #id / cheminDestination du lien
target_blank / _selfOù ouvrir le lien (nouvel onglet / même onglet)
relnoopener noreferrerSécurité avec target="_blank"
downloadnom-fichierForce le téléchargement au lieu d'ouvrir
titletexteInfobulle au survol
HTML
<!-- 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>
Images & Médias
Balise <img>
Accessibilité

L'attribut alt est obligatoire pour l'accessibilité et le SEO. Laisser vide (alt="") pour les images décoratives.

AttributDescription
srcChemin ou URL de l'image
altTexte alternatif (obligatoire)
width / heightDimensions en px (évite le layout shift)
loading="lazy"Chargement différé (performance)
srcsetImages responsives (plusieurs tailles)
sizesTaille d'affichage selon le viewport
HTML
<!-- 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="" />
Balise <picture> — images adaptatives avancées

Permet de servir différents formats (WebP, AVIF) ou différentes images selon les breakpoints. Le navigateur choisit la première source compatible.

HTML
<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>
Listes
Listes non ordonnée <ul>, ordonnée <ol> et de définitions <dl>
HTML
<!-- 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>
Tableaux
Structure complète d'un tableau
Accessibilité
BaliseRô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é)
HTML
<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>
Formulaires
Balise <form> — attributs essentiels
AttributValeursDescription
actionURLURL de destination des données
methodGET / POSTMéthode HTTP d'envoi
enctypemultipart/form-dataObligatoire pour l'upload de fichiers
novalidateDésactive la validation HTML native
autocompleteon / offActive/désactive l'autocomplétion
HTML
<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>
Attributs de validation natifs
Validation
AttributExempleDescription
requiredChamp obligatoire
minlengthminlength="3"Longueur minimale (texte)
maxlengthmaxlength="100"Longueur maximale (texte)
minmin="0"Valeur minimale (nombre/date)
maxmax="100"Valeur maximale
patternpattern="[0-9]{5}"Regex de validation
disabledDésactive le champ (non envoyé)
readonlyLecture seule (envoyé quand même)
autofocusFocus automatique au chargement
HTML
<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 />
Types d'inputs
Tous les types <input type="…">
TypeDescriptionExemple de valeur
textTexte libre"John"
passwordTexte masqué"••••••"
emailAdresse email (validé)"a@b.com"
numberNombre (avec flèches)42
telNuméro de téléphone"0612345678"
urlURL (validée)"https://…"
searchChamp de recherche (croix)"CSS flexbox"
dateSélecteur de date"2024-01-15"
timeSélecteur d'heure"14:30"
datetime-localDate + heure"2024-01-15T14:30"
monthMois et année"2024-01"
weekSemaine"2024-W03"
rangeCurseur (slider)0–100
colorSélecteur de couleur"#ff0000"
checkboxCase à cochertrue/false
radioBouton radio (choix unique)"option1"
fileUpload de fichier
hiddenValeur cachée envoyée au serveur"csrf-token"
submitBouton de soumission
resetRéinitialise le formulaire
buttonBouton générique (JS)
HTML
<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" />
Boutons <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.

HTML
<!-- 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 & Datalist
Liste déroulante <select>
HTML
<!-- 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>
Autocomplétion <datalist>
UX

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.

HTML
<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>
Zone de texte <textarea>
HTML
<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>
Balises sémantiques HTML5
Structure sémantique de page
SEOAccessibilité

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.

BaliseRô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
HTML
<!-- 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>
Vidéo & Audio
Balise <video>
AttributDescription
srcSource directe (ou utiliser <source>)
controlsAffiche les contrôles natifs du navigateur
autoplayLecture automatique (nécessite muted)
mutedCoupe le son (requis pour autoplay)
loopLecture en boucle
posterImage affichée avant la lecture
preloadauto / metadata / none
width / heightDimensions
HTML
<!-- 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>
Balise <audio>
HTML
<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 & Embed
Balise <iframe>
Sécurité

Intègre une autre page ou ressource externe. L'attribut sandbox limite les capacités de l'iframe pour la sécurité.

HTML
<!-- 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>
Attributs globaux
Attributs utilisables sur toutes les balises
AttributExempleDescription
idid="mon-id"Identifiant unique sur la page
classclass="btn btn-primary"Classes CSS (plusieurs séparées par espaces)
stylestyle="color: red;"Style inline (déconseillé, préférer CSS)
titletitle="Infobulle"Infobulle au survol
langlang="fr"Langue du contenu
dirdir="rtl"Direction du texte (ltr/rtl)
hiddenhiddenCache l'élément (display:none)
tabindextabindex="0"Ordre de tabulation (0=naturel, -1=exclu)
data-*data-id="42"Données personnalisées accessibles via JS
contenteditablecontenteditable="true"Rend l'élément éditable dans le navigateur
draggabledraggable="true"Rend l'élément glissable (drag & drop)
spellcheckspellcheck="false"Active/désactive la vérification orthographique
aria-labelaria-label="Fermer"Label pour les lecteurs d'écran
aria-hiddenaria-hidden="true"Cache aux lecteurs d'écran
rolerole="button"Rôle ARIA pour l'accessibilité
HTML
<!-- 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.