Partie 2 — Mise en page avancée avec CSS Box Model, Flexbox, Grid, Formulaires, Responsive, Animations


📑 Sommaire de la Partie 2


8. Comprendre et utiliser le modèle de boîte (Box Model)

8.1. Qu'est-ce que le Box Model ?

En CSS, tous les éléments HTML sont des boîtes rectangulaires. Le Box Model est le concept fondamental qui définit comment ces boîtes sont dimensionnées et comment l'espace est calculé autour d'elles. C'est la base de toute mise en page en CSS.

+-------------------------------------------------------+ | MARGIN (espace externe) | | ┌───────────────────────────────────────────────┐ | | │ BORDER (bordure) │ | | │ ┌───────────────────────────────────────┐ │ | | │ │ PADDING (espace interne) │ │ | | │ │ ┌───────────────────────────────┐ │ │ | | │ │ │ CONTENT (contenu) │ │ │ | | │ │ │ "Texte ou image" │ │ │ | | │ │ └───────────────────────────────┘ │ │ | | │ └───────────────────────────────────────┘ │ | | └───────────────────────────────────────────────┘ | +-------------------------------------------------------+

Le Box Model se compose de 4 couches (de l'intérieur vers l'extérieur) :

  • Content (contenu) : Le contenu réel de l'élément (texte, image, etc.).
  • Padding (espace interne) : L'espace entre le contenu et la bordure.
  • Border (bordure) : La ligne qui entoure le padding.
  • Margin (marge externe) : L'espace entre la bordure et les autres éléments.

8.2. Les propriétés du Box Model en détail

Propriété Description Exemple Valeurs typiques
content Le contenu interne width: 200px; px, %, em, rem, auto
padding Espace intérieur entre contenu et bordure padding: 20px; padding: 10px 20px; (haut/bas, gauche/droite)
border La bordure autour du padding border: 2px solid #333; solid, dashed, dotted, double
margin Espace extérieur entre la boîte et les autres éléments margin: 10px; auto (centrage horizontal)

8.2.1. Les raccourcis (shorthands)

Pour padding et margin, il existe des syntaxes raccourcies qui permettent de définir plusieurs côtés en une seule ligne :

/* Tous les côtés */
padding: 20px;

/* Haut + Bas | Gauche + Droite */
padding: 10px 20px;

/* Haut | Gauche + Droite | Bas */
padding: 10px 20px 30px;

/* Haut | Droite | Bas | Gauche (sens horaire) */
padding: 10px 15px 20px 25px;

/* Version explicite (équivalent) */
padding-top: 10px;
padding-right: 15px;
padding-bottom: 20px;
padding-left: 25px;

8.3. La propriété box-sizing — le concept le plus important

Par défaut (box-sizing: content-box), la largeur totale d'une boîte est :

Largeur _ totale = width + padding _ gauche + padding _ droite + border _ gauche + border _ droite
⚠️ Problème : Une boîte de width: 200px avec padding: 20px et border: 2px aura une largeur réelle de 244px ! Cela rend les calculs de mise en page très difficiles, surtout en responsive.

La solution : utiliser box-sizing: border-box, qui inclut le padding et la bordure dans la largeur définie.

Largeur _ totale = width ( inclut _ padding + border )
/* Règle universelle — À mettre en premier dans votre CSS */
* {
    box-sizing: border-box;
}
✅ Pourquoi border-box est recommandé ?
  • Plus intuitif : si vous définissez width: 200px, la boîte fait 200px, quel que soit le padding.
  • Facilite la conception responsive : les calculs sont plus simples.
  • Adopté par la majorité des frameworks CSS (Bootstrap, Tailwind, Foundation, etc.).
  • Évite les surprises lors de l'ajout de padding ou de bordures.

8.4. Le phénomène de fusion des marges (margin collapsing)

En CSS, les marges verticales de deux éléments adjacents se fusionnent. La marge résultante est égale à la plus grande des deux marges.

+------------------------------------------+ | Élément A (margin-bottom: 30px) | | ┌──────────────────────────────────┐ | | │ │ | | └──────────────────────────────────┘ | | ← 30px → | | ═══════════════════════════════════════ | | ← 20px → (se fusionne avec 30px) | | Élément B (margin-top: 20px) | | ┌──────────────────────────────────┐ | | │ │ | | └──────────────────────────────────┘ | | | | Résultat : espace entre A et B = 30px | +------------------------------------------+
/* Exemple de fusion des marges */
.element-a {
    margin-bottom: 30px;
}

.element-b {
    margin-top: 20px;
}

/* L'espace entre A et B sera de 30px, pas 50px ! */
💡 Astuce : Pour éviter la fusion des marges, vous pouvez :
  • Utiliser padding à la place de margin.
  • Ajouter border ou padding sur le parent.
  • Utiliser display: flex ou display: grid sur le parent.
  • Utiliser overflow: hidden ou overflow: auto sur le parent.

