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.
<!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>
html. Son seul rôle aujourd'hui est de sélectionner le mode standard.head pour que la page ne s'affiche pas d'abord sans style.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.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, nav, aside ou footer.section regroupe un contenu thématique et porte normalement un titre. article désigne une unité redistribuable de façon autonome : billet, fiche, commentaire.Balises de texte
<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
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:// */
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.
<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><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>:valid, :invalid, :user-invalid.<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
altsur chaque image : décrire la fonction, pas le fichier. Une image purement décorative prendalt=""(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: nonesans 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-motionpour toute animation comportant du mouvement (voir la section animation).
/* 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.
/* 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; } }
<link rel="stylesheet" href="css/style.css">
<style> .carte{ color:#333; } </style>
<p style="color:#333">Texte</p>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.
/* choisir un sélecteur */
Sélecteurs de base et combinateurs
i avant la fermeture du crochet pour ignorer la casse.Pseudo-classes et pseudo-éléments
:focus-visible ne stylise le focus que lorsqu'il provient du clavier.:nth-of-type() ne compte que les frères de même nom d'élément.:where() possède toujours une spécificité nulle. :has() sélectionne un parent d'après son contenu — Baseline depuis la fin de 2023.content. Restituées de façon peu fiable par les technologies d'assistance : décoration seulement..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.
#menu..item, [type=text], :hover.a, ::before.*, 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 ;
!importantinverse cet ordre. - Les couches
@layerinterviennent 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.
@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.
padding ou un margin en % se calcule toujours sur la largeur du conteneur.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 est l'unité de référence pour une justification lisible : 45 à 75 caractères.: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.
color de l'élément : une bordure ou un SVG suit alors automatiquement la couleur du texte.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.
/* À 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-rootsur le parent l'empêche. Les marges ne fusionnent jamais en Flex ni en Grid. margin: 0 autocentre un bloc doté d'une largeur explicite. Sans effet sur un élément en flux normal enwidth:auto, qui occupe déjà toute la ligne.min-widthetmax-widthl'emportent toujours surwidth;min-height: 0est souvent nécessaire pour autoriser un enfant Flex ou Grid à se réduire.overflow: hidden|auto|scroll|clipgouverne le contenu qui dépasse ;auton'affiche une barre de défilement qu'en cas de besoin.- Les propriétés logiques
margin-inline,padding-block,insetsuivent 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.
visibility:hidden conserve l'espace ; opacity:0 conserve l'espace et laisse l'élément cliquable.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.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.
contenu suivant — il remonte si la boîte quitte le flux
z-index sont ignorés. Ne sert pas de repère aux descendants en absolute.absolute.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.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-indexne s'applique qu'à un élément positionné (tout saufstatic) 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: 9999ne 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-indexn'est pasauto, uneopacityinférieure à 1,transform,filter,mix-blend-mode,isolation: isolate,will-changesur 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: isolatepour confiner un composant.
/* 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.
Propriétés du conteneur
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.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).stretch (défaut, les éléments remplissent la hauteur), flex-start, center, flex-end, baseline (les lignes de base des textes s'alignent).nowrap par défaut : les éléments se compriment au lieu de passer à la ligne. wrap autorise plusieurs lignes, ce qui active align-content.nowrap.Propriétés des éléments
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.width dans un conteneur en ligne.align-items pour un seul élément./* 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; }
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.
Définir la grille
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.auto-fill conserve les pistes vides, auto-fit les réduit à zéro, ce qui étire les éléments présents.minmax(80px, auto) est la valeur sûre habituelle.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
.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
stretch par défaut.justify-content déplace les éléments eux-mêmes.place-items: center centre tout dans les deux directions..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
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.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.::marker ou une image de fond.color, font-size, font-weight et content ; ni background ni padding.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./* 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.
system-ui utilise la police d'interface du système : aucun téléchargement, aucun décalage au chargement.rem pour le texte courant, afin de respecter le réglage du navigateur. clamp() produit une taille fluide entre deux bornes.line-height: 24px hérité par un enfant plus gros produit des lignes qui se chevauchent.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.balance équilibre les lignes d'un titre court, pretty évite une dernière ligne d'un seul mot. Amélioration progressive./* 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.
border-radius: 40px / 20px.inset place l'ombre à l'intérieur de la boîte./* 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.
Les trois fonctions de dégradé
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.circle ou ellipse, taille donnée par closest-side, farthest-corner (défaut) ou des longueurs explicites.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
transparentpeut produire une bande grise dans certains moteurs, cartransparentsignifie noir transparent. Faire plutôt un fondu vers la version transparente de la même couleur :rgb(22 48 156 / 0). in oklabouin hslaprès la direction fixe l'espace d'interpolation, ce qui évite le milieu terne entre deux teintes opposées.
/* 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
cover remplit la boîte en rognant ; contain montre tout en laissant du vide ; des longueurs explicites permettent les motifs répétés.center par défaut avec cover ; une valeur 50% 20% garde un visage visible lors du rognage.repeat, no-repeat, space, round.fixed produit un effet de parallaxe, coûteux sur mobile et ignoré par iOS dans plusieurs cas.border-box, padding-box, content-box, plus text pour un rognage sur les glyphes.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.
blur(), brightness(), contrast(), saturate(), grayscale(), sepia(), hue-rotate(), invert(), drop-shadow(). L'ordre compte.multiply, screen, overlay, difference, luminosity et les autres, identiques aux modes des logiciels d'image. isolation: isolate sur le parent confine l'effet./* 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.
translate(-50%, -50%).1 correspond à la taille d'origine ; une valeur négative produit un miroir. Un texte agrandi reste net, étant redessiné vectoriellement.deg, rad, turn, grad. rotateX, rotateY, rotateZ exigent une perspective sur le parent pour se lire en profondeur.center par défaut. Le modifier transforme une rotation en balancement depuis un coin.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.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..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.
all est commode mais surveille tout, y compris ce que modifie une règle sans rapport : les nommer plutôt une à une.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.display: none..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; }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.
from/to ou en pourcentages. Une propriété absente d'une étape continue d'être interpolée entre les étapes qui la déclarent.0s.infinite. Les valeurs fractionnaires sont permises : 2.5 s'arrête au milieu du troisième passage.alternate joue en aller-retour, ce qui évite le saut d'une boucle qui repart de zéro.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.running ou paused ; se bascule au survol ou depuis JavaScript.scroll(), view()). Vérifier l'état Baseline avant de s'y fier.@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;
}
}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.
Disposition appliquée :
.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
/* 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) ")"; } }
rem, afin qu'ils suivent la taille de police de l'utilisateur. Trois ou quatre suffisent en général.min-width (mobile d'abord) et s'y tenir.srcset et sizes laissent le navigateur choisir le fichier ; picture et source laissent l'auteur choisir, par format ou par cadrage.clamp(), min(), max(), repeat(auto-fit, minmax()) et flex-wrap couvrent la majorité des cas sans aucun point de rupture.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.
Toutes les valeurs proviennent de variables.
:root pour les jetons globaux. Sensible à la casse.calc(100% - 2rem). Les espaces autour de + et - sont obligatoires.clamp(min, idéal, max) remplace toute une famille de media queries pour la typographie et les espacements.: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; }/* 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.@layerrend 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 :
.alerteplutô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.
.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 redsur*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
transformetopacity. Ajouterwill-changejuste 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
widthetheightdéclarés pour réserver l'espace. content-visibility: autoassocié à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: swappour éviter un texte invisible pendant le chargement. - Éviter
@importen production : il sérialise les téléchargements. Utiliser plusieurs baliseslinkou 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