HTML / CSS — guide complet

Structure, sélecteurs, mise en page, dégradés, animations

Index

Page de référence pour le cours Interfaces virtuelles (570-G22-VM). Les sections sont classées du plus simple au plus complexe. Chaque bloc de code se copie en un clic ; chaque panneau interactif produit le CSS correspondant. Les comportements décrits suivent la norme HTML du WHATWG et les spécifications CSS du W3C.

Structure d'un document HTML

Un document HTML déclare un type de document, un élément html muni d'une langue, un head contenant les métadonnées et un body contenant le contenu visible. La déclaration <!DOCTYPE html> impose le mode standard ; sans elle, le navigateur bascule en mode de compatibilité (quirks mode) et le calcul des boîtes change.

index.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>
  <meta name="description" content="Résumé de 150 caractères.">
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
  <header></header>
  <main></main>
  <footer></footer>
  <script src="js/app.js" defer></script>
</body>
</html>
<!DOCTYPE html>
Première ligne du fichier, avant html. Son seul rôle aujourd'hui est de sélectionner le mode standard.
lang="fr"
Déclare la langue du contenu : utilisée par les lecteurs d'écran pour la prononciation, par le navigateur pour la césure et par les moteurs de recherche.
meta charset="UTF-8"
Doit apparaître dans les 1024 premiers octets du document. Sans elle, les caractères accentués risquent d'être altérés.
meta name="viewport"
Mobile uniquement : associe la fenêtre de rendu à la largeur de l'appareil. Sans elle, le navigateur mobile affiche la page en 980 px puis dézoome ; les media queries ne se déclenchent alors jamais.
link rel="stylesheet"
Charge une feuille de style externe. À placer dans le head pour que la page ne s'affiche pas d'abord sans style.
script ... defer
defer télécharge le script en parallèle et l'exécute après l'analyse du HTML, dans l'ordre du document. async l'exécute dès son arrivée, dans un ordre imprévisible.
Conventions de nommage : noms de fichiers en minuscules, sans espace ni accent, traits d'union plutôt que traits de soulignement. Le point d'entrée s'appelle toujours index.html. Sur un serveur Linux, Photo.JPG et photo.jpg sont deux fichiers distincts.

Balises de contenu et sémantique

Une balise se choisit pour ce que le contenu signifie, jamais pour son apparence : l'apparence relève du CSS. Une hiérarchie de titres correcte constitue aussi un plan du document exploitable par les technologies d'assistance et par les moteurs de recherche.

Balises structurantes

header / footer
Zone d'introduction et de clôture de la page ou d'une section. Plusieurs occurrences sont permises dans un même document.
nav
Bloc de liens de navigation principale. Réservé à la navigation primaire, pas à tout groupe de liens.
main
Contenu dominant du document. Une seule occurrence par page, jamais imbriquée dans header, nav, aside ou footer.
section / article
section regroupe un contenu thématique et porte normalement un titre. article désigne une unité redistribuable de façon autonome : billet, fiche, commentaire.
aside
Contenu accessoire par rapport au contenu principal : barre latérale, liens connexes, exergue.
div / span
Conteneurs neutres sans signification, respectivement bloc et en ligne. À utiliser seulement lorsqu'aucune balise sémantique ne convient.

Balises de texte

contenu.html
<h1>Un seul par page, le sujet du document</h1>
<h2>Section</h2>   /* ne jamais sauter de niveau : h2 puis h4 est un plan fautif */
<p>Paragraphe avec <strong>importance forte</strong> et <em>accent</em>.</p>
<a href="page.html">Lien interne</a>
<a href="https://exemple.org" target="_blank" rel="noopener">Lien externe</a>
<img src="img/vue.jpg" alt="Vue du fleuve depuis le quai" width="800" height="600">
<figure>
  <img src="img/plan.svg" alt="Plan de la salle">
  <figcaption>Figure 1 — plan de la salle</figcaption>
</figure>
<ul><li>Liste non ordonnée</li></ul>
<ol><li>Liste ordonnée</li></ol>
<blockquote cite="https://exemple.org">Citation longue.</blockquote>
<time datetime="2026-08-11">11 août 2026</time>
<code>code en ligne</code> <pre>bloc préformaté</pre>

strong et em portent un sens (importance, accentuation) ; b et i sont purement typographiques et ne transmettent rien à un lecteur d'écran. Les attributs width et height sur une image ne sont pas décoratifs : ils permettent au navigateur de réserver l'espace et d'éviter le décalage de mise en page au chargement.

Chemins d'accès

chemins
src="photo.jpg"          /* même dossier que le fichier HTML */
src="img/photo.jpg"      /* sous-dossier img */
src="../img/photo.jpg"   /* remonte d'un niveau, puis img */
src="/img/photo.jpg"     /* depuis la racine du site : ne fonctionne pas en file:// */
Un chemin relatif (sans barre oblique initiale) fonctionne en local comme en ligne. Un chemin absolu depuis la racine ne fonctionne qu'à travers un serveur web. Cette seule différence explique la majorité des images qui disparaissent après la mise en ligne d'un projet.

Tableaux, formulaires et médias

Un tableau représente des données tabulaires, jamais une mise en page. Un formulaire recueille des données ; chaque champ exige une étiquette associée par for/id, faute de quoi le champ devient inexploitable au lecteur d'écran et la zone cliquable se limite au contrôle lui-même.

tableau.html
<table>
  <caption>Résultats par trimestre</caption>
  <thead>
    <tr><th scope="col">Trimestre</th><th scope="col">Total</th></tr>
  </thead>
  <tbody>
    <tr><th scope="row">T1</th><td>12 400</td></tr>
    <tr><th scope="row">T2</th><td>15 900</td></tr>
  </tbody>
</table>
formulaire.html
<form action="/envoi" method="post">
  <fieldset>
    <legend>Coordonnées</legend>

    <label for="nom">Nom</label>
    <input type="text" id="nom" name="nom" required autocomplete="name">

    <label for="courriel">Courriel</label>
    <input type="email" id="courriel" name="courriel" required
           placeholder="prenom@domaine.ca">

    <label for="sujet">Sujet</label>
    <select id="sujet" name="sujet">
      <option value="info">Information</option>
      <option value="devis">Devis</option>
    </select>

    <label for="msg">Message</label>
    <textarea id="msg" name="msg" rows="5"></textarea>

    <label><input type="checkbox" name="infolettre"> Infolettre</label>
    <button type="submit">Envoyer</button>
  </fieldset>
</form>
type="email|tel|url|number|date"
Modifie le clavier mobile et active la validation native. Ne jamais s'y fier seul : la validation côté client est un confort, la validation côté serveur est la sécurité.
placeholder
Exemple du format attendu. Ce n'est pas une étiquette : il disparaît dès la saisie et son contraste est généralement insuffisant.
required, pattern, min, max
Contraintes natives ; la mise en forme suit avec les pseudo-classes :valid, :invalid, :user-invalid.
picture / source / srcset
Sert un fichier d'image différent selon la largeur d'affichage ou selon le format (AVIF, WebP, repli JPEG).
medias.html
<picture>
  <source srcset="img/vue.avif" type="image/avif">
  <source srcset="img/vue.webp" type="image/webp">
  <img src="img/vue.jpg" alt="Vue du fleuve" width="1200" height="800" loading="lazy">