9. Créer des mises en page flexibles avec Flexbox

9.1. Qu'est-ce que Flexbox ?

Flexbox (CSS Flexible Box Layout) est un module CSS qui a révolutionné la mise en page. Avant Flexbox, on utilisait des float, display: table ou position avec des calculs complexes. Flexbox simplifie radicalement l'alignement et la distribution d'espace.

Flexbox permet de répartir l'espace et d'aligner les éléments dans un conteneur sur un seul axe (horizontal ou vertical). C'est parfait pour :

  • Les menus de navigation (alignement horizontal).
  • Les barres d'outils.
  • Les cartes avec disposition flexible.
  • Le centrage vertical et horizontal.
  • Les listes d'éléments de taille variable.

9.2. Les deux axes de Flexbox

+---------------------------------------------------+ | Axe principal (défini par flex-direction) | | ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← | | | | ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ | | │ Élmt │ │ Élmt │ │ Élmt │ │ Élmt │ | | │ 1 │ │ 2 │ │ 3 │ │ 4 │ | | └─────┘ └─────┘ └─────┘ └─────┘ | | ↑ | | Axe secondaire (cross axis) | +---------------------------------------------------+
  • Axe principal (main axis) : Direction dans laquelle les éléments sont disposés.
  • Axe secondaire (cross axis) : Direction perpendiculaire à l'axe principal.

9.3. Activation de Flexbox

.conteneur-flex {
    display: flex;  /* Active le mode Flexbox */
}

9.4. Propriétés du conteneur Flex

Propriété Valeurs courantes Effet
flex-direction row (défaut), column, row-reverse, column-reverse Définit l'axe principal (direction des éléments)
justify-content flex-start, flex-end, center, space-between, space-around, space-evenly Aligne les éléments sur l'axe principal
align-items stretch (défaut), flex-start, flex-end, center, baseline Aligne les éléments sur l'axe secondaire
flex-wrap nowrap (défaut), wrap, wrap-reverse Permet le retour à la ligne lorsque les éléments ne rentrent pas
gap 10px, 1em, 5% Espace entre les éléments (équivalent à row-gap et column-gap)
align-content stretch, center, space-between, space-around Aligne les lignes sur l'axe secondaire (quand flex-wrap: wrap)

9.4.1. Visualisation de justify-content

🎯 Les différentes valeurs de justify-content :

  • flex-start → éléments alignés au début (à gauche).
  • flex-end → éléments alignés à la fin (à droite).
  • center → éléments centrés.
  • space-between → espace égal entre les éléments (1er à gauche, dernier à droite).
  • space-around → espace égal autour de chaque élément.
  • space-evenly → espace parfaitement égal partout.

9.5. Propriétés des éléments Flex

Propriété Valeurs Effet
flex-grow Nombre (0 par défaut) Capacité d'un élément à grandir pour occuper l'espace disponible
flex-shrink Nombre (1 par défaut) Capacité d'un élément à rétrécir si l'espace manque
flex-basis auto, 200px, 50% Taille de base de l'élément avant distribution de l'espace
flex 1 (équivaut à 1 1 0) Raccourci pour flex-grow flex-shrink flex-basis
align-self auto, center, flex-start, flex-end Override align-items pour un élément spécifique
order Nombre (0 par défaut) Modifie l'ordre d'affichage (ordre numérique)

9.6. Exemple complet : Barre de navigation avec Flexbox

<nav class="navbar">
    <div class="logo">🚀 MonSite</div>

    <ul class="menu">
        <li><a href="#">Accueil</a></li>
        <li><a href="#">Services</a></li>
        <li><a href="#">À propos</a></li>
        <li><a href="#">Contact</a></li>
    </ul>

    <div class="auth">
        <a href="#" class="btn-connexion">Se connecter</a>
        <a href="#" class="btn-inscription">S'inscrire</a>
    </div>
</nav>
.navbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: #1a1a2e;
    padding: 16px 40px;
    color: white;
    box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}

.logo {
    font-size: 24px;
    font-weight: 700;
}

.menu {
    display: flex;
    list-style: none;
    gap: 30px;
}

.menu a {
    color: rgba(255,255,255,0.8);
    text-decoration: none;
    font-weight: 500;
    transition: color 0.3s, border-color 0.3s;
    border-bottom: 2px solid transparent;
    padding: 6px 0;
}

.menu a:hover {
    color: white;
    border-bottom-color: #4361ee;
}

.auth {
    display: flex;
    gap: 12px;
}

.btn-connexion {
    color: white;
    text-decoration: none;
    padding: 8px 20px;
    border: 1px solid rgba(255,255,255,0.3);
    border-radius: 50px;
    transition: background 0.3s;
}

