Que contient un boilerplate HTML moderne ?
Créez une base HTML moderne avec les cinq lignes requises, les métadonnées utiles, les favicons et les balises sociales. Voyez quoi garder ou supprimer.
Un boilerplate HTML moderne doit comporter cinq éléments : le doctype HTML5, un attribut lang sur <html>, une déclaration d’encodage UTF-8, une balise meta viewport et un <title> unique. Tout le reste dépend de l’usage de la page : sera-t-elle partagée, installée ou ajoutée aux favoris ?
La plupart des pages partent du snippet ! d’Emmet, du fichier index.html d’un framework ou d’une copie de HTML5 Boilerplate vieille de dix ans. Personne ne revient vérifier ces lignes, si bien que les lignes obsolètes se recopient d’un projet à l’autre.
Cet article passe le document en revue ligne par ligne. Pour chaque ligne, il explique son rôle, ce qui se casse en son absence et si elle est obligatoire, facultative ou supprimable sans risque. Pour l’ordre des éléments dans le head et une vue d’ensemble des métadonnées, consultez l’article complémentaire sur ce qui a vraiment sa place dans le head de votre document.
Voici ce que génère le ! d’Emmet :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
C’est un point de départ valide. Il ne comporte toutefois ni description, ni URL canonique, ni balises sociales, ni icônes, ni color-scheme, et son viewport contient une valeur dont vous n’avez plus besoin.
Points clés à retenir
- Les lignes obligatoires d’un boilerplate HTML moderne sont le doctype,
lang,<meta charset="UTF-8">, la balise viewport et<title>. S’il en manque une seule, la page s’affiche incorrectement, devient moins accessible ou n’est pas valide. - L’attribut
langcontrôle la prononciation des lecteurs d’écran, la césure CSS et la traduction par le navigateur. Google ne l’utilise pas pour détecter la langue d’une page. maximum-scale,minimum-scaleetuser-scalable=noempêchent les utilisateurs malvoyants de zoomer. Supprimez-les partout où ils apparaissent.- Un jeu complet de favicons comprend
favicon.ico,favicon.svg, unapple-touch-icon.pngde 180×180 et un manifeste web avec des icônes de 192 et 512 pixels, plus une icône maskable. X-UA-Compatible,shrink-to-fit=noettype="text/javascript"n’apportent rien d’utile dans un nouveau projet et peuvent être supprimés.
Le doctype et l’attribut lang
Obligatoire. <!DOCTYPE html> fait passer le navigateur en mode standards. Sans lui, le parseur HTML se rabat sur le mode quirks, qui reproduit les bugs de mise en page des anciens navigateurs. Vous obtenez alors des différences de modèle de boîte et de dimensionnement des tableaux qu’aucun débogage CSS ne permet d’expliquer.
Obligatoire. L’attribut lang sur <html> remplit trois fonctions :
- Il indique aux lecteurs d’écran quelles règles de prononciation appliquer.
- Il permet à la propriété CSS
hyphens: autode couper les mots à l’aide du bon dictionnaire. - Il aide les fonctions de traduction du navigateur à identifier la langue de la page.
Sans lui, un lecteur d’écran risque de lire un texte français avec une phonétique anglaise. La valeur est une étiquette de langue BCP 47 comme en, de ou pt-BR, et les éléments enfants peuvent la redéfinir, comme l’explique la référence MDN sur lang.
lang relève de l’accessibilité et de la langue, pas du référencement. Google Search indique qu’il ignore lang et détecte la langue à partir du contenu de la page.
<!DOCTYPE html>
<html lang="en">
D’abord le charset, ensuite le viewport
Obligatoire. <meta charset="UTF-8"> doit figurer dans les 1024 premiers octets du document. C’est pourquoi on le place en premier dans <head>, avant <title> et tout autre texte que le navigateur risquerait sinon de décoder avec le mauvais encodage. S’il est absent ou placé trop loin, les caractères accentués et les emojis de votre titre se transforment en mojibake.
Obligatoire. La balise viewport indique aux navigateurs mobiles de mettre en page le document à la largeur de l’appareil. Sans elle, les téléphones affichent une mise en page à la largeur d’un écran de bureau (généralement autour de 980px) puis la réduisent, si bien que vos media queries ne se déclenchent jamais. width=device-width suffit à lui seul, et initial-scale=1 est généralement superflu. Consultez la référence MDN sur le viewport pour la liste complète des valeurs.
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
Facultatif, à tester d’abord. <meta name="text-scale" content="scale"> est défini dans le brouillon CSS Fonts Level 5, et seuls les navigateurs basés sur Chromium l’implémentent. Il aligne la taille de police racine sur la taille de texte choisie par l’utilisateur dans les réglages de son système ou de son navigateur. Conséquence : seul le texte dimensionné en rem et em grossit, et les composants à hauteur fixe peuvent déborder. Augmentez la taille du texte système et vérifiez vos mises en page avant de le déployer.
Title, description et URL canonique
Obligatoire. <title> nomme la page dans les onglets du navigateur, les favoris, l’historique et les résultats de recherche. Si vous conservez la valeur par défaut Document, tous vos onglets se ressemblent.
Facultatif mais recommandé. <meta name="description"> propose un résumé pour les extraits de recherche. Google peut le réécrire s’il trouve dans la page un contenu plus pertinent pour la requête, et il tronque les extraits en fonction de la largeur d’affichage. Les règles fondées sur le nombre de caractères sont donc peu fiables.
Facultatif mais recommandé. <link rel="canonical"> désigne l’URL à privilégier lorsqu’un même contenu est accessible à plusieurs adresses, par exemple avec des paramètres de requête ou des variantes avec ou sans barre oblique finale. Pour en savoir plus, consultez les balises HTML liées au SEO et comment les optimiser.
<title>Page title – Site name</title>
<meta name="description" content="One or two sentences describing this page.">
<link rel="canonical" href="https://example.com/page">
Balises Open Graph et Twitter Card
Facultatif, indispensable pour tout contenu destiné à être partagé. Les balises Open Graph contrôlent l’aperçu des liens sur les réseaux sociaux et dans les messageries. Sans elles, un lien partagé apparaît sous forme d’URL brute ou d’une carte construite à partir de ce que le scraper trouve.
Le protocole Open Graph définit og:title, og:type, og:image et og:url comme propriétés obligatoires, et précise qu’une page sans type doit être traitée comme website. Donnez à og:url la même valeur que votre URL canonique, afin que les liens comportant des paramètres de suivi ne soient pas mis en cache comme des pages distinctes. Pour og:image, Meta recommande une image d’au moins 1200×630 pixels, proche d’un ratio de 1,91:1.
X lit ses propres balises twitter:*, écrites avec name plutôt que property, et se rabat sur les valeurs og:* correspondantes lorsqu’elles sont absentes. En pratique, la seule balise spécifique à X dont vous avez besoin est twitter:card, et uniquement si vous souhaitez la carte avec grande image.
<meta property="og:title" content="Page title">
<meta property="og:description" content="Description for link previews.">
<meta property="og:image" content="https://example.com/og-image.jpg">
<meta property="og:url" content="https://example.com/page">
<meta name="twitter:card" content="summary_large_image">
Pour générer ces balises page par page, utilisez le générateur de balises meta.
Le jeu de favicons
Facultatif, mais attendu. Une configuration complète de favicons comporte quatre éléments. Sans eux, vous obtenez une icône d’onglet vide, une vignette façon capture d’écran sur l’écran d’accueil iOS et des icônes d’installation génériques sur Android.
- Un
favicon.icode 32×32 pour les anciens navigateurs. - Un
favicon.svgcapable de s’adapter àprefers-color-scheme. Safari prend en charge les favicons SVG depuis Safari 26.0. - Un
apple-touch-icon.pngde 180×180 pour l’écran d’accueil iOS. - Un manifeste d’application web listant des icônes PNG de 192×192 et 512×512, plus une variante maskable pour les masques circulaires et en squircle.
Conservez les deux éléments <link rel="icon">, celui du favicon.ico et celui du favicon.svg. Ainsi, les navigateurs qui ne gèrent pas les favicons SVG, y compris Safari avant la version 26, récupèrent tout de même le fichier ICO.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
circle { fill: #1a1a2e; }
@media (prefers-color-scheme: dark) {
circle { fill: #f5f5f5; }
}
</style>
<circle cx="16" cy="16" r="14"/>
</svg>
{
"name": "Site name",
"short_name": "Site",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}
Pour en savoir plus sur la génération de chaque fichier, consultez comment ajouter un favicon à votre site web.
color-scheme et theme-color
Facultatif, recommandé si vous proposez un mode sombre. <meta name="color-scheme" content="light dark"> indique au navigateur que la page prend en charge les deux modes avant même le chargement du CSS. Les arrière-plans par défaut, les contrôles de formulaire et les barres de défilement suivent alors la préférence de l’utilisateur. Sans cette balise, un site au thème sombre peut afficher un flash blanc au chargement. Consultez la documentation MDN sur color-scheme.
Facultatif. theme-color colore l’interface du navigateur et accepte un attribut media, ce qui permet de définir des valeurs distinctes pour les modes clair et sombre. Il fonctionne dans Chromium sur Android, mais MDN indique une prise en charge limitée par les navigateurs : considérez-le comme un bonus plutôt que comme un élément que tous les navigateurs afficheront.
<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#111111" media="(prefers-color-scheme: dark)">
Une réduction des animations par défaut
Facultatif, fortement recommandé. La réduction des animations par défaut est une règle de votre feuille de style de base, pas une balise du head. Elle a sa place dans le boilerplate parce que personne ne revient l’ajouter après coup. Un bloc prefers-reduced-motion: reduce raccourcit les animations et les transitions et désactive le défilement fluide pour les utilisateurs qui ont demandé à leur système d’exploitation de réduire les animations.
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Les durées sont fixées à 0.01ms plutôt qu’à 0 afin que les événements animationend et transitionend continuent de se déclencher. Ainsi, le JavaScript qui attend ces événements ne reste pas bloqué. Il s’agit d’un réglage par défaut radical. Chaque composant peut ensuite réactiver des animations douces, comme des fondus d’opacité, qui ne provoquent pas de troubles vestibulaires.
Quelles lignes supprimer des anciens boilerplates ?
À supprimer. Quatre lignes des anciens boilerplates HTML proviennent de modèles de l’ère IE et des premiers kits de démarrage responsive, et aucune n’a plus la moindre utilité aujourd’hui :
X-UA-Compatiblesélectionnait les modes de document d’Internet Explorer. Aucun des navigateurs que vous prenez en charge ne la lit.maximum-scale,minimum-scaleetuser-scalable=noempêchent les personnes malvoyantes de zoomer par pincement, ce qui va à l’encontre du critère WCAG 1.4.4 Redimensionnement du texte. Retirez-les de toutes vos balises viewport.shrink-to-fit=nocontournait un ancien comportement de mise à l’échelle d’iOS Safari et n’a plus aucun effet.type="text/javascript"répète la valeur par défaut. La spécification HTML demande aux auteurs d’omettretypepour les scripts classiques.
<!-- Before -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no">
<script type="text/javascript" src="/app.js"></script>
<!-- After -->
<meta name="viewport" content="width=device-width">
<script type="module" src="/app.js"></script>
Un script type="module" est différé par défaut : il s’exécute après l’analyse du document sans bloquer le rendu. Si un script ne peut pas être un module, ajoutez-lui defer.
Le boilerplate HTML complet
Le boilerplate HTML moderne complet ci-dessous réunit toutes les lignes obligatoires et recommandées de cet article. Ajoutez-y au besoin les éléments propres à votre site, comme des flux ou des preloads. Le lien d’évitement et le landmark <main> se placent dans le body, et l’article 10 éléments HTML essentiels présente les éléments sémantiques qui viennent ensuite.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<!-- Optional, test with large OS text first: <meta name="text-scale" content="scale"> -->
<title>Page title – Site name</title>
<meta name="description" content="One or two sentences describing this page.">
<link rel="canonical" href="https://example.com/page">
<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#111111" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="/styles.css">
<script type="module" src="/app.js"></script>
<link rel="icon" href="/favicon.ico">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
<meta property="og:title" content="Page title">
<meta property="og:description" content="Description for link previews.">
<meta property="og:image" content="https://example.com/og-image.jpg">
<meta property="og:url" content="https://example.com/page">
<meta name="twitter:card" content="summary_large_image">
</head>
<body>
<a href="#main">Skip to content</a>
<main id="main"></main>
</body>
</html>
| Ligne | Rôle | Ce qui se casse sans elle | Verdict |
|---|---|---|---|
| Doctype | Mode standards | Mise en page en mode quirks | Obligatoire |
lang | Prononciation, césure, traduction | Mauvaise voix du lecteur d’écran | Obligatoire |
charset | Déclare l’UTF-8 | Caractères illisibles | Obligatoire |
viewport | Mise en page à la largeur de l’appareil | Mise en page bureau réduite sur mobile | Obligatoire |
<title> | Nomme la page | Onglets et favoris identiques | Obligatoire |
| Description, URL canonique | Extrait et URL à privilégier | Extraits moins pertinents, URL en double | Facultatif |
Open Graph, twitter:card | Aperçus de liens | Cartes vides ou génériques | Facultatif |
| Jeu de favicons | Icônes d’onglet et d’écran d’accueil | Icônes vides ou façon capture d’écran | Facultatif |
color-scheme | Mode sombre natif | Flash blanc, contrôles clairs | Facultatif |
X-UA-Compatible, limites de zoom, shrink-to-fit, type="text/javascript" | Contournements hérités | Rien | À supprimer |
Seules cinq lignes d’un boilerplate HTML sont obligatoires. Tout le reste est soit facultatif, selon que la page est partagée, installée ou dotée d’un thème, soit une ligne héritée à supprimer. Ouvrez le fichier index.html de votre projet actuel, comparez chaque ligne au tableau ci-dessus et retirez tout ce qui figure dans la ligne « À supprimer » avant de copier le fichier dans votre prochain projet.
FAQ
meta charset est-il équivalent à meta http-equiv Content-Type ?
Oui. Selon la spécification HTML du WHATWG, la version http-equiv Content-Type remplit la même fonction que l'attribut charset. Toutes deux constituent une déclaration d'encodage des caractères et doivent figurer dans les 1024 premiers octets. Un document ne doit pas contenir les deux, et les validateurs le signalent comme une erreur. Utilisez la forme plus courte meta charset='UTF-8'. Si le serveur envoie un charset dans son en-tête HTTP Content-Type, vérifiez qu'il indique également UTF-8.
Les balises meta et link ont-elles besoin d'une barre oblique finale en HTML ?
Non. Meta, link, img et les autres éléments vides n'ont pas de balise fermante, et le parseur HTML ignore la barre oblique finale qu'on leur ajoute. Une balise écrite avec la barre oblique et la même balise écrite sans produisent le même élément. La barre oblique est valide mais sans effet : c'est une question de style. Le seul cas où elle compte est celui d'une page servie en XHTML avec un type MIME XML.
Peut-on omettre les balises html, head et body ?
Oui. La spécification HTML considère les balises html, head et body comme facultatives dans de nombreux cas, et le parseur crée ces éléments même lorsque les balises sont absentes. Un boilerplate devrait néanmoins les écrire explicitement. L'attribut lang a besoin d'une balise ouvrante html explicite pour y être placé, et des balises explicites rendent la frontière entre head et body plus lisible. Si vous omettez la balise html, vous perdez aussi lang.
Comment modifier la valeur lang par défaut du snippet ! d'Emmet ?
Définissez la variable lang dans le paramètre emmet.variables de VS Code. Dans settings.json, ajoutez à l'objet emmet.variables une clé lang avec une valeur comme fr : Emmet écrira alors ce code de langue à chaque expansion du snippet !. Ce même paramètre comporte une variable charset, que vous devez laisser à UTF-8. La ligne viewport contient toujours initial-scale=1.0 : supprimez-la à la main ou définissez un snippet personnalisé.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Star on GitHub12k