Créer un fichier CSS et le lier à sa page HTML

« Mon CSS ne s'applique pas. » Le fichier existe, la balise link est dans le head, et la page reste en noir sur blanc. Ce guide fait les trois étapes dans l'ordre : créer le fichier, le lier, puis vérifier qu'il est réellement chargé, parce que c'est cette vérification qui transforme une impression en certitude. Ensuite je reproduis, une par une, les quatre pannes classiques d'une feuille de style ignorée : un chemin faux, une majuscule de trop, deux fichiers qui se contredisent, et un cache qui garde l'ancienne version.

Méthode habituelle de ce blog : tout ce qui suit a été exécuté et mesuré pendant la rédaction, le 14 septembre 2026, dans Chromium 153.0.8010.12 (le navigateur headless de Playwright 1.63.0, même moteur que Chrome), avec un petit serveur statique écrit en Node 20.19.4 sur Windows 11, et un second serveur identique dans un conteneur Debian 12 (Node 22.23.2) pour le test des majuscules. Quand j'écris qu'un titre est bleu, ce n'est pas une impression : c'est la couleur calculée par le navigateur, lue avec getComputedStyle. Si la structure d'une page HTML est encore floue pour vous, commencez par les bases pour bien débuter en HTML, tout ce qui suit s'appuie dessus.

Pourquoi un fichier séparé plutôt que du CSS dans la page

Il existe trois façons d'appliquer du CSS, et je les compare dans donner du style à une page grâce au CSS. Celle qui compte pour un vrai site, c'est le fichier séparé. Un site a plusieurs pages, et toutes doivent avoir la même allure : avec un fichier style.css lié depuis chacune, une couleur se change à un seul endroit. C'est aussi un fichier que le navigateur peut garder en mémoire d'une page à l'autre, et réutiliser sans le télécharger à nouveau. Vous verrez à la fin que cette mémoire a un revers.

Étape 1 : créer le fichier style.css

Un fichier CSS est un simple fichier texte. Dans VS Code, ouvrez le dossier de votre site, créez un nouveau fichier et enregistrez-le sous le nom style.css, à côté de index.html. L'onglet de l'éditeur affiche le nom complet : vérifiez qu'il se termine bien par .css. Choisissez un nom en minuscules, sans espace ni accent ; la section sur les majuscules explique pourquoi ce n'est pas une coquetterie. Voici le dossier de départ :

mon-site/
├── index.html
└── style.css

Et le contenu de style.css, deux règles pour voir le résultat tout de suite : une police, une largeur de lecture et un centrage sur le corps de page, une couleur sur le titre.

body {
  font-family: system-ui, sans-serif;
  max-width: 40rem;
  margin: 2rem auto;
}

h1 {
  color: rgb(29, 78, 216);
}

Étape 2 : la balise link dans le head

Le lien entre les deux fichiers se fait dans l'en-tête du document, avec la balise link. Voici la page de référence, 340 octets. Les scénarios qui suivent adaptent sa balise link ; seule la page sans lien change aussi le titre du document et le texte du paragraphe.

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Ma première page</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>Ma première page</h1>
  <p>Ce paragraphe est mis en forme par le fichier style.css.</p>
</body>
</html>