.btn-connexion:hover {
    background: rgba(255,255,255,0.1);
}

.btn-inscription {
    color: white;
    text-decoration: none;
    padding: 8px 20px;
    background: #4361ee;
    border-radius: 50px;
    transition: background 0.3s, transform 0.2s;
}

.btn-inscription:hover {
    background: #3a0ca3;
    transform: scale(1.04);
}
💡 Astuce Flexbox : Utilisez gap plutôt que margin pour espacer les éléments Flex. C'est plus propre et cela évite les problèmes de marges qui s'accumulent. gap est supporté dans tous les navigateurs modernes.

10. Créer des mises en page en 2D avec CSS Grid

10.1. Qu'est-ce que CSS Grid ?

CSS Grid est un système de mise en page bidimensionnel. Contrairement à Flexbox (1D), Grid permet de contrôler à la fois les lignes et les colonnes simultanément. C'est idéal pour les mises en page complexes comme les tableaux de bord, les galeries, ou les interfaces d'administration.

+-----------------------------------------------+ | Grille 3 colonnes × 3 lignes | | ┌─────┬─────┬─────┐ | | │ 1,1 │ 1,2 │ 1,3 │ | | ├─────┼─────┼─────┤ | | │ 2,1 │ 2,2 │ 2,3 │ | | ├─────┼─────┼─────┤ | | │ 3,1 │ 3,2 │ 3,3 │ | | └─────┴─────┴─────┘ | | | | Un élément peut occuper plusieurs cellules | | ┌─────────┬─────┬─────┐ | | │ 1,1 │ 1,2 │ 1,3 │ | | │ (sur 2 ├─────┼─────┤ | | │ colonnes)│ 2,2 │ 2,3 │ | | ├─────────┴─────┴─────┤ | | │ 3,1 │ 3,2 │ 3,3 │ | | └─────────────────────┘ | +-----------------------------------------------+

10.2. Activation de Grid

.conteneur-grid {
    display: grid;
}

10.3. Propriétés du conteneur Grid

Propriété Valeurs courantes Effet
grid-template-columns 200px 1fr 200px, repeat(3, 1fr) Définit les colonnes et leur taille
grid-template-rows auto 200px auto, minmax(100px, auto) Définit les lignes et leur taille
gap 20px, 10px 20px Espace entre les cellules (lignes et colonnes)
grid-auto-rows 200px, minmax(100px, auto) Taille par défaut des lignes créées automatiquement
grid-auto-columns 200px Taille par défaut des colonnes créées automatiquement
grid-template-areas "header header header"
"sidebar main main"
"footer footer footer"
Définit des zones nommées pour une mise en page
justify-items start, end, center, stretch Aligne le contenu horizontalement dans les cellules
align-items start, end, center, stretch Aligne le contenu verticalement dans les cellules

10.4. Les unités spécifiques à Grid

10.4.1. L'unité fr (fraction)

L'unité fr représente une fraction de l'espace disponible dans le conteneur Grid. C'est l'équivalent de "parts" dans un partage équitable.

Répartition de l'espace avec les unités fr

1 f r + 2 f r + 1 f r = 4 f r

Chaque 1fr = 14 de l'espace total

/* 3 colonnes : 1fr, 2fr, 1fr */
grid-template-columns: 1fr 2fr 1fr;

/* 4 colonnes égales */
grid-template-columns: repeat(4, 1fr);

/* 2 colonnes : 200px, puis le reste */
grid-template-columns: 200px 1fr;

10.4.2. La fonction repeat()

repeat() permet de répéter un motif de colonnes ou de lignes sans avoir à le réécrire plusieurs fois.

/* Équivalent à : 1fr 1fr 1fr 1fr 1fr */
grid-template-columns: repeat(5, 1fr);

/* Équivalent à : 100px 200px 100px 200px 100px 200px */
grid-template-columns: repeat(3, 100px 200px);

/* Combinaison avec d'autres valeurs */
grid-template-columns: 200px repeat(3, 1fr) 100px;

10.4.3. La fonction minmax()

minmax() définit une taille minimale et une taille maximale pour une colonne ou une ligne.

/* Colonne qui fait au moins 100px et au plus 1fr */
grid-template-columns: minmax(100px, 1fr);

/* Ligne qui fait au moins 50px et au plus 200px */
grid-template-rows: minmax(50px, 200px);

/* Avec auto (taille naturelle) */
grid-template-columns: minmax(150px, auto) 1fr;

10.5. Propriétés des éléments Grid

