HTML
& CSS
Structure, sémantique, mise en page, Flexbox, Grid, animations — des bases aux astuces intermédiaires.
Structure & doctype
<!-- Déclaration du type de document : HTML5 -->
<!DOCTYPE html>
<html lang="fr">
<head>
<!-- Méta-données : encodage, viewport, titre... -->
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Ma page</title>
<link rel="stylesheet" href="style.css"/>
</head>
<body>
<!-- Contenu visible de la page -->
<header>...</header>
<main>...</main>
<footer>...</footer>
<script src="app.js"></script>
</body>
</html>
Balise vs élément : une balise est le marqueur textuel (<p>). Un élément inclut la balise ouvrante, le contenu et la balise fermante (<p>texte</p>). Certains éléments sont auto-fermants : <img/>, <br/>, <input/>.
Attributs : paires clé="valeur" dans la balise ouvrante. Les plus courants : id (unique sur la page), class (partageable), href (liens), src (source médias), alt (texte alternatif), type (formulaires).
Le <script> est placé en fin de <body> (ou avec l'attribut defer) pour ne pas bloquer le rendu de la page pendant le chargement du JavaScript.
Balises sémantiques
Les balises sémantiques donnent du sens au contenu (pas juste de la mise en forme). Elles améliorent l'accessibilité, le SEO et la lisibilité du code.
<header> <!-- en-tête, logo, nav principale -->
<nav> <!-- navigation principale -->
<ul><li><a href="/">Accueil</a></li></ul>
</nav>
</header>
<main> <!-- contenu principal (unique/page) -->
<article> <!-- contenu autonome (billet, produit) -->
<h1>Titre</h1>
<section> <!-- section thématique -->
<h2>Sous-titre</h2>
<p>...</p>
</section>
</article>
<aside> <!-- contenu connexe, sidebar -->
<p>Voir aussi...</p>
</aside>
</main>
<footer> <!-- pied de page -->
<address>contact@exemple.com</address>
</footer>
Balises sémantiques vs génériques
| Sémantique ✓ | Générique ✗ | Rôle |
|---|---|---|
| <header> | <div id="header"> | En-tête de section |
| <nav> | <div class="nav"> | Navigation |
| <main> | <div id="content"> | Contenu principal |
| <article> | <div class="post"> | Contenu autonome |
| <section> | <div class="block"> | Section thématique |
| <aside> | <div class="sidebar"> | Contenu connexe |
| <footer> | <div id="footer"> | Pied de page |
| <figure> | <div class="img-wrap"> | Illustration avec légende |
| <time> | <span> | Date/heure machine-readable |
Hiérarchie des titres : ne jamais sauter de niveaux. <h1> unique par page (titre principal), puis <h2> pour les sections, <h3> pour les sous-sections, etc. Les moteurs de recherche et les lecteurs d'écran s'appuient dessus.
Texte & liens
<!-- Paragraphes et titres -->
<h1> à <h6> Titres (importance décroissante)
<p> Paragraphe
<br/> Saut de ligne (à éviter — préférer CSS)
<hr/> Séparateur thématique
<!-- Mise en valeur -->
<strong>important</strong> Importance (bold sémantique)
<em>emphase</em> Emphase (italic sémantique)
<mark>surligné</mark> Mise en évidence
<code>monospace</code> Code inline
<pre><code>bloc</code></pre> Bloc de code
<abbr title="HyperText Markup Language">HTML</abbr>
<sup>exposant</sup> <sub>indice</sub>
<del>supprimé</del> <ins>ajouté</ins>
<!-- Listes -->
<ul><li>Non ordonné</li></ul>
<ol><li>Ordonné (1. 2. 3.)</li></ol>
<dl><dt>Terme</dt><dd>Définition</dd></dl>
<!-- Lien externe -->
<a href="https://exemple.com"
target="_blank"
rel="noopener noreferrer">
Ouvrir dans un onglet
</a>
<!-- rel="noopener" = sécurité (tabnapping) -->
<!-- Lien interne (ancre) -->
<a href="#section-id">Aller à la section</a>
<!-- Lien relatif -->
<a href="../about/index.html">À propos</a>
<!-- Lien email / téléphone -->
<a href="mailto:contact@site.com">Email</a>
<a href="tel:+3200000000">Appeler</a>
<!-- Lien téléchargement -->
<a href="rapport.pdf" download>
Télécharger le PDF
</a>
<!-- Image cliquable -->
<a href="/">
<img src="logo.svg" alt="Accueil"/>
</a>
Images & médias
<!-- Image simple -->
<img
src="photo.jpg"
alt="Description de l'image" <!-- OBLIGATOIRE -->
width="800"
height="600" <!-- évite le layout shift -->
loading="lazy" <!-- chargement différé -->
/>
<!-- Image responsive avec srcset -->
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, 800px"
alt="..."
/>
<!-- Figure avec légende -->
<figure>
<img src="graph.png" alt="Graphique des ventes"/>
<figcaption>Ventes T3 2024</figcaption>
</figure>
<!-- Vidéo HTML5 -->
<video
controls
autoplay
muted
loop
poster="thumbnail.jpg"
width="100%"
>
<source src="video.mp4" type="video/mp4"/>
<source src="video.webm" type="video/webm"/>
Votre navigateur ne supporte pas la vidéo.
</video>
<!-- Audio -->
<audio controls src="audio.mp3"></audio>
<!-- YouTube embedé (iFrame) -->
<iframe
src="https://www.youtube.com/embed/ID"
title="Description de la vidéo"
allowfullscreen
loading="lazy"
></iframe>
<!-- Formats recommandés :
Images : WebP (moderne) > AVIF > JPEG/PNG
Vidéo : MP4 (H.264) + WebM (VP9)
Icônes : SVG (scalable, léger) -->
Tableaux HTML
<table>
<caption>Résultats du semestre</caption>
<thead>
<tr>
<th scope="col">Cours</th>
<th scope="col">Note</th>
<th scope="col">Résultat</th>
</tr>
</thead>
<tbody>
<tr>
<td>Réseaux</td>
<td>15/20</td>
<td>Réussi</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Moyenne</td>
<td>14.2/20</td>
</tr>
</tfoot>
</table>
<!-- colspan="2" : fusionne 2 colonnes
rowspan="2" : fusionne 2 lignes
scope="col/row" : accessibilité lecteur d'écran -->
Tableaux ≠ mise en page. Les tableaux servent à présenter des données tabulaires. N'utiliser jamais <table> pour faire de la mise en page (colonnes, layouts) — c'est une pratique des années 2000. Utiliser Flexbox ou Grid à la place.
table {
border-collapse: collapse; /* fusionner les bordures */
width: 100%;
}
th, td {
padding: .6rem 1rem;
border: 1px solid #e2e8f0;
text-align: left;
}
th {
background: #f8fafc;
font-weight: bold;
}
/* Zébré — lignes alternées */
tr:nth-child(even) td {
background: #f1f5f9;
}
Formulaires
<form
action="/submit"
method="post"
novalidate <!-- validation gérée en JS -->
>
<fieldset>
<legend>Informations personnelles</legend>
<label for="nom">Nom *</label>
<input
id="nom" type="text"
name="nom"
placeholder="Dupont"
required
autocomplete="family-name"
/>
<label for="email">Email *</label>
<input
id="email" type="email"
name="email" required
/>
<label for="message">Message</label>
<textarea id="message" name="message"
rows="4"></textarea>
</fieldset>
<button type="submit">Envoyer</button>
</form>
<!-- Texte -->
<input type="text"/> champ libre
<input type="email"/> validation email
<input type="password"/> masqué
<input type="search"/> avec bouton reset
<input type="url"/> URL valide
<input type="tel"/> téléphone
<!-- Numérique -->
<input type="number" min="0" max="100"/>
<input type="range" min="0" max="10"/>
<!-- Date & temps -->
<input type="date"/> sélecteur de date
<input type="time"/>
<input type="datetime-local"/>
<!-- Sélection -->
<input type="checkbox"/> case à cocher
<input type="radio"/> bouton radio
<input type="color"/> sélecteur couleur
<input type="file"/> upload fichier
<input type="hidden"/> données cachées
<!-- Liste déroulante -->
<select name="pays">
<option value="be">Belgique</option>
<option value="fr" selected>France</option>
</select>
Head & méta-données
<head>
<!-- Encodage et viewport -->
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<!-- SEO -->
<title>Page | Site</title>
<meta name="description" content="Description courte (150-160 chars)"/>
<link rel="canonical" href="https://mon-site.com/page"/>
<!-- Open Graph (partage Facebook, LinkedIn, Discord…) -->
<meta property="og:title" content="Titre pour les réseaux"/>
<meta property="og:description" content="Résumé pour les réseaux"/>
<meta property="og:image" content="https://mon-site.com/og.jpg"/>
<meta property="og:url" content="https://mon-site.com/page"/>
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image"/>
<!-- Favicon -->
<link rel="icon" href="/favicon.ico"/>
<link rel="icon" href="/icon.svg" type="image/svg+xml"/>
<link rel="apple-touch-icon" href="/apple-icon.png"/>
<!-- CSS -->
<link rel="stylesheet" href="style.css"/>
</head>
Sélecteurs CSS
/* ─── Sélecteurs de base ─────────────────── */
* { } /* universel — tous les éléments */
p { } /* élément (type) */
.classe { } /* classe */
#identifiant{ } /* id — unique, spécificité élevée */
/* ─── Combinateurs ──────────────────────── */
div p { } /* descendant (p dans div) */
div > p { } /* enfant direct uniquement */
h2 + p { } /* frère adjacent (juste après h2) */
h2 ~ p { } /* tous les frères p après h2 */
/* ─── Attributs ─────────────────────────── */
a[href] { } /* a avec attribut href */
a[href="url"] { } /* valeur exacte */
a[href^="https"]{ } /* commence par */
a[href$=".pdf"] { } /* finit par */
a[href*="wiki"] { } /* contient */
input[type="email"]{ }
/* ─── Groupement ────────────────────────── */
h1, h2, h3 { font-family: sans-serif; }
/* ─── États ─────────────────────────────── */
a:hover { } /* souris dessus */
a:focus { } /* focus clavier (accessibilité !) */
a:active { } /* clic en cours */
a:visited { } /* lien déjà visité */
input:focus { outline: 2px solid blue; }
input:valid { border-color: green; }
input:invalid { border-color: red; }
input:disabled { opacity: .5; }
/* ─── Structurelles ─────────────────────── */
li:first-child { } /* premier enfant */
li:last-child { } /* dernier enfant */
li:nth-child(2) { } /* 2e enfant */
li:nth-child(odd) { } /* impairs (1, 3, 5…) */
li:nth-child(3n) { } /* multiples de 3 */
p:not(.special) { } /* tout sauf .special */
:is(h1, h2, h3) { } /* groupe avec même spécificité */
/* ─── Pseudo-éléments ───────────────────── */
p::first-line { font-weight: bold; }
p::first-letter { font-size: 2em; } /* lettrine */
.item::before { content: "→ "; }
.item::after { content: " ✓"; color: green; }
::selection { background: yellow; } /* texte sélectionné */
::placeholder { color: gray; }
Spécificité & cascade
Quand plusieurs règles s'appliquent au même élément, la spécificité détermine laquelle gagne. Elle se calcule avec 3 compteurs A-B-C (comme un nombre à 3 chiffres).
A = styles inline / !important
B = ids
C = classes, attributs, pseudo-classes
D (non montré) = éléments, pseudo-éléments
À spécificité égale, la règle déclarée en dernier gagne.
/* Ordre de priorité (du plus faible au plus fort) :
1. Styles du navigateur (user-agent stylesheet)
2. Styles de l'auteur (ton fichier CSS)
3. Styles de l'utilisateur (préférences navigateur)
4. !important de l'auteur
5. !important de l'utilisateur
Dans les styles de l'auteur, la priorité est :
a. Origine (où la règle est définie)
b. Spécificité du sélecteur
c. Ordre d'apparition (last wins) */
/* ✗ ÉVITER !important */
.bouton { color: red !important; }
/* Casse la cascade → cauchemar à maintenir */
/* ✓ PRÉFÉRER augmenter la spécificité */
.nav .bouton { color: red; }
:where(.nav) .bouton { color: red; } /* spécificité 0 */
/* Héritage : certaines propriétés se propagent
aux enfants automatiquement :
color, font-*, line-height, cursor, visibility
Les propriétés de boîte (margin, padding, border)
ne s'héritent PAS.
Forcer l'héritage : */
.enfant { color: inherit; border: inherit; }
Box model
Chaque élément HTML est une boîte rectangulaire composée de quatre couches. Comprendre le box model est fondamental pour maîtriser l'espacement et la taille des éléments.
width × height
/* Par défaut (content-box) — confusant ! */
.box {
width: 200px;
padding: 20px;
border: 2px solid black;
/* Largeur réelle = 200 + 20*2 + 2*2 = 244px !! */
}
/* ✓ TOUJOURS utiliser border-box */
*, *::before, *::after {
box-sizing: border-box;
/* Largeur réelle = 200px (padding et border inclus) */
}
/* Marges automatiques — centrer un bloc */
.centré {
width: 600px;
margin: 0 auto; /* haut/bas=0, gauche/droite=auto */
}
/* Raccourcis margin/padding */
.el {
margin: 1rem; /* tous les côtés */
margin: 1rem 2rem; /* haut/bas | gauche/droite */
margin: 1rem 2rem 3rem; /* haut | côtés | bas */
margin: 1rem 2rem 3rem 4rem; /* haut droite bas gauche */
}
Positionnement
| Valeur | Comportement | Cas d'usage |
|---|---|---|
static |
Défaut — flux normal, top/left ignorés | La majorité des éléments |
relative |
Décalé depuis sa position normale — garde sa place dans le flux | Créer un contexte de positionnement parent |
absolute |
Sorti du flux — positionné par rapport au parent relative le plus proche |
Badges, tooltips, menus flottants |
fixed |
Sorti du flux — positionné par rapport à la fenêtre. Ne bouge pas au scroll | Navbar collante, bouton "retour en haut" |
sticky |
Relatif jusqu'à un seuil scroll, puis se fixe. Reste dans le flux | En-têtes de tableaux, menu secondaire |
/* Badge sur une carte */
.carte { position: relative; }
.badge {
position: absolute;
top: -8px; right: -8px;
/* Se positionne par rapport à .carte */
}
/* Navbar collante */
nav {
position: sticky;
top: 0; /* se fixe quand il atteint le haut */
z-index: 100;
}
/* Centrage absolu (remplacé par flex aujourd'hui) */
.parent { position: relative; }
.enfant {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
/* z-index — empilement */
.modal-overlay { z-index: 1000; position: fixed; }
.modal { z-index: 1001; position: fixed; }
/* z-index ne fonctionne que sur les éléments
positionnés (pas static) */
Variables CSS (Custom Properties)
/* ─── Déclaration dans :root (globale) ──── */
:root {
/* Couleurs */
--couleur-primaire: #3b82f6;
--couleur-texte: #1e293b;
--couleur-fond: #f8fafc;
/* Espacements */
--espace-sm: .5rem;
--espace-md: 1rem;
--espace-lg: 2rem;
/* Typographie */
--font-titre: 'Outfit', sans-serif;
--taille-base: 1rem;
/* Bordures */
--rayon: 8px;
--ombre: 0 2px 8px rgba(0,0,0,.1);
}
/* ─── Utilisation ─────────────────────── */
.bouton {
background: var(--couleur-primaire);
padding: var(--espace-sm) var(--espace-md);
border-radius: var(--rayon);
font-family: var(--font-titre);
/* Valeur de secours si la variable n'existe pas */
color: var(--couleur-texte, black);
}
:root {
--bg: #ffffff;
--texte: #1e293b;
--carte: #f1f5f9;
}
/* Redéfinir les variables en dark mode */
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a;
--texte: #e2e8f0;
--carte: #1e293b;
}
}
/* Tout le CSS utilise les mêmes variables */
body { background: var(--bg); color: var(--texte); }
.carte { background: var(--carte); }
/* → Changement de thème entier sans changer le CSS ! */
/* Modifier une variable localement */
.section-hero {
--couleur-primaire: #ec4899; /* rose pour cette section seulement */
background: var(--couleur-primaire);
}
/* Manipuler depuis JavaScript */
// JS
document.documentElement.style
.setProperty('--couleur-primaire', '#10b981');
Flexbox
Flexbox est un système de layout unidimensionnel (une rangée ou une colonne). Idéal pour aligner des éléments sur un axe, distribuer l'espace, et construire des navbars, cartes, et composants.
.container {
display: flex; /* activer flexbox */
/* Direction */
flex-direction: row; /* défaut — ligne */
flex-direction: column; /* colonne */
flex-direction: row-reverse;
/* Retour à la ligne */
flex-wrap: nowrap; /* défaut */
flex-wrap: wrap; /* passe à la ligne si besoin */
/* Alignement axe principal (→ en row) */
justify-content: flex-start; /* défaut */
justify-content: center;
justify-content: flex-end;
justify-content: space-between; /* espaces entre */
justify-content: space-around; /* espaces autour */
justify-content: space-evenly; /* espaces égaux */
/* Alignement axe transversal (↓ en row) */
align-items: stretch; /* défaut — s'étire */
align-items: center;
align-items: flex-start;
align-items: flex-end;
align-items: baseline;
gap: 1rem; /* espacement entre éléments */
gap: 1rem 2rem; /* rangée | colonne */
}
.item {
/* flex = grow shrink basis */
flex: 1; /* 1 1 0 — prend l'espace disponible */
flex: auto; /* 1 1 auto */
flex: none; /* 0 0 auto — taille fixe */
flex: 0 0 200px; /* largeur fixe 200px */
flex-grow: 1; /* coefficient d'expansion */
flex-shrink: 0; /* ne rétrécit pas */
flex-basis: 200px; /* taille de départ */
align-self: center; /* override align-items */
order: 2; /* ordre d'affichage */
}
/* ─── Patterns courants ──────────────── */
/* Centrer parfaitement */
.centré {
display: flex;
justify-content: center;
align-items: center;
}
/* Navbar : logo à gauche, liens à droite */
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Footer collant (sticky footer) */
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main { flex: 1; } /* prend tout l'espace */
Démonstration — flex avec gap et justify-content: space-between
CSS Grid
CSS Grid est un système de layout bidimensionnel (lignes ET colonnes simultanément). Parfait pour les mises en page de page entière, galeries et tout layout complexe en deux dimensions.
.grille {
display: grid;
/* Définir les colonnes */
grid-template-columns: 200px 1fr 1fr;
grid-template-columns: repeat(3, 1fr); /* 3 colonnes égales */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* ↑ responsive : autant de colonnes que possible ≥ 200px */
/* Définir les lignes */
grid-template-rows: auto 1fr auto; /* header, content, footer */
/* Layout nommé avec template areas */
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 1rem; /* espace entre toutes les cellules */
row-gap: 1rem; /* espace entre lignes seulement */
column-gap: 2rem;/* espace entre colonnes seulement */
/* Alignement de tout le contenu */
justify-items: stretch; /* horizontal dans chaque cellule */
align-items: start; /* vertical dans chaque cellule */
}
/* Avec grid-area (si template-areas défini) */
header { grid-area: header; }
.sidebar{ grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
/* Avec les lignes de grille (plus précis) */
.hero {
grid-column: 1 / -1; /* toute la largeur */
grid-row: 1 / 3; /* de ligne 1 à 3 */
}
.carte-large {
grid-column: span 2; /* s'étend sur 2 colonnes */
}
/* Layout classique header/sidebar/main/footer */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
grid-template-areas:
"header header"
"sidebar main "
"footer footer";
}
Grid 3 colonnes — span complet sur première ligne
Responsive & media queries
/* ─── Mobile first : on part du plus petit ─ */
/* Styles de base — mobile */
.grille {
display: flex;
flex-direction: column;
gap: 1rem;
}
/* Tablette ≥ 768px */
@media (min-width: 768px) {
.grille {
flex-direction: row;
}
}
/* Desktop ≥ 1024px */
@media (min-width: 1024px) {
.grille {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
/* Autres types de media queries */
@media (prefers-color-scheme: dark) { }
@media (prefers-reduced-motion: reduce){ }
@media (orientation: landscape) { }
@media print { }
@media (min-width: 600px) and
(max-width: 900px) { }
/* ─── Unités relatives ─────────────────── */
.el {
font-size: 1rem; /* par rapport à la racine (html) */
font-size: 1.2em; /* par rapport au parent direct */
font-size: 2vw; /* 2% de la largeur de viewport */
font-size: 2vh; /* 2% de la hauteur de viewport */
width: 50%; /* 50% du parent */
}
/* ─── Taille de police fluide ───────────── */
html {
font-size: clamp(14px, 2vw, 18px);
/* min=14px, idéal=2vw, max=18px */
}
/* ─── Grille responsive sans media queries ─ */
.auto-grille {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(250px, 1fr));
/* Crée autant de colonnes ≥ 250px que possible */
}
/* Container queries (CSS moderne) */
.parent { container-type: inline-size; }
@container (min-width: 400px) {
.enfant { font-size: 1.2rem; }
}
Transitions
Les transitions animent le passage d'un état CSS à un autre (au hover, au focus…). Elles sont simples, performantes, et parfaites pour les micro-interactions.
.bouton {
background: #3b82f6;
transform: scale(1);
box-shadow: none;
/* transition: propriété durée timing délai */
transition: background .2s ease,
transform .2s ease,
box-shadow .2s ease;
/* Ou toutes les propriétés en même temps */
transition: all .2s ease;
}
.bouton:hover {
background: #2563eb;
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(59,130,246,.4);
}
/* ─── Timing functions ──────────────────── */
.a { transition-timing-function: ease; } /* défaut */
.b { transition-timing-function: ease-in; } /* accélère */
.c { transition-timing-function: ease-out; } /* décélère */
.d { transition-timing-function: ease-in-out; } /* les deux */
.e { transition-timing-function: linear; } /* constant */
.f { transition-timing-function:
cubic-bezier(.34, 1.56, .64, 1); } /* rebond */
/* ✓ PERFORMANTES — GPU, pas de reflow */
transform: translateX(20px); /* déplacement */
transform: scale(1.1); /* agrandissement */
transform: rotate(45deg); /* rotation */
transform: skew(10deg); /* inclinaison */
opacity: 0; /* fondu */
filter: blur(4px); /* flou */
/* ✗ À ÉVITER — causent un reflow (lent) */
width: 100px; /* recalcule le layout */
height: 100px;
top: 20px;
left: 20px;
margin: 1rem;
/* ─── Apparition d'un modal ──────────────── */
.modal {
opacity: 0;
transform: scale(.95) translateY(-10px);
transition: opacity .2s ease,
transform .2s ease;
pointer-events: none;
}
.modal.visible {
opacity: 1;
transform: scale(1) translateY(0);
pointer-events: auto;
}
Animations & @keyframes
Les animations CSS permettent des effets autonomes — elles se déclenchent sans interaction, peuvent boucler, et contrôlent précisément chaque étape avec @keyframes.
/* Définir l'animation */
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: .5; transform: scale(.9); }
}
@keyframes apparition {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes progress-bar {
from { width: 0%; }
to { width: 100%; }
}
/* Appliquer l'animation */
.loader {
animation-name: pulse;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-delay: .5s;
animation-fill-mode: both;
/* Raccourci : name durée timing delay count direction fill */
animation: pulse 2s ease-in-out 0s infinite alternate both;
}
/* animation-iteration-count */
animation-iteration-count: 1; /* une fois */
animation-iteration-count: 3; /* 3 fois */
animation-iteration-count: infinite; /* infini */
/* animation-direction */
animation-direction: normal; /* → */
animation-direction: reverse; /* ← */
animation-direction: alternate; /* → puis ← */
animation-direction: alternate-reverse;
/* animation-fill-mode */
animation-fill-mode: none; /* retour état initial */
animation-fill-mode: forwards; /* reste à l'état final */
animation-fill-mode: backwards;/* commence à l'état 0% pendant le délai */
animation-fill-mode: both; /* forwards + backwards */
/* Contrôler depuis JS */
el.style.animationPlayState = 'paused';
el.style.animationPlayState = 'running';
/* Respecter les préférences */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
transition-duration: .01ms !important;
}
}
Pseudo-classes & astuces avancées
/* :is() — simplifie les groupements */
/* Avant : */
header a, footer a, nav a { color: blue; }
/* Après : */
:is(header, footer, nav) a { color: blue; }
/* :where() — même chose, spécificité = 0 */
:where(header, footer) a { color: blue; }
/* :has() — sélectionner le parent */
figure:has(figcaption) { border: 1px solid; }
/* figure qui contient une figcaption */
form:has(input:invalid) { border-color: red; }
/* formulaire avec un input invalide */
li:has(+ li) { margin-bottom: .5rem; }
/* li qui n'est pas le dernier */
/* :not() — exclusion */
a:not([href]) { color: gray; } /* sans href */
p:not(:last-child) { margin-bottom: 1rem; }
/* Tronquer le texte avec ellipsis */
.tronqué {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
}
/* Tronquer sur N lignes */
.tronqué-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* Ratio d'aspect */
.video-wrap { aspect-ratio: 16 / 9; }
.avatar { aspect-ratio: 1; border-radius: 50%; }
/* Scroll snapping */
.slider {
overflow-x: scroll;
scroll-snap-type: x mandatory;
}
.slide { scroll-snap-align: start; }
/* Gradient sur du texte */
.titre-dégradé {
background: linear-gradient(90deg, #f472b6, #818cf8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
Cheat sheet
Balises HTML clés
| Structure | header, main, footer, nav, section, article, aside |
| Titres | h1–h6 (ne pas sauter) |
| Texte | p, strong, em, code, pre, mark |
| Listes | ul/ol > li, dl > dt/dd |
| Médias | img (alt !), video, audio, figure |
| Formulaires | form, label, input, select, textarea, button |
Unités CSS
| rem | Relatif à html (root) — préférer |
| em | Relatif au parent direct |
| % | Relatif au parent |
| vw / vh | % largeur / hauteur viewport |
| px | Absolu — éviter pour la typo |
| clamp() | min, valeur fluide, max |
Flexbox rapide
| display: flex | Activer |
| flex-direction | row / column |
| justify-content | Axe principal |
| align-items | Axe transversal |
| flex: 1 | Prend l'espace dispo |
| gap | Espace entre items |
Grid rapide
| display: grid | Activer |
| grid-template-columns | Définir colonnes |
| repeat(3, 1fr) | 3 colonnes égales |
| auto-fit + minmax | Responsive auto |
| grid-column: 1/-1 | Pleine largeur |
| grid-area | Template areas |