Deux attributs, et les deux sont indispensables. href donne le chemin du fichier, ici style.css parce qu'il est dans le même dossier que la page. rel="stylesheet" dit au navigateur quelle relation ce fichier entretient avec la page : c'est une feuille de style, à télécharger et à appliquer. L'attribut type="text/css" que vous verrez dans de vieux tutoriels est facultatif : le standard HTML prévoit qu'une ressource liée avec rel="stylesheet" est traitée comme du CSS quand type est absent (section sur l'élément link du standard HTML de WHATWG, consultée le 14 septembre 2026). Les autres balises de l'en-tête, dont la meta viewport qui compte sur mobile, sont détaillées dans les 5 balises à connaître pour le head.

Oublier rel est une erreur silencieuse, et je l'ai mesurée. Avec <link href="style.css"> tout seul, le navigateur ne demande même pas le fichier au serveur : zéro requête vers style.css, document.styleSheets.length vaut 0, et le titre reste rgb(0, 0, 0), noir. Aucun message d'erreur nulle part : du point de vue du navigateur, une balise link sans relation ne demande rien.

Étape 3 : vérifier que la feuille est vraiment chargée

Quand tout va bien, voici ce que le navigateur fait, dans l'ordre : il lit index.html, rencontre la balise link, demande style.css au serveur, reçoit le fichier avec le code 200, et applique les règles. Sur ma page, le titre est calculé à rgb(29, 78, 216), document.styleSheets.length vaut 1 et cette feuille contient 2 règles. Si l'aller-retour entre le navigateur et le serveur est encore abstrait pour vous, comment fonctionne un site web le raconte pas à pas.

1. Le navigateur lit index.html 2. <link rel="stylesheet" href="style.css"> 3. Il demande style.css au serveur Réponse 200 2 règles appliquées titre rgb(29, 78, 216) Réponse 404 0 règle, titre noir erreur dans la console
Les trois étapes du chargement et les deux issues, telles que mesurées.

Quand ça va mal, la page s'affiche quand même. C'est le piège : un fichier CSS introuvable ne produit aucun message visible pour le visiteur, juste une page sans style. Sur ma page avec un chemin faux, le titre est calculé à rgb(0, 0, 0), et la seule trace est dans les outils de développement (touche F12 dans Chrome). L'onglet Réseau (Network) montre la requête style.css avec le statut 404, et l'onglet Console affiche exactement ceci :

Failed to load resource: the server responded with a status of 404 (Not Found)

Prenez donc l'habitude, à chaque nouvelle page, d'ouvrir la console et de vérifier qu'elle est vide. Pour aller plus vite, voici une ligne à coller dans la console, qui liste chaque feuille de style avec son nombre de règles :

[...document.styleSheets].map(f => `${f.href ?? "style dans la page"} : ${f.cssRules.length} règle(s)`)

Sur la page correcte, elle renvoie http://localhost:8080/ok/style.css : 2 règle(s). Sur la page au chemin faux, elle renvoie http://localhost:8080/mauvais-chemin/css/style.css : 0 règle(s). Ce détail m'a surpris au banc : sur un 404, Chrome crée quand même une feuille, vide. document.styleSheets.length vaut 1 dans les deux cas, et la propriété sheet de la balise link n'est pas nulle non plus. Pour ces pages, qui chargent leur feuille depuis le même site, croisez donc trois indices : le statut de la requête dans l'onglet Réseau, le nombre de règles, et le style calculé du titre. Le nombre de règles seul ne prouve pas que le style attendu s'applique à l'élément que vous regardez.

Le chemin relatif : où le navigateur cherche vraiment le fichier

Le chemin écrit dans href est résolu à partir du dossier où se trouve la page HTML, pas à partir du dossier du site. Tant que tout est au même endroit, on ne s'en rend pas compte. Le problème arrive dès qu'on range : une feuille dans un dossier css/, des pages secondaires dans un dossier pages/. J'ai construit ce dossier et mesuré trois façons d'écrire le lien depuis pages/apropos.html (au banc, une page par écriture, dans le même dossier pages/).

mon-site/
├── index.html
├── css/
│   └── style.css
└── pages/
    └── apropos.html
Depuis pages/apropos.html, où mène href ? mon-site/ ├─ index.html ├─ css/ │ └─ style.css └─ pages/ └─ apropos.html css/style.css cherche pages/css/ : 404 ../css/style.css remonte d'un dossier : 200 /css/style.css racine du site : 200 (échoue en double-clic)
Trois écritures du même lien depuis une page rangée dans un sous-dossier, et le statut mesuré pour chacune.

Première écriture testée : href="css/style.css", recopiée telle quelle depuis index.html, où elle marchait. Depuis pages/apropos.html, le navigateur cherche /pages/css/style.css, qui n'existe pas : statut 404, titre noir, message d'erreur en console. Deuxième écriture : href="../css/style.css". Les deux points signifient « le dossier parent » ; le navigateur remonte de pages/ vers mon-site/, puis descend dans css/ : statut 200, titre bleu. Troisième écriture : href="/css/style.css", avec une barre oblique en tête. Ce chemin part de la racine du site, quel que soit le dossier de la page : statut 200 aussi, et il a l'avantage de s'écrire pareil dans toutes les pages.

Le chemin qui commence par une barre a pourtant un défaut mesurable pendant l'apprentissage. Si vous ouvrez la page par un double-clic dans l'explorateur, sans serveur, l'adresse commence par file:// et la « racine » devient celle du disque : sur mon poste, le lien a été résolu en file:///C:/css/style.css, et Chrome a répondu net::ERR_FILE_NOT_FOUND. La même page avec ../css/style.css s'affiche correctement en double-clic. Tant que vous travaillez sans serveur local, préférez les chemins relatifs avec ../.

Majuscules et minuscules : ça marche sur votre PC, plus une fois en ligne

Voici la panne la plus déroutante des quatre, parce qu'elle n'apparaît qu'au moment de mettre le site en ligne. J'ai nommé le fichier style.css et écrit href="Style.css", avec une majuscule. Servie depuis mon PC sous Windows, la page est parfaite : requête en 200, titre bleu. Le même dossier, copié dans un conteneur Debian 12 et servi par le même programme, répond 404 : titre noir, erreur en console. Dans les deux environnements testés, le système de fichiers de Windows ignore la casse, celui du conteneur Debian la distingue ; et le serveur qui héberge ce site la distingue aussi, puisque sa propre feuille de style répond 404 dès qu'on change une majuscule de son nom.

Le fichier n'a pas bougé, le code non plus. Dans mon test, la différence vient du système de fichiers ; le serveur public de ce site distingue lui aussi ces deux adresses. La règle qui évite ce piège : tout en minuscules, les noms de fichiers comme les chemins écrits dans href et dans src, sans espace ni accent, et exactement les mêmes des deux côtés. Un site qui respecte cette règle ne peut plus tomber sur cette incohérence-là.

Plusieurs fichiers CSS : le dernier a le dernier mot

Rien n'interdit de lier plusieurs feuilles, par exemple une base commune et un thème. Mais si deux feuilles donnent une valeur différente à la même propriété du même élément, à conditions égales (je les détaille juste après), l'ordre des balises link tranche. Mon test : base.css met le titre en bleu, theme.css le met en vert, chaque feuille contenant une seule règle h1. Voici les deux lignes du head, indentation comprise :

  <link rel="stylesheet" href="base.css">
  <link rel="stylesheet" href="theme.css">

Dans cet ordre, le titre est calculé à rgb(22, 163, 74), vert : la règle de theme.css, lue en dernier, l'emporte. En inversant les deux balises, il passe à rgb(29, 78, 216), bleu. Les deux feuilles sont bien chargées dans les deux cas (2 feuilles, 1 règle chacune), c'est seulement l'ordre de lecture qui change. Dans ce test, les deux déclarations ont la même origine (mes feuilles), la même importance (pas de !important), aucune couche déclarée et la même spécificité (le sélecteur h1) : c'est alors l'ordre qui départage. Dès que l'un de ces critères diffère, la cascade tranche avant l'ordre, et c'est un autre sujet.

« J'ai modifié mon CSS et rien ne change » : le cache

Dernière panne, celle qui fait douter de tout : vous changez une couleur, vous rechargez la page, et rien ne bouge. Le fichier est pourtant enregistré. J'ai reproduit la situation avec un serveur qui envoie l'en-tête Cache-Control: max-age=3600 sur les fichiers CSS, c'est-à-dire l'autorisation de garder la feuille en mémoire pendant une heure. Premier chargement : titre bleu. Je modifie style.css pour passer le titre en vert, et je recharge la page normalement : le titre est toujours rgb(29, 78, 216), bleu. Le journal du serveur confirme qu'il n'a reçu qu'une seule demande de style.css : le navigateur a réutilisé sa copie sans rien demander. Un rechargement forcé, qui ignore le cache, ramène le vert rgb(22, 163, 74), et le serveur reçoit alors sa deuxième demande.

Avec le même serveur réglé sur max-age=0, le rechargement normal suffit : le titre passe au vert dès ce rechargement, qui est la deuxième demande de style.css reçue par le serveur, et le rechargement forcé qui suit porte le compte à trois. La différence tient à une décision de Chrome, annoncée sur le blog Chromium le 26 janvier 2017 (article « Reload, reloaded: faster and leaner page reloads ») : un rechargement ordinaire ne revérifie que la page elle-même, et les fichiers qu'elle charge sont repris du cache tant que leur durée n'est pas écoulée. Les hébergeurs envoient bien ce genre d'en-tête. Relevés le 14 septembre 2026 : la feuille de style de GitHub Pages arrive avec max-age=600, dix minutes ; celle de ce site avec max-age=31536000, immutable, un an. Une durée pareille se combine avec une adresse versionnée : une nouvelle version est publiée sous un nouveau nom de fichier, sans attendre l'expiration de l'ancien. Une empreinte du contenu peut servir à construire cette adresse versionnée ; c'est une façon parmi d'autres.

Deux gestes règlent le problème pendant le développement. Le rechargement forcé, Maj+F5, Ctrl+F5 ou Ctrl+Maj+R sur Windows et Linux, Cmd+Maj+R sur Mac. Ou, plus confortable, la case « Désactiver le cache » (Disable cache) en haut de l'onglet Réseau des outils de développement, qui reste active tant que ces outils sont ouverts.

La checklist quand le CSS ne s'applique pas

Un fichier style.css lié par <link rel="stylesheet" href="style.css"> dans le head, et la vérification qui va avec : l'onglet Réseau doit montrer un 200, la console doit être vide. Quand le style attendu ne s'applique pas, voici les cinq vérifications mesurées dans cet article, dans l'ordre où je les fais :

Pour voir ces principes à l'œuvre sur un vrai projet de trois fichiers, avec des variables CSS et une mise en page complète, enchaînez sur créer un portfolio de développeur avec HTML, CSS et un peu de JS.

Et si votre feuille de style est maintenant chargée mais encore presque vide, la suite logique est la typographie : mettre en forme le texte en CSS, police, taille, graisse et alignement.