Propriété Valeurs courantes Effet
grid-column 1 / 3, span 2 Position de l'élément : de la colonne 1 à la colonne 3
grid-row 1 / 3, span 2 Position de l'élément : de la ligne 1 à la ligne 3
grid-area header, 1 / 1 / 3 / 4 Raccourci pour grid-row-start / grid-column-start / grid-row-end / grid-column-end
justify-self start, end, center, stretch Override justify-items pour un élément
align-self start, end, center, stretch Override align-items pour un élément

10.6. Exemple complet : Galerie de photos avec Grid

<div class="galerie">
    <div class="item item1">📸 1</div>
    <div class="item item2">📸 2</div>
    <div class="item item3">📸 3</div>
    <div class="item item4">📸 4</div>
    <div class="item item5">📸 5</div>
    <div class="item item6">📸 6</div>
    <div class="item item7">📸 7</div>
    <div class="item item8">📸 8</div>
</div>
.galerie {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 180px;
    gap: 15px;
    padding: 20px;
    max-width: 1100px;
    margin: 0 auto;
}

.item {
    background: #4361ee;
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    font-size: 20px;
    font-weight: 600;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
    cursor: pointer;
}

.item:hover {
    transform: scale(1.03);
    box-shadow: 0 8px 25px rgba(67, 97, 238, 0.3);
}

/* Élément qui prend 2 colonnes et 2 lignes */
.item1 {
    grid-column: 1 / 3;
    grid-row: 1 / 3;
    background: #e74c3c;
}

/* Élément qui prend 2 colonnes en largeur */
.item4 {
    grid-column: 2 / 4;
    background: #f39c12;
}

/* Élément qui prend 2 lignes en hauteur */
.item6 {
    grid-row: span 2;
    background: #2ecc71;
}

/* Élément qui prend 3 colonnes */
.item8 {
    grid-column: span 3;
    background: #9b59b6;
}
📸 1
📸 2
📸 3
📸 4
📸 5
📸 6
📸 7
📸 8

10.7. Flexbox vs Grid — Guide de choix

Cas d'usage Flexbox (1D) CSS Grid (2D)
Navigation ✅ Idéal (alignement horizontal) ❌ Trop puissant
Centrage d'un élément ✅ Parfait (justify-content: center; align-items: center;) ✅ Aussi possible
Galerie de photos ⚠️ Possible avec flex-wrap ✅ Idéal (grille régulière)
Mise en page complexe (header, sidebar, main, footer) ⚠️ Difficile (plusieurs conteneurs) ✅ Parfait (grid-template-areas)
Alignement vertical ✅ Simple ✅ Simple aussi
Distribution d'espace space-between, space-around ⚠️ Moins intuitif
Ordre des éléments order ⚠️ Plus complexe
💡 Règle d'or : Utilisez Flexbox pour les composants (menus, barres d'outils, cartes) et Grid pour la structure globale de la page. Ils se complètent parfaitement.

11. Styliser les liens, les listes et les formulaires

11.1. Styliser les liens (<a>)

Les liens ont 4 états en CSS, correspondant à des pseudo-classes. L'ordre est important : :link:visited:hover:active (mémoire : LOVE HATE).

/* État normal (non visité) */
a:link {
    color: #4361ee;
    text-decoration: none;
}

/* État visité */
a:visited {
    color: #7b1fa2;
}

/* Au survol (souris) */
a:hover {
    color: #e74c3c;
    text-decoration: underline;
}

/* Au moment du clic */
a:active {
    color: #1a1a2e;
}

/* Style alternatif pour les liens dans une navigation */
.menu a {
    color: white;
    text-decoration: none;
    padding: 8px 16px;
    border-radius: 6px;
    transition: background 0.3s;
}

.menu a:hover {
    background: rgba(255,255,255,0.15);
}

.menu a:active {
    background: rgba(255,255,255,0.25);
}
📝 Règle mnémonique : Link → Visited → Hover → Active
"Love Hate" est un moyen facile de s'en souvenir !

11.2. Styliser les listes

/* Enlever les puces et les marges */
ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

/* Listes à puces personnalisées */
ul.custom {
    list-style-type: square;
    padding-left: 25px;
}

ul.custom li {
    margin-bottom: 8px;
    padding-left: 8px;
}

/* Liste horizontale (menus) */
ul.horizontal {
    display: flex;
    gap: 20px;
    flex-wrap: wrap;
}

ul.horizontal li {
    background: #eef2ff;
    padding: 8px 18px;
    border-radius: 50px;
    font-weight: 500;
}

/* Puce personnalisée avec ::before */
ul.emoji-puces {
    list-style: none;
    padding: 0;
}

ul.emoji-puces li::before {
    content: "✨ ";
    color: #4361ee;
    font-weight: bold;
}

/* Puce en forme de nombre pour les listes ordonnées */
ol.roman {
    list-style-type: upper-roman;
    padding-left: 30px;
}

11.3. Styliser les formulaires — bonnes pratiques

