Développement Web

HTML
& CSS

Structure, sémantique, mise en page, Flexbox, Grid, animations — des bases aux astuces intermédiaires.

Structure & doctype

page.html — squelette minimal
<!-- 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.

Structure sémantique type
<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

Balises de texte courantes
<!-- 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>
Liens — toutes les variantes
<!-- 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

Images — bonnes pratiques
<!-- 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, audio, iFrame
<!-- 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

Tableau sémantique complet
<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.

CSS — styliser un tableau
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

Formulaire complet — accessibilité incluse
<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>
Types d'inputs — cheat sheet
<!-- 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>

Sélecteurs CSS

Sélecteurs — du plus simple au plus puissant
/* ─── 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; }
Pseudo-classes & pseudo-éléments
/* ─── É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).

0
·
0
·
1
p { } élément seul
0
·
1
·
0
.classe { } classe / attribut / pseudo-classe
0
·
1
·
1
p.classe { } élément + classe
0
·
2
·
1
.nav a:hover { } classe + élément + pseudo-classe
1
·
0
·
0
#id { } identifiant — très fort
·
·
style="…" / !important éviter absolument
💡

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 la cascade CSS
/* 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.

MARGIN — espace extérieur (transparent)
BORDER — bordure visible
PADDING — espace intérieur
CONTENU
width × height
box-sizing — la propriété à toujours définir
/* 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

ValeurComportementCas 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
Positionnement — patterns courants
/* 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éclarer et utiliser des variables
/* ─── 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);
}
Dark mode avec variables
: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.

Propriétés du conteneur
.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 */
}
Propriétés des enfants (flex items)
.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

Item 1
Item 2
Item 3
Item 4

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.

Syntaxe — conteneur Grid
.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 */
}
Placer les éléments dans la grille
/* 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

Header (grid-column: 1 / -1)
Sidebar
Main (span 2)
Footer (1 / -1)

Responsive & media queries

Media queries — approche mobile-first
/* ─── 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 & fluides
/* ─── 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.

Syntaxe et timing functions
.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 */
Propriétés performantes à animer
/* ✓ 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.

pulse
spin
bounce
shake
@keyframes — définir une animation
/* 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;
}
Paramètres clés
/* 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

Pseudo-classes modernes utiles
/* :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; }
Astuces CSS pratiques
/* 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

Structureheader, main, footer, nav, section, article, aside
Titresh1–h6 (ne pas sauter)
Textep, strong, em, code, pre, mark
Listesul/ol > li, dl > dt/dd
Médiasimg (alt !), video, audio, figure
Formulairesform, label, input, select, textarea, button

Unités CSS

remRelatif à html (root) — préférer
emRelatif au parent direct
%Relatif au parent
vw / vh% largeur / hauteur viewport
pxAbsolu — éviter pour la typo
clamp()min, valeur fluide, max

Flexbox rapide

display: flexActiver
flex-directionrow / column
justify-contentAxe principal
align-itemsAxe transversal
flex: 1Prend l'espace dispo
gapEspace entre items

Grid rapide

display: gridActiver
grid-template-columnsDéfinir colonnes
repeat(3, 1fr)3 colonnes égales
auto-fit + minmaxResponsive auto
grid-column: 1/-1Pleine largeur
grid-areaTemplate areas