</picture>

<video src="video/demo.mp4" controls poster="img/apercu.jpg" width="640"></video>
<audio src="son/piste.mp3" controls></audio>

loading="lazy" diffère les images situées hors de l'écran ; ne jamais l'appliquer à la plus grande image visible au chargement, ce qui retarderait l'affichage principal.

Accessibilité : le minimum non négociable

  • alt sur chaque image : décrire la fonction, pas le fichier. Une image purement décorative prend alt="" (vide), ce qui la fait ignorer par les lecteurs d'écran.
  • Un seul h1, puis une hiérarchie de titres stricte. Les utilisateurs de lecteurs d'écran naviguent d'abord par les titres.
  • Un intitulé de lien doit rester compréhensible hors contexte : jamais un simple « cliquez ici ».
  • Rapport de contraste d'au moins 4,5:1 pour le texte courant et 3:1 pour un texte de 18,66 px gras ou 24 px, selon WCAG 2.2 niveau AA.
  • Conserver un indicateur de focus visible. outline: none sans remplacement rend la navigation au clavier impossible.
  • Ne pas transmettre une information par la seule couleur : ajouter une forme, un texte ou un symbole.
  • Respecter prefers-reduced-motion pour toute animation comportant du mouvement (voir la section animation).
focus + skip link
/* Focus visible, au clavier seulement */
:focus-visible{ outline:3px solid #16309c; outline-offset:2px; }

/* Lien d'évitement : premier élément du body */
.skip{ position:absolute; left:-9999px; }
.skip:focus{ left:8px; top:8px; background:#fff; padding:8px; z-index:999; }

CSS : syntaxe et insertion

Une règle CSS associe un sélecteur à un bloc de déclarations. Chaque déclaration comprend une propriété, un deux-points, une valeur et un point-virgule. Trois méthodes d'insertion existent ; seul le fichier externe est maintenable, car il est mis en cache, réutilisable sur plusieurs pages et séparé du contenu.

style.css
/* sélecteur { propriété : valeur ; } */
.carte{
  background:#ffffff;
  padding:16px 20px;      /* raccourci : vertical horizontal */
  border-radius:8px;
}

/* Règles-at */
@import url("typo.css");            /* bloquant : préférer une seconde balise link */
@media (min-width:48rem){ .carte{ padding:24px; } }
@supports (display:grid){ .grille{ display:grid; } }
Fichier externe (recommandé)
head
<link rel="stylesheet" href="css/style.css">
Interne, puis en ligne (à éviter)
head / balise
<style> .carte{ color:#333; } </style>
<p style="color:#333">Texte</p>
Un attribut style en ligne possède une spécificité de 1000 et ne peut être écrasé que par !important. C'est la première cause de feuilles de style qui cessent de fonctionner. Le réserver aux valeurs calculées par JavaScript.

Sélecteurs

Un sélecteur décrit les éléments auxquels une règle s'applique. Cliquer sur un sélecteur ci-dessous : les éléments correspondants du document témoin sont encadrés et comptés.

Premier paragraphe, identifiant intro.

Second paragraphe.

Règle générée0
/* choisir un sélecteur */

Sélecteurs de base et combinateurs

p, .classe, #id, *
Élément, classe, identifiant, universel. Une classe est réutilisable ; un identifiant doit être unique dans le document.
A B
Descendant : tout B contenu dans un A, à n'importe quelle profondeur.
A > B
Enfant direct uniquement.
A + B
Frère adjacent : le B qui suit immédiatement un A.
A ~ B
Frère général : tout B situé après un A, même parent.
[attr], [attr="v"], [attr^="v"], [attr$="v"], [attr*="v"]
Attribut présent, valeur exacte, commence par, finit par, contient. Ajouter i avant la fermeture du crochet pour ignorer la casse.

Pseudo-classes et pseudo-éléments

:hover :focus :focus-visible :active
États d'interaction. :focus-visible ne stylise le focus que lorsqu'il provient du clavier.
:first-child :last-child :nth-child(2n+1)
Position parmi tous les frères. :nth-of-type() ne compte que les frères de même nom d'élément.
:not() :is() :where() :has()
Fonctionnelles. :where() possède toujours une spécificité nulle. :has() sélectionne un parent d'après son contenu — Baseline depuis la fin de 2023.
::before ::after
Boîtes générées exigeant content. Restituées de façon peu fiable par les technologies d'assistance : décoration seulement.
::marker ::placeholder ::selection ::first-line
Marqueur de liste, texte indicatif, texte sélectionné, première ligne rendue.
selecteurs.css
.menu li + li{ margin-top:4px; }
a[href^="https://"]::after{ content:" ↗"; }
li:nth-child(odd){ background:#f4f6f8; }
.carte:has(img){ padding-top:0; }          /* une carte qui contient une image */
:is(h1,h2,h3) + p{ margin-top:0; }
input:user-invalid{ border-color:#c0392b; } /* après que l'utilisateur a quitté le champ */

Cascade, spécificité, héritage

Lorsque plusieurs règles visent le même élément, le navigateur tranche dans cet ordre : origine et importance, puis couches de cascade, puis spécificité, puis ordre d'apparition. La spécificité est un triplet (identifiants, classes/attributs/pseudo-classes, éléments/pseudo-éléments) comparé de gauche à droite ; ce n'est pas un nombre en base 10, onze classes ne l'emportent donc jamais sur un identifiant.

0 - 0 - 0
1 - 0 - 0
Un identifiant : #menu.
0 - 1 - 0
Une classe, un sélecteur d'attribut ou une pseudo-classe : .item, [type=text], :hover.
0 - 0 - 1
Un élément ou un pseudo-élément : a, ::before.
0 - 0 - 0
*, les combinateurs et tout ce qui figure dans :where().

Ordre de résolution

  • Feuille du navigateur, puis feuille de l'auteur, puis feuille de l'utilisateur ; !important inverse cet ordre.
  • Les couches @layer interviennent ensuite : une règle d'une couche plus tardive l'emporte sur une couche antérieure, quelle que soit la spécificité. Les règles hors couche l'emportent sur les règles en couche.
  • Puis la spécificité, puis l'ordre du code : la dernière déclaration écrite l'emporte.
  • L'héritage n'intervient pas dans la cascade : une valeur héritée ne s'applique que si aucune règle ne vise l'élément.
cascade.css
@layer reset, base, composants, utilitaires;

@layer base{ a{ color:#16309c; } }
@layer utilitaires{ .lien-muet{ color:#6a6e73; } }  /* l'emporte : couche plus tardive */

/* Hérité par défaut : color, font-*, line-height, letter-spacing, visibility */
/* Non hérité : margin, padding, border, background, display, width */
.zone{ all:unset; }        /* réinitialise toutes les propriétés */
.zone p{ color:inherit; }  /* force l'héritage */
!important est un dernier recours, pas un outil de débogage. Deux !important concurrents déclenchent une escalade de spécificité que personne ne gagne. Réduire plutôt la spécificité de la règle fautive.

Unités et valeurs

Les unités absolues ignorent le contexte ; les unités relatives dépendent de la taille de police, du parent ou de la fenêtre. Déplacer les deux réglages : les barres ci-dessous affichent la largeur réellement calculée pour chaque unité.

Repère : la police du conteneur vaut 20 px, donc 1em = 20 px à l'intérieur.

px
Pixel CSS, unité absolue de référence. Indépendante de la taille de police choisie par l'utilisateur : inadaptée au texte courant.
rem
Taille de police de l'élément racine (16 px par défaut, modifiée par le réglage du navigateur). Unité par défaut pour la typographie, les espacements et les points de rupture.
em
Taille de police de l'élément courant ; se compose en cas d'imbrication. Utile pour un espacement proportionnel au texte d'un composant.
%
Relatif au parent : la largeur par rapport à la largeur du parent, mais un padding ou un margin en % se calcule toujours sur la largeur du conteneur.
vw vh vmin vmax
Pourcentage de la fenêtre. svh, lvh et dvh traitent le cas de la barre d'outils mobile qui apparaît et disparaît ; dvh la suit en direct.
ch ex lh
Largeur du caractère « 0 », hauteur d'x, interligne calculé. ch est l'unité de référence pour une justification lisible : 45 à 75 caractères.
fr
Fraction de l'espace libre, en Grid uniquement.
unites.css
:root{ font-size:100%; }        /* ne jamais la fixer en px : cela écrase le choix de l'utilisateur */
.article{ max-width:65ch; }
.titre{ font-size:clamp(1.5rem, 1rem + 2.5vw, 3rem); }
.section{ padding-block:clamp(2rem, 6vh, 5rem); }
.plein-ecran{ min-height:100dvh; }
.calcul{ width:calc(100% - 2rem); }

Couleur

Une même couleur s'écrit sous plusieurs notations. L'hexadécimal est compact, hsl() est lisible et permet d'en déduire des variantes, oklch() conserve une clarté perçue constante d'une teinte à l'autre. Choisir une couleur : le panneau produit chaque notation.

Aa
Aa
Notations
#rrggbb / #rgb / #rrggbbaa
Hexadécimal, avec alpha facultatif sur les deux derniers chiffres.
rgb(R G B / A)
Syntaxe moderne séparée par des espaces ; la forme à virgules reste valide.
hsl(H S% L% / A)
Teinte 0-360, saturation, clarté. Faire varier la seule clarté produit une palette cohérente.
oklch(L C H)
Espace perceptuellement uniforme, gamut étendu. Baseline depuis 2023.
currentColor
Renvoie à la valeur de color de l'élément : une bordure ou un SVG suit alors automatiquement la couleur du texte.
color-mix(in oklab, A 70%, B)
Mélange deux couleurs dans un espace donné ; utile pour dériver un état de survol à partir d'une seule variable.
transparent
Équivalent à rgb(0 0 0 / 0). Dans un dégradé, préférer une version transparente explicite de la couleur pour éviter une bande grise dans certains moteurs.

Modèle de boîte

Tout élément engendre une boîte rectangulaire formée de quatre couches : contenu, remplissage, bordure, marge. Avec la valeur initiale box-sizing: content-box, la width déclarée s'applique au seul contenu, auquel s'ajoutent donc le remplissage et la bordure. Avec border-box, la largeur déclarée englobe remplissage et bordure — le seul comportement praticable pour construire une mise en page.

content
CSS
reset.css
/* À placer en tête de tout projet */
*,*::before,*::after{ box-sizing:border-box; }
body{ margin:0; }
img,video{ max-width:100%; height:auto; display:block; }

Comportements à connaître

  • Fusion des marges verticales : deux marges verticales adjacentes se fondent en la plus grande des deux ; un parent et son premier enfant peuvent aussi fusionner. Un remplissage, une bordure ou display:flow-root sur le parent l'empêche. Les marges ne fusionnent jamais en Flex ni en Grid.
  • margin: 0 auto centre un bloc doté d'une largeur explicite. Sans effet sur un élément en flux normal en width:auto, qui occupe déjà toute la ligne.
  • min-width et max-width l'emportent toujours sur width ; min-height: 0 est souvent nécessaire pour autoriser un enfant Flex ou Grid à se réduire.
  • overflow: hidden|auto|scroll|clip gouverne le contenu qui dépasse ; auto n'affiche une barre de défilement qu'en cas de besoin.
  • Les propriétés logiques margin-inline, padding-block, inset suivent le sens d'écriture et résistent à une traduction vers une langue de droite à gauche.

display et flux normal

En flux normal, les boîtes de type bloc s'empilent verticalement et occupent toute la largeur disponible, tandis que les boîtes en ligne se suivent sur une même ligne et ignorent width, height et les marges verticales. display modifie à la fois le comportement extérieur de la boîte et la mise en page de ses enfants.

block
Nouvelle ligne, pleine largeur, dimensions respectées. Valeur par défaut de div, p, section, h1-h6.
inline
Reste dans la ligne de texte ; largeur, hauteur et marges verticales sans effet ; le remplissage horizontal fonctionne. Valeur par défaut de span, a, strong, em.
inline-block
S'écoule comme du texte mais accepte toutes les dimensions. Un espace d'environ 4 px apparaît entre deux boîtes, hérité des espaces du code HTML.
none
L'élément et sa descendance sont retirés de l'arbre de rendu ; l'espace est libéré et le contenu masqué aux technologies d'assistance. visibility:hidden conserve l'espace ; opacity:0 conserve l'espace et laisse l'élément cliquable.
flow-root
Bloc établissant un nouveau contexte de formatage : contient les flottants et stoppe la fusion des marges. Remplaçant propre du clearfix.
flex / grid / contents
Modes de mise en page traités plus bas. contents supprime la boîte et promeut les enfants — à manier avec prudence, cela retire aussi la sémantique de l'élément dans plusieurs moteurs.
Deux notions souvent confondues : display détermine la façon dont l'élément dispose ses enfants, position détermine la façon dont il est placé par rapport à sa propre boîte. Elles sont indépendantes et se combinent.

position et empilement

position détermine la boîte de référence des décalages top, right, bottom, left, et si l'élément occupe encore de la place dans le flux. Modifier la valeur et les décalages ci-dessous : le fantôme gris indique la place occupée dans le flux normal.

parent
boîte

contenu suivant — il remonte si la boîte quitte le flux

CSS
static
Valeur initiale. Dans le flux ; les décalages et z-index sont ignorés. Ne sert pas de repère aux descendants en absolute.
relative
Reste dans le flux en conservant sa place d'origine, puis se décale visuellement par rapport à elle-même. Son usage principal est de servir de repère aux enfants en absolute.
absolute
Retiré du flux ; positionné par rapport à l'ancêtre positionné le plus proche, sinon par rapport au bloc conteneur initial. Sans largeur, il se réduit à son contenu.
fixed
Retiré du flux ; positionné par rapport à la fenêtre et immobile au défilement. Exception : un ancêtre portant transform, filter, backdrop-filter, perspective ou will-change devient le repère — première cause d'un en-tête fixe qui défile malgré tout.
sticky
Reste dans le flux jusqu'au seuil défini par top (ou un autre côté), puis colle à l'intérieur de son parent. Exige un seuil, un parent plus haut que l'élément et aucun overflow: hidden|auto sur un ancêtre.

z-index

  • z-index ne s'applique qu'à un élément positionné (tout sauf static) ou à un enfant Flex ou Grid.
  • Les valeurs ne se comparent qu'au sein d'un même contexte d'empilement. Un enfant en z-index: 9999 ne franchira jamais un parent placé plus bas.
  • Un contexte d'empilement est créé par : l'élément racine, un élément positionné dont le z-index n'est pas auto, une opacity inférieure à 1, transform, filter, mix-blend-mode, isolation: isolate, will-change sur l'une de ces propriétés.
  • Tenir une échelle ordonnée (10, 20, 30) plutôt que des valeurs qui s'emballent, et utiliser isolation: isolate pour confiner un composant.
position.css
/* Barre de navigation collante */
.nav{ position:sticky; top:0; z-index:20; background:#fff; }

/* Calque couvrant tout le parent positionné */
.carte{ position:relative; }
.carte .voile{ position:absolute; inset:0; background:#0006; }

/* Centrage d'un élément de dimensions inconnues */
.centre{ position:absolute; top:50%; left:50%; translate:-50% -50%; }

Flexbox : mise en page à une dimension

display: flex transforme un élément en conteneur flexible dont les enfants directs deviennent des éléments répartis le long d'un axe principal. L'axe principal est horizontal par défaut ; flex-direction: column le rend vertical, et l'axe secondaire lui reste toujours perpendiculaire. C'est l'outil d'une barre d'outils, d'une navigation, d'une rangée de cartes ou d'une ligne de formulaire — tout ce qui s'organise selon un seul axe.

CSS

Propriétés du conteneur

flex-direction
row (défaut), row-reverse, column, column-reverse. L'inversion modifie l'ordre visuel mais non l'ordre du DOM : l'ordre au clavier ne correspond alors plus, à éviter pour du contenu interactif.
justify-content
Répartition sur l'axe principal : flex-start, flex-end, center, space-between (premier et dernier collés aux bords), space-around (espace égal autour de chaque élément, donc moitié aux extrémités), space-evenly (espaces strictement égaux partout).
align-items
Alignement sur l'axe secondaire : stretch (défaut, les éléments remplissent la hauteur), flex-start, center, flex-end, baseline (les lignes de base des textes s'alignent).
flex-wrap
nowrap par défaut : les éléments se compriment au lieu de passer à la ligne. wrap autorise plusieurs lignes, ce qui active align-content.
align-content
Répartition des lignes entre elles, uniquement s'il y en a plusieurs. Sans effet en nowrap.
gap / row-gap / column-gap
Espace entre les éléments, sans les marges de contournement d'autrefois. Fonctionne en Flex, en Grid et en colonnes multiples.

Propriétés des éléments

flex: grow shrink basis
Raccourci. flex: 1 équivaut à 1 1 0% : chaque élément prend une part égale de l'espace, indépendamment de son contenu. flex: auto équivaut à 1 1 auto : la part est proportionnelle au contenu. flex: none fige l'élément.
flex-basis
Taille de référence avant croissance ou réduction, le long de l'axe principal. Prime sur width dans un conteneur en ligne.
align-self
Redéfinit align-items pour un seul élément.
order
Réordonnancement visuel seulement ; l'ordre de lecture et de tabulation reste celui du DOM.
flex-patrons.css
/* Barre : logo à gauche, liens à droite */
.barre{ display:flex; align-items:center; gap:1rem; }
.barre .logo{ margin-right:auto; }

/* Carte dont le pied reste en bas quelle que soit la longueur du texte */
.carte{ display:flex; flex-direction:column; }
.carte .corps{ flex:1; }

/* Rangée adaptative sans media query */
.rangee{ display:flex; flex-wrap:wrap; gap:1rem; }
.rangee > *{ flex:1 1 260px; }   /* passe à la ligne sous 260 px par élément */

/* Centrage parfait, deux axes */
.centre{ display:flex; justify-content:center; align-items:center; min-height:100dvh; }
Un élément flexible ne peut pas se réduire sous la taille de son contenu par défaut (min-width: auto). Un mot long ou un bloc pre fait alors déborder le conteneur. Le correctif est min-width: 0 sur l'élément, ou overflow-wrap: anywhere sur son texte.

CSS Grid : mise en page à deux dimensions

Grid définit simultanément des lignes et des colonnes. Flexbox répartit le contenu sur un axe ; Grid impose une structure sur les deux axes, dans laquelle les éléments viennent se placer. En pratique : Grid pour la charpente de la page et pour toute grille de contenu véritable, Flexbox pour le contenu de chaque cellule.

CSS

Définir la grille

grid-template-columns / -rows
Nombre et taille des pistes explicites. Toutes les unités sont acceptées : px, %, rem, auto, fr, minmax(), repeat(), fit-content().
fr
Fraction de l'espace restant une fois les pistes fixes et les gouttières soustraites. 1fr possède un minimum implicite de auto, ce qui explique qu'un contenu long refuse de se réduire ; minmax(0, 1fr) corrige le cas.
repeat(auto-fit | auto-fill, minmax(…))
Grille adaptative sans media query. auto-fill conserve les pistes vides, auto-fit les réduit à zéro, ce qui étire les éléments présents.
grid-auto-rows / -columns
Taille des pistes implicites, créées lorsque les éléments dépassent la grille explicite. minmax(80px, auto) est la valeur sûre habituelle.
grid-auto-flow
row par défaut. dense comble les trous laissés par les éléments étendus, au prix d'un ordre visuel qui ne suit plus le DOM.

Placer les éléments

placement.css
.item{ grid-column:1 / 3; }        /* de la ligne 1 à la ligne 3 = 2 pistes */
.item{ grid-column:1 / -1; }       /* toute la largeur, -1 = dernière ligne */
.item{ grid-column:span 2; }       /* 2 pistes depuis la position courante */
.item{ grid-row:2 / span 2; }
.item{ grid-area:2 / 1 / 4 / 3; }  /* début ligne / début col. / fin ligne / fin col. */

/* Zones nommées : la charpente de la page se lit comme un dessin */
.page{
  display:grid;
  grid-template-columns:220px 1fr;
  grid-template-rows:auto 1fr auto;
  grid-template-areas:
    "entete entete"
    "menu   contenu"
    "pied   pied";
  min-height:100dvh;
  gap:1rem;
}
.page > header{ grid-area:entete; }
.page > nav   { grid-area:menu; }
.page > main  { grid-area:contenu; }
.page > footer{ grid-area:pied; }

@media (max-width:48rem){
  .page{ grid-template-columns:1fr;
         grid-template-areas:"entete" "menu" "contenu" "pied"; }
}

Alignement

justify-items / align-items
Position de chaque élément dans sa propre cellule, horizontalement puis verticalement. stretch par défaut.
justify-self / align-self
Même chose pour un seul élément.
justify-content / align-content
Position de la grille entière dans le conteneur, lorsque les pistes sont plus étroites que lui. C'est la différence avec Flexbox, où justify-content déplace les éléments eux-mêmes.
place-items / place-content
Raccourcis : place-items: center centre tout dans les deux directions.
subgrid
Une grille imbriquée reprend les pistes de son parent, ce qui aligne les titres et les boutons de cartes de longueurs différentes. Baseline depuis 2023.
subgrid.css
.grille{ display:grid; grid-template-columns:repeat(3,1fr); gap:1rem; }
.carte{ display:grid; grid-row:span 3; grid-template-rows:subgrid; }
/* chaque carte partage les mêmes trois rangées : image, texte, bouton */

Listes et marqueurs

Une liste porte un sens : un lecteur d'écran annonce le nombre d'éléments. La mise en forme modifie le marqueur sans toucher à ce sens, à condition de ne pas priver la liste de son rôle. Régler le panneau ci-dessous pour observer chaque combinaison de type et de position.

  • Premier élément de la liste
  • Deuxième élément, volontairement assez long pour revenir à la ligne et montrer l'alignement du retour
  • Troisième élément
CSS
list-style-type
Forme du marqueur. disc, circle, square pour ul ; decimal, lower-roman, upper-alpha, lower-greek et une trentaine d'autres pour ol ; toute chaîne entre guillemets est également acceptée.
list-style-position
outside (défaut) place le marqueur dans la marge gauche : le retour à la ligne reste aligné sur le texte. inside le place dans le flux : le retour à la ligne repasse sous le marqueur.
list-style-image
Image comme marqueur. Sa taille n'est pas contrôlable, d'où la préférence pour ::marker ou une image de fond.
::marker
Cible le marqueur lui-même. Accepte color, font-size, font-weight et content ; ni background ni padding.
@counter-style
Définit un système de numérotation personnalisé : symboles, préfixe, suffixe, remplissage.
Piège classique : un reset qui applique padding: 0 aux listes fait disparaître les marqueurs, car en outside ils se situent dans une marge devenue inexistante. Ils restent pourtant dans le DOM — aucune erreur en console. Conserver un padding-left, passer en inside, ou remplacer le remplissage par un margin-left.
listes.css
/* Marqueur coloré, plus gros que le texte */
li::marker{ color:#16309c; font-size:1.2em; }

/* Contrôle total : le marqueur devient une vraie boîte */
ul.perso{ list-style:none; padding-left:0; }
ul.perso li{ position:relative; padding-left:1.6em; }
ul.perso li::before{
  content:"";
  position:absolute; left:0; top:.45em;
  width:.6em; height:.6em; background:#16309c; rotate:45deg;
}

/* Numérotation personnalisée */
@counter-style etapes{
  system:numeric; symbols:"0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
  prefix:"Étape "; suffix:" — ";
}
ol.etapes{ list-style:etapes; }

/* Menu : conserver la sémantique, retirer l'apparence de liste */
nav ul{ list-style:none; margin:0; padding:0; display:flex; gap:1rem; }

Typographie

La lisibilité repose sur quatre valeurs : le corps, l'interligne, la justification et le contraste. Un texte courant entre 16 et 20 px, un interligne autour de 1,5, une justification de 45 à 75 caractères et un rapport de contraste d'au moins 4,5:1 couvrent la majorité des cas.

La typographie est l'art d'organiser le texte pour qu'il se lise sans effort. Une justification trop large oblige l'œil à chercher le début de la ligne suivante ; une justification trop étroite hache la lecture. L'interligne compense la longueur de ligne : plus la ligne est longue, plus l'interligne doit être généreux.

CSS
font-family
Pile ordonnée se terminant par une famille générique. system-ui utilise la police d'interface du système : aucun téléchargement, aucun décalage au chargement.
font-size
En rem pour le texte courant, afin de respecter le réglage du navigateur. clamp() produit une taille fluide entre deux bornes.
line-height
Sans unité : la valeur multiplie la taille de police de l'élément et s'hérite correctement. Un line-height: 24px hérité par un enfant plus gros produit des lignes qui se chevauchent.
letter-spacing / word-spacing
Légèrement négatif sur les grands titres, légèrement positif sur les petites capitales. Jamais sur du texte courant.
text-align
left (ou start) pour le texte courant. Un texte justifié sans césure ouvre des lézardes ; ajouter hyphens: auto avec une langue déclarée.
text-wrap: balance | pretty
balance équilibre les lignes d'un titre court, pretty évite une dernière ligne d'un seul mot. Amélioration progressive.
typo.css
/* Police auto-hébergée, sans saut de mise en page */
@font-face{
  font-family:"Inter";
  src:url("fonts/inter.woff2") format("woff2");
  font-weight:100 900;          /* police variable : un seul fichier pour toutes les graisses */
  font-display:swap;
}

body{
  font-family:"Inter", system-ui, sans-serif;
  font-size:1.0625rem;
  line-height:1.6;
  text-rendering:optimizeLegibility;
}
.article{ max-width:68ch; }
h1{ font-size:clamp(1.75rem, 1.2rem + 2.5vw, 3.25rem); line-height:1.1;
    letter-spacing:-.02em; text-wrap:balance; }
.long-mot{ overflow-wrap:anywhere; hyphens:auto; }

Bordures, arrondis et ombres

Une bordure occupe de la place dans la boîte ; un contour (outline) n'en occupe pas, ce qui en fait l'outil approprié pour un anneau de focus. Une ombre n'influence jamais la mise en page : elle est peinte à l'extérieur de la boîte, ou à l'intérieur avec inset.

CSS
border: 1px solid #ccc
Raccourci pour l'épaisseur, le style et la couleur. Sans style, aucune bordure n'apparaît, quelle que soit l'épaisseur.
border-radius
De une à quatre valeurs, dans le sens horaire depuis le coin haut gauche. Une barre oblique sépare les rayons horizontaux et verticaux, ce qui produit des ellipses : border-radius: 40px / 20px.
outline / outline-offset
Peint hors de la bordure, n'occupe aucune place, suit l'arrondi dans les navigateurs actuels. Réservé au focus.
box-shadow: x y blur spread color
Plusieurs ombres séparées par des virgules, peintes de la première à la dernière. inset place l'ombre à l'intérieur de la boîte.
text-shadow: x y blur color
Même syntaxe sans étalement ; s'applique aux glyphes.
filter: drop-shadow()
Suit le canal alpha de l'élément : seule méthode pour projeter une ombre épousant un PNG transparent ou une forme SVG.
ombres.css
/* Des ombres superposées paraissent plus naturelles qu'un seul grand flou */
.carte{
  box-shadow:
    0 1px 2px rgb(11 29 99 / .10),
    0 4px 10px rgb(11 29 99 / .08),
    0 12px 28px rgb(11 29 99 / .06);
}
.carte:hover{ box-shadow:0 10px 30px rgb(11 29 99 / .22); }

/* Bordure dessinée sans occuper de place */
.jeton{ box-shadow:inset 0 0 0 2px currentColor; }

/* Ombre suivant une forme transparente */
.logo{ filter:drop-shadow(0 4px 6px rgb(0 0 0 / .35)); }

Arrière-plans et dégradés

Un dégradé est une image générée par le navigateur : il se place dans background-image, se superpose à d'autres arrière-plans et se redimensionne sans perte. En composer un ci-dessous ; le panneau écrit la déclaration exacte.

CSS

Les trois fonctions de dégradé

linear-gradient(angle, stops)
Progression rectiligne. 0deg va du bas vers le haut, 90deg de la gauche vers la droite, 180deg du haut vers le bas. Les mots-clés to right, to bottom left sont équivalents et plus lisibles.
radial-gradient(shape size at position, stops)
Rayonne depuis un point. circle ou ellipse, taille donnée par closest-side, farthest-corner (défaut) ou des longueurs explicites.
conic-gradient(from angle at position, stops)
Balaye autour d'un point : diagrammes circulaires, roues chromatiques, damiers.
repeating-*-gradient()
Répète le motif d'arrêts jusqu'au bord de la boîte : rayures, réglures, ruban de signalisation.

Arrêts de couleur

  • Un arrêt est une couleur suivie d'une position facultative : red 20%. Deux positions identiques créent une rupture nette, donc une bande plutôt qu'un fondu.
  • Un pourcentage isolé entre deux couleurs est un point d'inflexion : il déplace le milieu du mélange sans ajouter de couleur.
  • Un fondu vers transparent peut produire une bande grise dans certains moteurs, car transparent signifie noir transparent. Faire plutôt un fondu vers la version transparente de la même couleur : rgb(22 48 156 / 0).
  • in oklab ou in hsl après la direction fixe l'espace d'interpolation, ce qui évite le milieu terne entre deux teintes opposées.
degrades.css
/* Voile lisible sur une photographie */
.entete{
  background-image:
    linear-gradient(to top, rgb(0 0 0 / .75), rgb(0 0 0 / 0) 60%),
    url("img/vue.jpg");
  background-size:cover;
  background-position:center;
}

/* Rayures : arrêts francs aux mêmes positions */
.rayures{
  background:repeating-linear-gradient(45deg,
    #16309c 0 12px, #4a82ee 12px 24px);
}

/* Diagramme circulaire en une déclaration */
.part{
  background:conic-gradient(#16309c 0 62%, #dfe2e5 62% 100%);
  border-radius:50%;
}

/* Texte en dégradé */
.titre-degrade{
  background:linear-gradient(90deg,#16309c,#0e8f8f);
  background-clip:text;
  color:transparent;
}

/* Bordure en dégradé au moyen de deux couches */
.cadre{
  border:3px solid transparent;
  background:
    linear-gradient(#fff,#fff) padding-box,
    linear-gradient(135deg,#16309c,#ffd23c) border-box;
}

Les propriétés d'arrière-plan

background-size
cover remplit la boîte en rognant ; contain montre tout en laissant du vide ; des longueurs explicites permettent les motifs répétés.
background-position
Point d'ancrage de l'image. center par défaut avec cover ; une valeur 50% 20% garde un visage visible lors du rognage.
background-repeat
Valeurs repeat, no-repeat, space, round.
background-attachment
fixed produit un effet de parallaxe, coûteux sur mobile et ignoré par iOS dans plusieurs cas.
background-clip / -origin
Zone de peinture et boîte d'origine : border-box, padding-box, content-box, plus text pour un rognage sur les glyphes.
object-fit / object-position
Équivalent pour un élément img ou video : object-fit: cover rogne le média dans sa propre boîte.

Filtres, opacité et modes de fusion

filter applique un traitement d'image à un élément et à tout son contenu. backdrop-filter l'applique à ce qui se trouve derrière l'élément, principe des panneaux dépolis. mix-blend-mode combine l'élément avec les couches inférieures, comme dans un logiciel de composition.

FILTRE
CSS
filter
Fonctions enchaînées dans l'ordre : blur(), brightness(), contrast(), saturate(), grayscale(), sepia(), hue-rotate(), invert(), drop-shadow(). L'ordre compte.
backdrop-filter
Exige un fond partiellement transparent sur l'élément lui-même, faute de quoi rien ne transparaît. Coûteux : en limiter la surface.
opacity
S'applique à l'élément et à toute sa descendance, et crée un contexte d'empilement. Pour ne rendre translucide que le fond, utiliser une couleur avec canal alpha.
mix-blend-mode / background-blend-mode
Valeurs multiply, screen, overlay, difference, luminosity et les autres, identiques aux modes des logiciels d'image. isolation: isolate sur le parent confine l'effet.
effets.css
/* Panneau dépoli au-dessus du contenu */
.panneau{
  background:rgb(255 255 255 / .55);
  backdrop-filter:blur(12px) saturate(160%);
  border:1px solid rgb(255 255 255 / .4);
}

/* Teinte appliquée sur une photographie */
.vignette{ background:#16309c; }
.vignette img{ mix-blend-mode:luminosity; opacity:.85; }

/* Niveaux de gris qui s'anime au survol */
.miniature{ filter:grayscale(1); transition:filter .3s ease; }
.miniature:hover{ filter:grayscale(0); }

transform

Une transformation déplace, met à l'échelle, tourne ou incline l'élément peint sans toucher à la mise en page : l'espace occupé reste identique et les voisins ne bougent pas. Les transformations sont composées par le processeur graphique, ce qui en fait, avec opacity, les deux seules propriétés animables à soixante images par seconde sans repeindre.

boîte
CSS
translate(x, y) / translateX / translateY / translate3d
Les pourcentages se rapportent à la taille de l'élément lui-même, non à celle du parent — principe de la technique de centrage translate(-50%, -50%).
scale(x, y)
1 correspond à la taille d'origine ; une valeur négative produit un miroir. Un texte agrandi reste net, étant redessiné vectoriellement.
rotate(angle)
Accepte deg, rad, turn, grad. rotateX, rotateY, rotateZ exigent une perspective sur le parent pour se lire en profondeur.
skew(x, y)
Cisaillement. Le texte se déforme ; appliquer le cisaillement inverse à l'élément intérieur pour le garder lisible.
transform-origin
Point fixe de la transformation, center par défaut. Le modifier transforme une rotation en balancement depuis un coin.
perspective / transform-style
perspective sur le parent définit un point de fuite commun : plus la valeur est faible, plus l'effet est marqué. transform-style: preserve-3d place les enfants dans le même espace tridimensionnel.
L'ordre compte : translateX(50px) rotate(45deg) diffère de rotate(45deg) translateX(50px), car dans le second cas la translation suit l'axe tourné. Les propriétés individuelles translate, rotate et scale s'appliquent toujours dans cet ordre fixe, quel que soit l'ordre écrit dans le CSS.
flip-carte.css
.scene{ perspective:900px; }
.carte{ position:relative; transform-style:preserve-3d; transition:transform .6s; }
.scene:hover .carte{ transform:rotateY(180deg); }
.face{ position:absolute; inset:0; backface-visibility:hidden; }
.face.dos{ transform:rotateY(180deg); }

transition

Une transition interpole une propriété entre deux états déclenchés par un événement : un survol, un focus, une classe ajoutée par JavaScript. Elle exige une valeur de départ et une valeur d'arrivée, toutes deux animables. La fonction de temporisation détermine tout le caractère du mouvement ; modifier la courbe ci-dessous et observer le repère.

CSS
transition-property
Liste des propriétés surveillées. all est commode mais surveille tout, y compris ce que modifie une règle sans rapport : les nommer plutôt une à une.
transition-duration
150 à 250 ms pour une réponse d'interface, 300 à 500 ms pour l'entrée d'un élément. Au-delà de 600 ms, l'interface paraît lourde.
transition-timing-function
Valeurs ease (défaut), linear, ease-in (départ lent), ease-out (arrivée douce, choix habituel pour une apparition), ease-in-out, cubic-bezier(x1,y1,x2,y2), steps(n) pour une lecture image par image.
transition-delay
Retard avant le départ. En l'augmentant élément par élément, on obtient une entrée en cascade.
@starting-style
Déclare la valeur initiale d'un élément qui vient d'apparaître, ce qui rend possible une transition d'entrée depuis display: none.
transitions.css
.bouton{
  background:#16309c; color:#fff;
  transition:background-color .18s ease-out, translate .18s ease-out, box-shadow .18s ease-out;
}
.bouton:hover{ background:#4a82ee; translate:0 -2px; box-shadow:0 6px 16px rgb(11 29 99 / .3); }
.bouton:active{ translate:0 0; transition-duration:.06s; }

/* Entrée en cascade, sans JavaScript */
.liste li{ opacity:0; translate:0 12px; transition:opacity .4s, translate .4s; }
.liste.visible li{ opacity:1; translate:0 0; }
.liste.visible li:nth-child(1){ transition-delay:.05s; }
.liste.visible li:nth-child(2){ transition-delay:.10s; }
.liste.visible li:nth-child(3){ transition-delay:.15s; }
Une transition exige deux valeurs calculables. Passer de height: auto à une hauteur fixe n'anime rien : utiliser grid-template-rows: 0fr vers 1fr, ou max-height, ou la propriété interpolate-size: allow-keywords là où elle est prise en charge.

Animation et @keyframes

Une animation se déroule seule, sans déclencheur, et peut comporter plusieurs états intermédiaires. @keyframes décrit la ligne de temps en pourcentages ; la propriété animation l'associe à un élément avec une durée, un nombre de répétitions et un sens. En construire une ci-dessous et en copier le résultat.

1
2
3
CSS
@keyframes nom
Étapes écrites en from/to ou en pourcentages. Une propriété absente d'une étape continue d'être interpolée entre les étapes qui la déclarent.
animation-name / -duration
Sans durée, rien ne se produit : la valeur initiale est 0s.
animation-iteration-count
Un nombre ou infinite. Les valeurs fractionnaires sont permises : 2.5 s'arrête au milieu du troisième passage.
animation-direction
alternate joue en aller-retour, ce qui évite le saut d'une boucle qui repart de zéro.
animation-fill-mode
forwards conserve l'état final après la dernière itération, backwards applique le premier état pendant le retard, both combine les deux. Sans cette valeur, l'élément reprend brutalement son style de base.
animation-play-state
running ou paused ; se bascule au survol ou depuis JavaScript.
animation-timeline
Lie l'animation au défilement plutôt qu'au temps (scroll(), view()). Vérifier l'état Baseline avant de s'y fier.
animations.css
@keyframes apparition{
  from{ opacity:0; translate:0 16px; }
  to  { opacity:1; translate:0 0; }
}
@keyframes pulsation{
  0%,100%{ scale:1; }
  50%    { scale:1.08; }
}
@keyframes rotation{ to{ rotate:360deg; } }

.carte{ animation:apparition .5s ease-out both; }
.carte:nth-child(2){ animation-delay:.08s; }
.carte:nth-child(3){ animation-delay:.16s; }

/* Indicateur de chargement en CSS pur */
.chargement{
  width:34px; height:34px; border-radius:50%;
  border:4px solid #dfe2e5; border-top-color:#16309c;
  animation:rotation .9s linear infinite;
}

/* Plusieurs animations sur un même élément */
.jeton{ animation:apparition .4s ease-out both, pulsation 2s ease-in-out 1s infinite; }

/* Obligatoire : respecter la préférence de mouvement réduit */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
}
Animer d'abord transform et opacity : ils sont composés sans recalcul de mise en page. Animer width, height, top, left, margin ou padding force un recalcul à chaque image et fait chuter la cadence sur du matériel modeste.

Conception adaptative

Une page est fluide par défaut ; c'est une largeur fixe qui la casse. La méthode consiste donc à écrire une mise en page valable à toute largeur, puis à n'ajouter des points de rupture que là où le rendu se dégrade réellement. Les media queries observent la fenêtre, les container queries observent le conteneur de l'élément — ce dont a besoin un composant réutilisable. Déplacer le réglage : la fiche ci-dessous réagit à son conteneur, non à la fenêtre.

Fiche de cours
Disposition appliquée :
CSS
.liste{ container-type:inline-size; container-name:fiche; }

.fiche{ display:grid; grid-template-columns:1fr; gap:1rem; }

@container fiche (min-width:380px){
  .fiche{ grid-template-columns:130px 1fr; align-items:center; }
}
@container fiche (min-width:560px){
  .fiche{ grid-template-columns:180px 1fr auto; }
}

Media queries

responsive.css
/* Mobile d'abord : la règle de base vise le petit écran, puis on élargit */
.grille{ display:grid; grid-template-columns:1fr; gap:1rem; }

@media (min-width:48rem){  /* 768 px à la taille racine par défaut */
  .grille{ grid-template-columns:repeat(2,1fr); }
}
@media (min-width:75rem){ /* 1200px */
  .grille{ grid-template-columns:repeat(3,1fr); }
}

/* Syntaxe d'intervalle, plus lisible */
@media (30rem <= width <= 60rem){ .barre{ display:none; } }

/* Requêtes de capacité et de préférence */
@media (hover:hover) and (pointer:fine){ .carte:hover{ scale:1.02; } }
@media (prefers-color-scheme:dark){ :root{ --fond:#12141a; --texte:#e6edf3; } }
@media (prefers-reduced-motion:reduce){ .carrousel{ animation:none; } }
@media print{ nav,.pub{ display:none; } a::after{ content:" (" attr(href) ")"; } }
Points de rupture
Les déduire du contenu, non de noms d'appareils. En rem, afin qu'ils suivent la taille de police de l'utilisateur. Trois ou quatre suffisent en général.
min-width vs max-width
Mêler les deux directions dans un même projet produit des plages qui se chevauchent et des conflits. Choisir min-width (mobile d'abord) et s'y tenir.
Images adaptatives
srcset et sizes laissent le navigateur choisir le fichier ; picture et source laissent l'auteur choisir, par format ou par cadrage.
Fluide sans requête
clamp(), min(), max(), repeat(auto-fit, minmax()) et flex-wrap couvrent la majorité des cas sans aucun point de rupture.
Cibles tactiles
Au moins 24 sur 24 pixels CSS selon WCAG 2.2, 44 sur 44 selon les recommandations mobiles usuelles, avec un espacement entre elles.

Propriétés personnalisées, calc et fonctions

Une propriété personnalisée est une véritable variable CSS : elle est héritée, dynamique, lisible et modifiable depuis JavaScript, et redéfinissable dans une media query ou sur un seul composant. C'est le mécanisme des thèmes, du mode sombre et des jetons de conception. Modifier les valeurs ci-dessous : tout ce qui en dépend suit.

Carte
Toutes les valeurs proviennent de variables.
CSS
--nom: valeur
Déclarée sur n'importe quel sélecteur, généralement sur :root pour les jetons globaux. Sensible à la casse.
var(--nom, repli)
Le second argument est la valeur de repli employée si la variable n'est pas définie.
calc()
Mélange les unités : calc(100% - 2rem). Les espaces autour de + et - sont obligatoires.
min() / max() / clamp()
clamp(min, idéal, max) remplace toute une famille de media queries pour la typographie et les espacements.
@property
Type une propriété personnalisée, ce qui la rend animable : un angle de dégradé ou une couleur peuvent alors être mis en transition.
jetons.css
:root{
  --marque:#16309c;
  --marque-clair:color-mix(in oklab, var(--marque) 70%, white);
  --texte:#12141a;
  --fond:#ffffff;
  --espace:1rem;
  --rayon:.5rem;
  --transition:.2s ease-out;
}
[data-theme="sombre"]{
  --texte:#e6edf3;
  --fond:#12141a;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="clair"]){ --texte:#e6edf3; --fond:#12141a; }
}

.carte{
  background:var(--fond); color:var(--texte);
  padding:var(--espace); border-radius:var(--rayon);
  transition:background-color var(--transition);
}

/* Propriété personnalisée animable */
@property --angle{ syntax:"<angle>"; initial-value:0deg; inherits:false; }
.anneau{ background:conic-gradient(from var(--angle),#16309c,#0e8f8f,#16309c);
         transition:--angle .6s linear; }
.anneau:hover{ --angle:360deg; }
theme.js
/* Lire et écrire une variable depuis JavaScript */
const racine = document.documentElement;
racine.style.setProperty("--marque", "#0e8f8f");
getComputedStyle(racine).getPropertyValue("--marque").trim();
racine.dataset.theme = "sombre";

Organisation, débogage, performance

Structurer une feuille de style

  • Ordre fixe : reset, jetons (:root), éléments de base, mise en page, composants, utilitaires. @layer rend cet ordre explicite et le met à l'abri des accidents de spécificité.
  • Nommer les classes par leur rôle et non par leur apparence : .alerte plutôt que .texte-rouge. Une convention de type BEM (bloc__element--variante) maintient une spécificité plate.
  • L'imbrication native est disponible dans tous les moteurs actuels. La limiter à deux niveaux : au-delà, elle reconstruit les problèmes de spécificité qu'elle devait éviter.
  • Un composant, un fichier, une responsabilité claire. Ce qui sert trois fois devient un jeton ou un utilitaire.
imbrication.css
.carte{
  padding:var(--espace);

  & .titre{ font-size:1.25rem; }        /* l'esperluette est facultative devant une classe */
  &:hover{ box-shadow:0 6px 18px #0002; } /* obligatoire devant une pseudo-classe */

  @media (min-width:48rem){ padding:2rem; }
}

Débogage

  • outline: 1px solid red sur * révèle toutes les boîtes d'un coup, sans modifier la mise en page comme le ferait une bordure.
  • Dans les outils de développement, l'onglet Calculé indique la règle gagnante et celles qui sont barrées ; l'onglet Mise en page superpose les lignes de grille et les axes flexibles.
  • Un débordement horizontal provient presque toujours d'une largeur fixe, d'une marge négative ou d'une longue chaîne insécable. body{ overflow-x: hidden } masque le symptôme, non la cause.
  • Un style qui refuse de s'appliquer : vérifier le sélecteur dans la console avec document.querySelectorAll(), puis la spécificité, puis l'ordre du code, puis une faute dans le nom de la propriété — une déclaration invalide est ignorée silencieusement.
  • Valider le balisage (validateur du W3C) : une balise non fermée peut déplacer un bloc entier dans un mauvais parent.

Performance

  • N'animer que transform et opacity. Ajouter will-change juste avant l'animation et le retirer ensuite ; le laisser en place conserve une couche en mémoire pour rien.
  • Servir les images à la taille d'affichage, en AVIF ou WebP, avec width et height déclarés pour réserver l'espace.
  • content-visibility: auto associé à contain-intrinsic-size évite le rendu des sections hors écran sur les pages longues.
  • Auto-héberger les polices, s'en tenir à deux familles et utiliser font-display: swap pour éviter un texte invisible pendant le chargement.
  • Éviter @import en production : il sérialise les téléchargements. Utiliser plusieurs balises link ou une étape de compilation.

Sources et conditions d'usage

  • WHATWG, HTML Living Standard — https://html.spec.whatwg.org/multipage/
  • W3C, index des spécifications CSS (Selectors 4, CSS Cascade 5, CSS Box Model 3, CSS Flexible Box 1, CSS Grid 2, CSS Images 4, CSS Transforms 2, CSS Transitions, CSS Animations, CSS Values 4) — https://www.w3.org/Style/CSS/specs.en.html
  • W3C, Web Content Accessibility Guidelines (WCAG) 2.2 — https://www.w3.org/TR/WCAG22/
  • MDN Web Docs (Mozilla), CSS reference — https://developer.mozilla.org/docs/Web/CSS
  • W3C, service de validation du balisage — https://validator.w3.org/ et validateur CSS — https://jigsaw.w3.org/css-validator/
  • Baseline (groupe communautaire WebDX) pour l'état de prise en charge — https://web.dev/baseline
Les mentions de prise en charge de cette page ont été vérifiées auprès de Baseline en août 2026. La prise en charge évolue : vérifier l'état d'une fonctionnalité récente avant de s'y fier en production.
ISRAËL DUPUIS
Référence pédagogique — 570-G22-VM Interfaces virtuelles.
© 2026 Israël Dupuis. israeldupuis.com
Haut