Les formulaires sont souvent sous-estimés dans leur stylisation. Voici les bonnes pratiques pour des formulaires modernes et accessibles.

✅ Accessibilité des formulaires :
  • Utilisez toujours <label> avec for correspondant à l'id du champ.
  • Placez les messages d'erreur à proximité du champ concerné.
  • Utilisez autocomplete pour faciliter le remplissage.
  • Indiquez les champs obligatoires avec required ou un astérisque visible.
  • Utilisez aria-describedby pour lier les messages d'aide.
<form class="formulaire-moderne">
    <h2>Contactez-nous</h2>

    <div class="champ">
        <label for="nom">Nom complet</label>
        <input type="text" id="nom" placeholder="Jean Dupont" required>
        <span class="aide">Votre nom et prénom</span>
    </div>

    <div class="champ">
        <label for="email">Email</label>
        <input type="email" id="email" placeholder="jean@exemple.com" required>
    </div>

    <div class="champ">
        <label for="message">Message</label>
        <textarea id="message" rows="5" placeholder="Votre message..."></textarea>
    </div>

    <div class="champ checkbox">
        <input type="checkbox" id="rgpd" required>
        <label for="rgpd">J'accepte la politique de confidentialité</label>
    </div>

    <button type="submit" class="btn-envoyer">
        <span>✉️</span> Envoyer le message
    </button>
</form>
.formulaire-moderne {
    max-width: 550px;
    margin: 0 auto;
    padding: 35px 40px;
    background: white;
    border-radius: 16px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.08);
}

.formulaire-moderne h2 {
    margin-top: 0;
    margin-bottom: 25px;
    color: #1a1a2e;
    font-size: 26px;
}

.champ {
    margin-bottom: 22px;
}

.champ label {
    display: block;
    font-weight: 600;
    margin-bottom: 6px;
    color: #2d3436;
    font-size: 14px;
}

.champ input,
.champ textarea,
.champ select {
    width: 100%;
    padding: 12px 16px;
    border: 2px solid #e0e0e0;
    border-radius: 8px;
    font-size: 16px;
    font-family: inherit;
    transition: border-color 0.3s, box-shadow 0.3s;
    background: #fafafa;
}

.champ input:focus,
.champ textarea:focus,
.champ select:focus {
    border-color: #4361ee;
    box-shadow: 0 0 0 4px rgba(67, 97, 238, 0.15);
    outline: none;
    background: white;
}

.champ textarea {
    resize: vertical;
    min-height: 100px;
}

.champ .aide {
    display: block;
    font-size: 13px;
    color: #6c757d;
    margin-top: 4px;
}

.champ.checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
}

.champ.checkbox input {
    width: auto;
    margin: 0;
    accent-color: #4361ee;
    width: 18px;
    height: 18px;
    cursor: pointer;
}

.champ.checkbox label {
    margin: 0;
    font-weight: 400;
    cursor: pointer;
}

.btn-envoyer {
    width: 100%;
    padding: 14px;
    background: #4361ee;
    color: white;
    border: none;
    border-radius: 8px;
    font-size: 18px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.3s, transform 0.2s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.btn-envoyer:hover {
    background: #3a0ca3;
    transform: translateY(-2px);
}

.btn-envoyer:active {
    transform: scale(0.97);
}

/* État de validation des champs */
.champ input:valid {
    border-color: #2ecc71;
}

.champ input:invalid:not(:placeholder-shown) {
    border-color: #e74c3c;
}

12. Comprendre le responsive design

12.1. Qu'est-ce que le responsive design ?

Le responsive design (ou design adaptatif) est une approche de conception web qui vise à créer des sites qui s'affichent correctement sur tous les types d'écrans : ordinateur, tablette, smartphone, télévision, etc.

Il a été popularisé par Ethan Marcotte en 2010 et repose sur trois piliers :

  • Les grilles fluides : utilisation de pourcentages plutôt que de pixels fixes.
  • Les images flexibles : images qui s'adaptent à la taille du conteneur.
  • Les media queries : points de rupture où le design change.

12.2. La balise viewport

Sans la balise viewport, les mobiles affichent les pages comme si elles étaient sur un écran d'ordinateur, ce qui oblige l'utilisateur à zoomer. La balise viewport résout ce problème.

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Explication des paramètres :

  • width=device-width : La largeur de la page est égale à la largeur de l'écran.
  • initial-scale=1.0 : Niveau de zoom initial de 100%.
  • maximum-scale=1.0 (optionnel) : Empêche le zoom (déconseillé pour l'accessibilité).
  • user-scalable=yes (optionnel) : Permet à l'utilisateur de zoomer (recommandé).

📐 Relation entre la taille de l'écran et la résolution :

densité _ pixels = nombre _ pixels _ réels × 160 dpi largeur _ écran _ en _ pouces

Exemple : un écran de 375px avec un facteur d'échelle de 2× équivaut à 750px physiques.

12.3. Les unités relatives

Unité Description Exemple Calcul
% Pourcentage du parent width: 80%; 80% de la largeur du parent
em Relatif à la taille de police du parent font-size: 2em; 2× la taille de police du parent
rem Relatif à la taille de police racine (<html>) font-size: 1.5rem; 1.5× la taille de police racine
vw 1% de la largeur de la fenêtre width: 50vw; 50% de la largeur du viewport
vh 1% de la hauteur de la fenêtre height: 100vh; 100% de la hauteur du viewport
vmin 1% de la plus petite dimension font-size: 2vmin; 2% de la plus petite dimension
vmax 1% de la plus grande dimension font-size: 2vmax; 2% de la plus grande dimension
💡 Bonne pratique : Utilisez rem pour les tailles de police et les espacements. Cela permet à l'utilisateur de modifier la taille de la police via les paramètres de son navigateur. La taille racine par défaut est généralement 16px.

12.4. Les media queries

Les media queries permettent d'appliquer des styles CSS spécifiques selon les caractéristiques de l'appareil (largeur, hauteur, orientation, etc.).

/* ============================================= */
/* APPROCHE MOBILE-FIRST (recommandée)           */
/* ============================================= */

/* Styles pour TOUS les écrans (base mobile) */
body {
    font-size: 16px;
    padding: 10px;
}

h1 {
    font-size: 24px;
}

.grille {
    grid-template-columns: 1fr;
    gap: 15px;
}

/* ============================================= */
/* Tablettes (≥ 768px)                          */
/* ============================================= */
@media (min-width: 768px) {
    body {
        font-size: 18px;
        padding: 20px;
    }

    h1 {
        font-size: 32px;
    }

    .grille {
        grid-template-columns: repeat(2, 1fr);
        gap: 20px;
    }
}

/* ============================================= */
/* Ordinateurs (≥ 1024px)                      */
/* ============================================= */
@media (min-width: 1024px) {
    body {
        font-size: 20px;
        padding: 30px;
    }

    h1 {
        font-size: 42px;
    }

    .grille {
        grid-template-columns: repeat(4, 1fr);
        gap: 25px;
    }
}

/* ============================================= */
/* Grands écrans (≥ 1440px)                    */
/* ============================================= */
@media (min-width: 1440px) {
    body {
        max-width: 1400px;
        margin: 0 auto;
    }
}

/* ============================================= */
/* Impression                                   */
/* ============================================= */
@media print {
    nav, .publicite {
        display: none;
    }
    body {
        font-size: 12pt;
        color: black;
        background: white;
    }
}
✅ Approche "Mobile-First" :
  • On commence par écrire le CSS pour les mobiles (taille d'écran la plus petite).
  • On utilise des min-width pour ajouter des styles pour les écrans plus grands.
  • Avantages : performance (moins de CSS à charger sur mobile), meilleure accessibilité.
  • Cette approche est aujourd'hui la référence en matière de responsive design.

12.5. Exemple : Menu responsive avec burger

<!-- HTML -->
<nav class="nav-responsive">
    <div class="logo">🚀 MonSite</div>

    <input type="checkbox" id="burger" class="burger-input">
    <label for="burger" class="burger-label">
        <span></span>
        <span></span>
        <span></span>
    </label>

    <ul class="nav-links">
        <li><a href="#">Accueil</a></li>
        <li><a href="#">Services</a></li>
        <li><a href="#">À propos</a></li>
        <li><a href="#">Contact</a></li>
    </ul>
</nav>
/* CSS */
.nav-responsive {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px 20px;
    background: #1a1a2e;
    color: white;
    position: relative;
}

.logo {
    font-size: 22px;
    font-weight: 700;
}

.nav-links {
    display: flex;
    list-style: none;
    gap: 25px;
}

.nav-links a {
    color: rgba(255,255,255,0.8);
    text-decoration: none;
    padding: 6px 12px;
    border-radius: 6px;
    transition: background 0.3s;
}

.nav-links a:hover {
    background: rgba(255,255,255,0.12);
    color: white;
}

/* Cacher le burger sur desktop */
.burger-input,
.burger-label {
    display: none;
}

/* ============================================= */
/* VERSION MOBILE                               */
/* ============================================= */
@media (max-width: 768px) {
    .burger-label {
        display: flex;
        flex-direction: column;
        gap: 5px;
        cursor: pointer;
        padding: 5px;
        z-index: 10;
    }

    .burger-label span {
        display: block;
        width: 28px;
        height: 3px;
        background: white;
        border-radius: 2px;
        transition: 0.3s ease;
    }

    /* Animation du burger en croix */
    .burger-input:checked + .burger-label span:nth-child(1) {
        transform: rotate(45deg) translate(5px, 6px);
    }

    .burger-input:checked + .burger-label span:nth-child(2) {
        opacity: 0;
    }

    .burger-input:checked + .burger-label span:nth-child(3) {
        transform: rotate(-45deg) translate(5px, -6px);
    }

    /* Menu caché par défaut */
    .nav-links {
        display: none;
        flex-direction: column;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        background: #1a1a2e;
        padding: 20px;
        gap: 5px;
        border-top: 1px solid rgba(255,255,255,0.1);
        box-shadow: 0 10px 30px rgba(0,0,0,0.3);
    }

    .nav-links li {
        width: 100%;
    }

    .nav-links a {
        display: block;
        padding: 12px 16px;
        width: 100%;
        border-radius: 8px;
        font-size: 18px;
    }

    .nav-links a:hover {
        background: rgba(67, 97, 238, 0.2);
    }

    /* Afficher le menu quand la checkbox est cochée */
    .burger-input:checked ~ .nav-links {
        display: flex;
    }
}

13. Ajouter des animations et transitions

13.1. Les transitions

Les transitions permettent de passer en douceur d'une valeur CSS à une autre lors d'un changement d'état (survol, focus, etc.).

Syntaxe :

transition: propriété durée fonction délai;
Paramètre Valeurs Explication
Propriété all, color, transform, opacity La propriété CSS à animer
Durée 0.3s, 300ms, 2s Durée de la transition
Fonction ease, linear, ease-in, ease-out, ease-in-out, cubic-bezier() Courbe d'accélération
Délai 0s, 0.5s, 1s Temps d'attente avant le début
/* Transition sur plusieurs propriétés */
.bouton {
    background: #4361ee;
    color: white;
    padding: 12px 30px;
    border: none;
    border-radius: 8px;
    font-size: 16px;
    cursor: pointer;

    /* Transition sur background et transform */
    transition: background 0.3s ease, transform 0.2s ease-out;
}

.bouton:hover {
    background: #3a0ca3;
    transform: scale(1.05);
}

.bouton:active {
    transform: scale(0.95);
}

📐 Fonctions de transition (courbes de Bézier) :

B ( t ) = ( 1 - t ) 3 P 0 + 3 ( 1 - t ) 2 t P 1 + 3 ( 1 - t ) t 2 P 2 + t 3 P 3 ,   t ∈ [ 0 , 1 ]

Les points de contrôle définissent l'accélération de la transition.

13.2. Les animations keyframes

Les animations permettent de créer des séquences d'étapes (keyframes) pour des mouvements plus complexes et répétitifs.

Syntaxe :

@keyframes nom-de-lanimation {
    0%   { /* styles au début */ }
    50%  { /* styles à mi-parcours */ }
    100% { /* styles à la fin */ }
}

.element {
    animation: nom-de-lanimation 2s ease-in-out infinite;
}
/* Animation de pulsation */
@keyframes pulse {
    0% {
        transform: scale(1);
        opacity: 1;
    }
    50% {
        transform: scale(1.08);
        opacity: 0.8;
    }
    100% {
        transform: scale(1);
        opacity: 1;
    }
}

.pulse {
    animation: pulse 1.5s ease-in-out infinite;
}

/* Animation de chargement (spinner) */
@keyframes spin {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}

.spinner {
    animation: spin 1s linear infinite;
}

/* Animation d'apparition en fondu */
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.fade-in {
    animation: fadeInUp 0.6s ease-out forwards;
}

/* Animation de rebond */
@keyframes bounce {
    0%, 100% {
        transform: translateY(0);
    }
    30% {
        transform: translateY(-40px);
    }
    50% {
        transform: translateY(0);
    }
    70% {
        transform: translateY(-20px);
    }
    85% {
        transform: translateY(0);
    }
    95% {
        transform: translateY(-8px);
    }
}

.bounce {
    animation: bounce 1.2s ease infinite;
}

13.3. Exemple de carte animée

<div class="carte-interactive">
    <img src="image.jpg" alt="Image de la carte">
    <div class="contenu-carte">
        <h3>Titre de la carte</h3>
        <p>Description de la carte avec des détails intéressants.</p>
        <a href="#" class="btn-carte">En savoir plus →</a>
    </div>
</div>
.carte-interactive {
    background: white;
    border-radius: 16px;
    overflow: hidden;
    max-width: 340px;
    box-shadow: 0 4px 15px rgba(0,0,0,0.08);
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.4s ease;
}

.carte-interactive:hover {
    transform: translateY(-12px) scale(1.01);
    box-shadow: 0 20px 50px rgba(0,0,0,0.15);
}

.carte-interactive img {
    width: 100%;
    height: 200px;
    object-fit: cover;
    transition: transform 0.6s ease;
}

.carte-interactive:hover img {
    transform: scale(1.06);
}

.contenu-carte {
    padding: 20px 24px 24px;
}

.contenu-carte h3 {
    margin: 0 0 8px 0;
    font-size: 20px;
    color: #1a1a2e;
}

.contenu-carte p {
    color: #4a4e69;
    font-size: 14px;
    line-height: 1.6;
    margin-bottom: 16px;
}

.btn-carte {
    display: inline-block;
    padding: 10px 24px;
    background: #4361ee;
    color: white;
    text-decoration: none;
    border-radius: 50px;
    font-weight: 600;
    transition: background 0.3s, transform 0.2s;
}

.btn-carte:hover {
    background: #3a0ca3;
    transform: translateX(4px);
}

📝 Exercices pratiques

Exercice 1 — Box Model

Créez un élément div avec les caractéristiques suivantes :

  • Largeur : 300px
  • Padding : 20px
  • Bordure : 3px solide noire
  • Marge : 15px
  • Couleur de fond : #eef2ff

Question : Quelle est la largeur totale de l'élément avec box-sizing: content-box ? Et avec box-sizing: border-box ?

✅ Correction

Avec content-box :

Largeur _ totale = 300 + 20 + 20 + 3 + 3 = 346 px

Avec border-box :

Largeur _ totale = 300 px  (le padding et la bordure sont inclus)
/* Solution CSS */
.boite {
    width: 300px;
    padding: 20px;
    border: 3px solid #000;
    margin: 15px;
    background: #eef2ff;
    box-sizing: border-box; /* ou content-box pour tester */
}

Exercice 2 — Flexbox

Créez une barre de navigation avec Flexbox qui contient :

  • Un logo à gauche
  • 4 liens de navigation centrés
  • Un bouton "Connexion" à droite

La barre doit avoir un fond sombre (#1a1a2e) et les liens doivent être blancs.

✅ Correction
<nav class="navbar-exo">
    <div class="logo">MonLogo</div>
    <ul class="menu-exo">
        <li><a href="#">Accueil</a></li>
        <li><a href="#">Services</a></li>
        <li><a href="#">À propos</a></li>
        <li><a href="#">Contact</a></li>
    </ul>
    <a href="#" class="btn-connexion-exo">Connexion</a>
</nav>
.navbar-exo {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: #1a1a2e;
    padding: 16px 30px;
    color: white;
}

.logo {
    font-size: 22px;
    font-weight: 700;
}

.menu-exo {
    display: flex;
    list-style: none;
    gap: 30px;
}

.menu-exo a {
    color: white;
    text-decoration: none;
}

.btn-connexion-exo {
    color: white;
    text-decoration: none;
    padding: 8px 20px;
    border: 1px solid rgba(255,255,255,0.3);
    border-radius: 50px;
}

Exercice 3 — CSS Grid

Créez une grille de 6 éléments avec les spécifications suivantes :

  • 3 colonnes de largeur égale
  • Un espace de 15px entre les éléments
  • L'élément 1 occupe 2 colonnes
  • L'élément 4 occupe 2 lignes
✅ Correction
.grille-exo {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 15px;
}

.item-1 {
    grid-column: span 2;
    background: #e74c3c;
}

.item-4 {
    grid-row: span 2;
    background: #2ecc71;
}

/* Les autres éléments ont une couleur par défaut */
.item {
    background: #4361ee;
    color: white;
    padding: 40px 20px;
    text-align: center;
    border-radius: 8px;
}

Exercice 4 — Responsive

À partir de l'exercice 3, rendez la grille responsive :

  • Sur mobile (moins de 768px) : 1 colonne
  • Sur tablette (768px - 1024px) : 2 colonnes
  • Sur desktop (plus de 1024px) : 3 colonnes
✅ Correction
/* Version mobile (par défaut) */
.grille-exo {
    display: grid;
    grid-template-columns: 1fr;
    gap: 15px;
}

/* Tablette */
@media (min-width: 768px) {
    .grille-exo {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Desktop */
@media (min-width: 1024px) {
    .grille-exo {
        grid-template-columns: repeat(3, 1fr);
    }
}

Exercice 5 — Animation

Créez une animation qui fait pivoter un élément de 360° et qui change de couleur du bleu au rouge en 2 secondes, en boucle infinie.

✅ Correction
@keyframes spinColor {
    0% {
        transform: rotate(0deg);
        background: #4361ee;
    }
    100% {
        transform: rotate(360deg);
        background: #e74c3c;
    }
}

.element-anime {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    animation: spinColor 2s linear infinite;
}

 Prochaine étape :
  •  JavaScript
  •  SASS/LESS
  •  Tailwind CSS
  •  React / Vue

— Cours HTML & CSS

Last modified: Saturday, 8 August 2026, 3:56 PM