HTML & CSS — Cours Complet Version ultra-détaillée avec schémas, MathML et exercices corrigés
Par OpenClassrooms — Formation approfondie au développement web
Partie 1 — Fondamentaux
Partie 2 — Mise en page
Partie 3 — Exercice pratique complet
Partie 1 : Les fondamentaux du HTML et CSS
1. Distinguer HTML et CSS — Explications approfondies
1.1. Qu'est-ce que le HTML ?
Le HTML (HyperText Markup Language) est le langage de structure d'une page web. Il a été créé par Tim Berners-Lee en 1991. Sa première version officielle (HTML 2.0) date de 1995. Aujourd'hui, nous utilisons HTML5, la dernière version majeure, qui a introduit les balises sémantiques, le support de la vidéo et de l'audio natifs, et bien d'autres fonctionnalités.
- Architecture : HTML = les fondations, les murs porteurs, l'ossature d'une maison. Sans HTML, le contenu n'existe pas.
- Biologie : HTML = le squelette d'un corps humain. Il donne la structure et maintient tout en place.
- Théâtre : HTML = le texte du scénario. Il dit "ceci est un dialogue", "ceci est une didascalie".
Ce que le HTML fait concrètement :
- Il définit les titres (
<h1>à<h6>) pour structurer la hiérarchie du contenu. - Il crée des paragraphes (
<p>) pour organiser le texte. - Il insère des images (
<img>), des vidéos (<video>) et des audios (<audio>). - Il crée des liens hypertextes (
<a>) pour naviguer entre les pages. - Il structure le contenu en listes (
<ul>,<ol>), tableaux (<table>) et formulaires (<form>).
1.2. Qu'est-ce que le CSS ?
Le CSS (Cascading Style Sheets) est le langage de présentation d'une page web. Il a été créé en 1996 par Håkon Wium Lie et Bert Bos. Le terme "cascading" (en cascade) fait référence à la manière dont les styles se superposent et se transmettent d'un parent à ses enfants dans l'arbre DOM.
- Architecture : CSS = la peinture, la décoration intérieure, l'aménagement de la maison.
- Biologie : CSS = la peau, les vêtements, la coiffure qui donnent l'apparence extérieure.
- Théâtre : CSS = la mise en scène, les costumes, les lumières qui créent l'ambiance.
Ce que le CSS fait concrètement :
- Il définit les couleurs de fond, de texte et de bordures.
- Il contrôle la typographie : polices, tailles, graisses, espacements.
- Il gère la mise en page : marges, paddings, positions, alignements.
- Il crée des effets visuels : ombres, dégradés, animations, transitions.
- Il assure l'adaptabilité (responsive design) : la page s'affiche correctement sur tous les écrans.
1.3. Résumé comparatif
| Critère | HTML | CSS |
|---|---|---|
| Rôle | Structure, contenu, sémantique | Style, présentation, mise en page |
| Question | "Qu'est-ce que c'est ?" (nature du contenu) | "À quoi ça ressemble ?" (apparence du contenu) |
| Extension de fichier | .html ou .htm |
.css |
| Syntaxe | Balises <nom> avec attributs |
Règles sélecteur { propriété: valeur; } |
| Historique | Tim Berners-Lee (1991) | Håkon Wium Lie (1996) |
| Dernière version | HTML5 (2014) | CSS3 (modules depuis 1999) |
style qui est une exception à éviter). Le HTML est pour la structure, le CSS pour le style. Gardez-les toujours séparés pour un code propre et maintenable.2. Reconnaître les éléments HTML courants et leurs attributs
2.1. La structure minimale d'une page HTML
Toute page HTML valide doit commencer par une déclaration de type de document (!DOCTYPE) qui indique au navigateur qu'il s'agit de HTML5. Ensuite, la balise racine <html> contient deux sections principales :
- <head> : Les métadonnées (non visibles) — titre, encodage, liens vers CSS, etc.
- <body> : Le contenu visible par l'utilisateur.
<!DOCTYPE html>
<html lang="fr">
<head>
<!-- Encodage des caractères (UTF-8 recommandé) -->
<meta charset="UTF-8">
<!-- Rendu responsive sur mobiles -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Titre affiché dans l'onglet du navigateur -->
<title>Ma première page</title>
<!-- Lien vers la feuille de style CSS externe -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Tout le contenu visible va ici -->
<h1>Bienvenue sur mon site</h1>
<p>Ceci est mon premier paragraphe.</p>
</body>
</html>
2.2. Les éléments HTML les plus utilisés
| Balise | Utilité | Exemple | Attributs courants |
|---|---|---|---|
<h1> à <h6> |
Titres hiérarchiques (h1 = plus important) | <h1>Titre principal</h1> |
class, id, style |
<p> |
Paragraphe de texte | <p>Ceci est un paragraphe.</p> |
class, id |
<a> |
Lien hypertexte (ancre) | <a href="https://exemple.com">Cliquez</a> |
href, target, rel |
<img> |
Image (auto-fermante) | <img src="photo.jpg" alt="Description"> |
src, alt, width, height |
<ul> / <ol> |
Liste non-ordonnée / ordonnée | <ul><li>Item</li></ul> |
class, id |
<div> |
Conteneur générique (bloc) | <div class="conteneur">...</div> |
class, id |
<span> |
Conteneur générique (en ligne) | <span class="surligne">texte</span> |
class, id |
<br> |
Saut de ligne (auto-fermant) | Ligne 1<br>Ligne 2 |
Aucun |
<hr> |
Ligne de séparation horizontale | <hr> |
Aucun |
<strong> |
Texte fortement important (gras) | <strong>Important</strong> |
class |
<em> |
Texte mis en emphase (italique) | <em>Emphase</em> |
class |
2.3. Les attributs HTML en détail
Les attributs sont des informations supplémentaires que l'on ajoute aux balises pour modifier leur comportement ou leur donner des métadonnées. Ils s'écrivent toujours sous la forme nom="valeur".
| Attribut | Utilisé sur | Utilité | Exemple |
|---|---|---|---|
href |
<a> |
Définit la destination du lien (URL) | <a href="https://google.com"> |
src |
<img>, <script>, <iframe> |
Définit la source (chemin) du fichier | <img src="images/logo.png"> |
alt |
<img> |
Texte alternatif (accessibilité, si l'image ne charge pas) | <img src="logo.png" alt="Logo de l'entreprise"> |
class |
Toutes les balises | Identifie un groupe d'éléments (pour CSS/JS) | <div class="carte article"> |
id |
Toutes les balises | Identifie un élément unique (DOIT être unique) | <h1 id="titre-principal"> |
target |
<a>, <form> |
Ouvrir le lien dans un nouvel onglet (_blank) |
<a href="#" target="_blank"> |
title |
Presque toutes | Texte informatif affiché au survol (tooltip) | <abbr title="HyperText Markup Language">HTML</abbr> |
style |
Presque toutes | CSS en ligne (à éviter, sauf exceptions) | <p style="color: red;">Texte rouge</p> |
data-* |
Presque toutes | Données personnalisées pour JavaScript | <div data-user-id="123"> |
role |
Presque toutes | Rôle ARIA pour l'accessibilité | <nav role="navigation"> |
alt sur les images. C'est obligatoire pour l'accessibilité (lecteurs d'écran pour malvoyants) et cela aide également le référencement (SEO). De plus, si l'image ne charge pas, le texte alternatif s'affiche à la place.3. Expliquer comment les balises sémantiques structurent une page web
3.1. Qu'est-ce que la sémantique en HTML ?
Avant HTML5, les développeurs utilisaient principalement des <div> avec des classes comme class="header", class="nav", etc. Cela fonctionnait, mais cela ne donnait aucune information sémantique au navigateur, aux moteurs de recherche ou aux lecteurs d'écran.
HTML5 a introduit des balises sémantiques qui décrivent ce qu'est le contenu, et non seulement comment il est affiché. C'est un changement fondamental qui améliore :
- L'accessibilité : Les lecteurs d'écran peuvent naviguer plus facilement.
- Le SEO : Google comprend mieux la structure de la page.
- La maintenabilité : Le code est plus lisible et compréhensible.
3.2. Les balises sémantiques HTML5
| Balise | Signification | Utilisation typique | Équivalent "div" avant HTML5 |
|---|---|---|---|
<header> |
En-tête | Logo, titre principal, navigation principale | <div class="header"> |
<nav> |
Navigation | Menu principal, liens de navigation | <div class="nav"> |
<main> |
Contenu principal | Contenu central unique de la page | <div class="main"> |
<section> |
Section thématique | Regroupe un thème cohérent (ex: "Nos produits") | <div class="section"> |
<article> |
Article | Contenu indépendant et réutilisable (blog, news) | <div class="article"> |
<aside> |
À côté / contenu secondaire | Barre latérale, publicités, informations complémentaires | <div class="sidebar"> |
<footer> |
Pied de page | Mentions légales, copyright, contact, liens utiles | <div class="footer"> |
<figure> |
Figure / illustration | Image avec légende (<figcaption>) |
<div class="figure"> |
<figcaption> |
Légende d'une figure | Texte descriptif d'une image ou d'un graphique | <p class="caption"> |
<mark> |
Texte surligné | Mettre en évidence une partie du texte | <span class="highlight"> |
<time> |
Date / Heure | Indiquer une date ou une heure (machine-readable) | <span class="date"> |
3.3. Structure d'une page sémantique complète
<body>
<header>
<h1>Mon Site Web</h1>
<nav>
<ul>
<li><a href="#">Accueil</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</header>
<main>
<section>
<h2>Nos derniers articles</h2>
<article>
<h3>Comment débuter en HTML</h3>
<time datetime="2026-08-08">8 août 2026</time>
<p>Le HTML est le langage de base du web...</p>
<a href="#">Lire la suite</a>
</article>
<article>
<h3>Les bases du CSS</h3>
<time datetime="2026-08-07">7 août 2026</time>
<p>Le CSS permet de styliser vos pages...</p>
<a href="#">Lire la suite</a>
</article>
</section>
<aside>
<h4>À propos</h4>
<p>Je suis un développeur web passionné.</p>
</aside>
</main>
<footer>
<p>© 2026 MonSite - Tous droits réservés.</p>
</footer>
</body>
- Accessibilité : Les lecteurs d'écran (comme NVDA ou VoiceOver) peuvent identifier les zones de la page et proposer une navigation par points de repère.
- SEO : Google et les autres moteurs de recherche accordent plus d'importance au contenu dans
<main>et<article>. - Maintenance : Un collègue (ou vous-même dans 6 mois) comprendra immédiatement la structure de la page.
- Validation : Le validateur W3C encourage l'utilisation de balises sémantiques.
4. Distinguer les éléments en bloc des éléments en ligne
4.1. Les éléments en bloc (block elements)
Les éléments de type bloc sont les "briques" structurelles d'une page. Ils créent des rectangles qui s'empilent verticalement.
Caractéristiques :
- Ils prennent toute la largeur disponible de leur conteneur parent.
- Ils provoquent un retour à la ligne (saut de ligne) avant et après eux.
- On peut leur donner une largeur (
width) et une hauteur (height). - Ils peuvent contenir d'autres blocs ou des éléments en ligne.
Exemples d'éléments en bloc :
<div> <p> <h1> à <h6> <ul> / <ol> <header> <section> <footer> <article> <nav> <aside> <main> <figure>4.2. Les éléments en ligne (inline elements)
Les éléments en ligne sont utilisés pour styliser ou marquer une partie du texte à l'intérieur d'un paragraphe ou d'un bloc. Ils ne créent pas de rupture dans le flux du texte.
Caractéristiques :
- Ils prennent uniquement la largeur de leur contenu (pas plus).
- Ils ne provoquent pas de retour à la ligne ; ils s'enchaînent sur la même ligne.
- On ne peut pas leur donner de
widthou deheight(ils s'adaptent au contenu). - On peut leur appliquer un
paddinget unmarginhorizontal, mais pas vertical (dans certaines conditions).
Exemples d'éléments en ligne :
<a> <span> <img> <strong> <em> <br> <time> <mark>4.3. Le cas particulier : display: inline-block
Le CSS offre une troisième option : display: inline-block. C'est un hybride qui combine les avantages des deux :
- L'élément s'affiche en ligne (pas de retour à la ligne).
- On peut lui donner width, height, padding et margin (comme un bloc).
.bouton {
display: inline-block;
width: 150px;
height: 50px;
padding: 10px;
text-align: center;
background: #4361ee;
color: white;
border-radius: 8px;
}
4.4. Résumé comparatif
| Propriété | Bloc (block) |
En ligne (inline) |
Bloc en ligne (inline-block) |
|---|---|---|---|
| Largeur | 100% du parent | Contenu uniquement | Contenu ou définie |
| Retour à la ligne | Oui (avant et après) | Non | Non |
Peut avoir width |
Oui | Non | Oui |
Peut avoir height |
Oui | Non | Oui |
| Peut contenir des blocs | Oui | Non | Non |
| Exemples typiques | div, p, h1, section |
span, a, img, strong |
Boutons, images avec texte |
width et height à un <span> ou à un <a> sans résultat. Pour qu'un élément en ligne accepte des dimensions, il faut le passer en display: inline-block ou display: block.5. Utiliser des balises et attributs pour identifier les informations clés
5.1. Les attributs universels class et id
Ces deux attributs sont essentiels pour lier le HTML au CSS et au JavaScript. Ils permettent de cibler des éléments spécifiques.
| Attribut | Objectif | Règles |
|---|---|---|
class |
Identifier un groupe d'éléments | - Peut être utilisé plusieurs fois - Un élément peut avoir plusieurs classes ( class="carte article important")- Les classes sont séparées par des espaces |
id |
Identifier un élément unique | - DOIT être unique dans la page - Un élément ne peut avoir qu'un seul ID - L'ID doit commencer par une lettre (pas de chiffre) |
<!-- ID unique -->
<h1 id="titre-principal">Accueil</h1>
<!-- Classe réutilisable -->
<p class="intro">Introduction 1</p>
<p class="intro">Introduction 2</p>
<!-- Plusieurs classes -->
<div class="carte produit populaire">
<h3>Produit A</h3>
</div>
<!-- Un élément avec un ID ET des classes -->
<div id="article-1" class="article premium">
<h2>Article 1</h2>
</div>
5.2. Les attributs ARIA pour l'accessibilité
ARIA (Accessible Rich Internet Applications) est un ensemble d'attributs qui améliorent l'accessibilité pour les personnes utilisant des technologies d'assistance.
| Attribut ARIA | Utilisation | Exemple |
|---|---|---|
role |
Définit le rôle d'un élément | <nav role="navigation"> |
aria-label |
Étiquette accessible (quand pas de texte visible) | <button aria-label="Fermer le menu">X</button> |
aria-describedby |
Référence un élément qui décrit le contenu | <input aria-describedby="email-help"> |
aria-hidden |
Cache un élément aux lecteurs d'écran | <div aria-hidden="true">Décoration</div> |
aria-expanded |
Indique si un élément est déplié/replié | <button aria-expanded="false">Menu</button> |
5.3. Les microdonnées Schema.org
Schema.org est un vocabulaire structuré (développé par Google, Microsoft, Yahoo et Yandex) qui permet d'enrichir le HTML pour que les moteurs de recherche comprennent mieux le contenu.
<!-- Exemple d'un produit avec Schema.org -->
<div itemscope itemtype="http://schema.org/Product">
<img itemprop="image" src="casque.jpg" alt="Casque audio">
<h2 itemprop="name">Casque sans fil Pro</h2>
<p itemprop="description">Casque audio haute fidélité avec réduction de bruit.</p>
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<span itemprop="price" content="99.99">99,99 €</span>
<span itemprop="availability" content="InStock">En stock</span>
</div>
<div itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
<span itemprop="ratingValue">4.5</span> / 5
<span itemprop="reviewCount">127</span> avis
</div>
</div>
6. Identifier et utiliser la syntaxe CSS correcte
6.1. La syntaxe de base
Une règle CSS est composée de trois parties :
- Sélecteur : Cible l'élément (ou les éléments) à styliser.
- Propriété : L'aspect visuel à modifier (
color,font-size, etc.). - Valeur : La valeur appliquée à la propriété.
- Déclaration : Une ligne
propriété: valeur; - Règle : L'ensemble
sélecteur { déclarations }
6.2. Les sélecteurs CSS
| Type | Syntaxe | Exemple | Cible |
|---|---|---|---|
| Élément | balise |
p { color: red; } |
Tous les <p> |
| Classe | .nom |
.intro { font-weight: bold; } |
Tous les éléments avec class="intro" |
| ID | #nom |
#titre { font-size: 40px; } |
L'élément avec id="titre" |
| Universel | * |
* { margin: 0; } |
Tous les éléments |
| Descendant | parent enfant |
article p { color: gray; } |
Les <p> dans un <article> |
| Enfant direct | parent > enfant |
ul > li { color: blue; } |
Les <li> enfants directs d'un <ul> |
| Adjacent | élément1 + élément2 |
h1 + p { margin-top: 0; } |
Le <p> juste après un <h1> |
| Pseudo-classe | :pseudo |
a:hover { color: red; } |
Lien au survol |
| Pseudo-élément | ::pseudo |
p::first-letter { font-size: 2em; } |
Première lettre d'un paragraphe |
| Attribut | [attr] |
input[type="text"] { border: 1px solid blue; } |
Champs de texte |
6.3. Où écrire le CSS ?
- Feuille de style externe (✅ RECOMMANDÉ)
Fichier séparé
.csslié via<link>dans le<head>.<link rel="stylesheet" href="styles/main.css">✅ Avantages : Réutilisable, cache navigateur, séparation claire HTML/CSS, maintenance facilitée. - Style interne (⚠️ À utiliser avec modération)
Balise
<style>dans le<head>.<style> p { color: blue; } </style>⚠️ Inconvénients : Non réutilisable, alourdit le HTML, pas de cache. - Style en ligne (❌ À ÉVITER sauf exceptions)
Attribut
stylesur une balise.<p style="color: blue; font-size: 20px;">Texte</p>❌ Inconvénients : Priorité maximale (difficile à surcharger), mélange HTML/CSS, non maintenable, répétitif.
7. Appliquer le CSS aux éléments HTML
7.1. Exemple complet : Carte de visite avec styles
Voici un exemple complet qui met en œuvre toutes les notions vues précédemment : structure HTML sémantique, classes, ID, et styles CSS externes.
<!-- HTML -->
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ma carte de visite</title>
<link rel="stylesheet" href="carte.css">
</head>
<body>
<div class="carte">
<img src="avatar.jpg" alt="Photo de Jean Dupont" class="avatar">
<h1 id="nom">Jean Dupont</h1>
<p class="titre">Développeur Web Full-Stack</p>
<p class="description">
Passionné par les technologies web, je crée des sites modernes,
accessibles et performants.
</p>
<ul class="competences">
<li>HTML5 & CSS3</li>
<li>JavaScript / React</li>
<li>Node.js / Express</li>
</ul>
<a href="mailto:jean@exemple.com" class="bouton">Me contacter</a>
</div>
</body>
</html>
/* CSS — carte.css */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.carte {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0,0,0,0.15);
padding: 40px 35px 35px;
text-align: center;
max-width: 380px;
width: 100%;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.carte:hover {
transform: translateY(-6px);
box-shadow: 0 30px 80px rgba(0,0,0,0.2);
}
.avatar {
width: 120px;
height: 120px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #4361ee;
margin-bottom: 18px;
}
#nom {
font-size: 26px;
color: #1a1a2e;
margin-bottom: 4px;
}
.titre {
color: #4361ee;
font-size: 16px;
font-weight: 600;
margin-bottom: 12px;
letter-spacing: 0.5px;
}
.description {
color: #4a4e69;
font-size: 14px;
line-height: 1.6;
margin-bottom: 18px;
}
.competences {
list-style: none;
padding: 0;
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 22px;
}
.competences li {
background: #eef2ff;
color: #2d2b4e;
padding: 6px 16px;
border-radius: 50px;
font-size: 13px;
font-weight: 500;
}
.bouton {
display: inline-block;
padding: 12px 35px;
background: #4361ee;
color: white;
text-decoration: none;
border-radius: 50px;
font-weight: 600;
transition: background 0.3s ease, transform 0.2s ease;
}
.bouton:hover {
background: #3a0ca3;
transform: scale(1.04);
}
.bouton:active {
transform: scale(0.96);
}
📐 Calcul de l'ombre de la carte (box-shadow) :
ombre = ( dx , dy , r , ( r g b a ) )où dx = décalage horizontal, dy = décalage vertical, r = rayon de flou, (rgba) = couleur avec transparence.
Partie 2 : Maîtrise de la mise en page
8. Comprendre 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 qui définit comment ces boîtes sont dimensionnées et comment l'espace est calculé autour d'elles.
8.2. Les propriétés du Box Model
| Propriété | Description | Exemple | Valeurs typiques |
|---|---|---|---|
content |
Le contenu interne (texte, image, etc.) | width: 200px; |
px, %, em, rem, auto |
padding |
Espace intérieur entre le contenu et la bordure | padding: 20px; |
padding: 10px 20px; (haut/bas, gauche/droite) |
border |
La bordure qui entoure le 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.3. Les raccourcis (shorthands)
Pour padding et margin, il existe des syntaxes raccourcies :
/* 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.4. La propriété box-sizing — un concept fondamental
Par défaut (box-sizing: content-box), la largeur totale d'une boîte est :
Cela signifie qu'une boîte de width: 200px avec padding: 20px et border: 2px aura une largeur réelle de 244px ! C'est souvent source d'erreurs.
La solution : utiliser box-sizing: border-box, qui inclut le padding et la bordure dans la largeur définie.
/* Règle universelle — À mettre en premier dans votre CSS */
* {
box-sizing: border-box;
}
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, etc.).
9. Utiliser Flexbox pour des mises en page flexibles
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 tout cela.
Il permet de répartir l'espace et d'aligner les éléments dans un conteneur sur un seul axe (horizontal ou vertical).
Deux axes en Flexbox :
9.2. Activation de Flexbox
.conteneur-flex {
display: flex; /* Active le mode Flexbox */
}
9.3. 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 |
Aligne les lignes sur l'axe secondaire (quand flex-wrap: wrap) |
🎯 Visualisation des différentes valeurs de justify-content :
flex-start → éléments à gauchecenter → éléments au centreflex-end → éléments à droitespace-between → espace égal entre les élémentsspace-around → espace égal autour des élémentsspace-evenly → espace parfaitement égal9.4. 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.5. Exemple complet : Menu de navigation avancé 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;
letter-spacing: -0.5px;
}
.menu {
display: flex;
list-style: none;
gap: 30px;
}
.menu a {
color: rgba(255,255,255,0.8);
text-decoration: none;
font-weight: 500;
padding: 6px 0;
border-bottom: 2px solid transparent;
transition: color 0.3s, border-color 0.3s;
}
.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);
}
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.10. Utiliser CSS Grid pour des mises en page en 2 dimensions
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.
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" |
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. 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.5. Les unités fr, repeat() et minmax()
fr: Fraction de l'espace disponible.1 f r + 2 f r + 1 f r = 4 f r , 1 f r = 1 4 × espace _ totalrepeat(): Répète un motif.grid-template-columns: repeat(4, 1fr); /* 4 colonnes égales */ grid-template-columns: repeat(3, 200px); /* 3 colonnes de 200px */minmax(): Définit une taille minimale et maximale.grid-template-columns: minmax(100px, 1fr); /* Colonne entre 100px et 1fr */
10.6. Exemple complet : Galerie de photos avec Grid
<div class="galerie">
<div class="item item1">📸 Photo 1</div>
<div class="item item2">📸 Photo 2</div>
<div class="item item3">📸 Photo 3</div>
<div class="item item4">📸 Photo 4</div>
<div class="item item5">📸 Photo 5</div>
<div class="item item6">📸 Photo 6</div>
<div class="item item7">📸 Photo 7</div>
<div class="item item8">📸 Photo 8</div>
</div>
.galerie {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 200px;
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: 18px;
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;
}
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);
}
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
Les formulaires sont souvent sous-estimés dans leur stylisation. Voici les bonnes pratiques pour des formulaires modernes et accessibles.
<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">
<label>Service concerné :</label>
<select>
<option value="support">Support technique</option>
<option value="commercial">Commercial</option>
<option value="autre">Autre</option>
</select>
</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;
}
- Utilisez toujours
<label>avecforcorrespondant à l'iddu champ. - Placez les messages d'erreur à proximité du champ concerné.
- Utilisez
autocompletepour faciliter le remplissage. - Indiquez les champs obligatoires avec
requiredou un astérisque visible.
12. Comprendre les bases du 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 _ poucesExemple : 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 |
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;
}
}
/* ============================================= */
/* Orientation paysage sur mobile */
/* ============================================= */
@media (max-width: 768px) and (orientation: landscape) {
.banniere {
height: 60vh;
}
}
/* ============================================= */
/* Impression */
/* ============================================= */
@media print {
nav, .publicite {
display: none;
}
body {
font-size: 12pt;
color: black;
background: white;
}
}
- On commence par écrire le CSS pour les mobiles (taille d'écran la plus petite).
- On utilise des
min-widthpour 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 pratique : 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);
}
Partie 3 : Exercice pratique complet
14. Page de présentation de services — Projet complet
14.1. Objectif du projet
Vous allez créer une page de présentation de services pour une agence web. Ce projet intègre toutes les notions vues dans ce cours :
- Structure HTML sémantique
- Navigation avec Flexbox
- Grille de services avec CSS Grid
- Cartes animées
- Formulaire de contact stylisé
- Responsive design (mobile-first)
- Transitions et animations
14.2. Structure de la page
14.3. Code complet — HTML
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MonAgence — Services numériques</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- ============================================= -->
<!-- NAVBAR -->
<!-- ============================================= -->
<nav class="navbar">
<div class="logo">🚀 MonAgence</div>
<input type="checkbox" id="menu-toggle" class="menu-toggle">
<label for="menu-toggle" class="menu-hamburger">
<span></span>
<span></span>
<span></span>
</label>
<ul class="nav-links">
<li><a href="#" class="active">Accueil</a></li>
<li><a href="#services">Services</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
<!-- ============================================= -->
<!-- HERO SECTION -->
<!-- ============================================= -->
<header class="hero" id="accueil">
<div class="hero-contenu">
<h1>Des solutions numériques <span>sur mesure</span></h1>
<p>Nous créons des expériences web uniques qui transforment vos idées en réalité.</p>
<a href="#contact" class="btn-cta">
🚀 Commencer un projet
</a>
</div>
<div class="hero-statistiques">
<div class="stat">
<span class="stat-nombre">150+</span>
<span class="stat-label">Projets réalisés</span>
</div>
<div class="stat">
<span class="stat-nombre">98%</span>
<span class="stat-label">Clients satisfaits</span>
</div>
<div class="stat">
<span class="stat-nombre">4.9★</span>
<span class="stat-label">Avis clients</span>
</div>
</div>
</header>
<!-- ============================================= -->
<!-- SERVICES SECTION -->
<!-- ============================================= -->
<section class="services" id="services">
<div class="services-header">
<span class="services-badge">Nos compétences</span>
<h2>Ce que nous faisons de mieux</h2>
<p>Des services digitaux conçus pour répondre à vos besoins spécifiques.</p>
</div>
<div class="grille-services">
<div class="service-card">
<div class="service-icone">💻</div>
<h3>Développement web</h3>
<p>Création de sites vitrines, e-commerces et applications web sur mesure.</p>
<a href="#" class="service-lien">En savoir plus →</a>
</div>
<div class="service-card">
<div class="service-icone">📱</div>
<h3>Applications mobiles</h3>
<p>Développement d'applications natives et hybrides pour iOS et Android.</p>
<a href="#" class="service-lien">En savoir plus →</a>
</div>
<div class="service-card">
<div class="service-icone">🎨</div>
<h3>Design UX/UI</h3>
<p>Conception d'interfaces modernes, intuitives et centrées sur l'utilisateur.</p>
<a href="#" class="service-lien">En savoir plus →</a>
</div>
<div class="service-card">
<div class="service-icone">🔍</div>
<h3>Référencement SEO</h3>
<p>Optimisation de votre visibilité sur les moteurs de recherche.</p>
<a href="#" class="service-lien">En savoir plus →</a>
</div>
<div class="service-card">
<div class="service-icone">📊</div>
<h3>Analyse de données</h3>
<p>Tableaux de bord et analyses pour piloter votre stratégie digitale.</p>
<a href="#" class="service-lien">En savoir plus →</a>
</div>
<div class="service-card">
<div class="service-icone">⚡</div>
<h3>Maintenance & support</h3>
<p>Accompagnement continu et maintenance technique de vos projets.</p>
<a href="#" class="service-lien">En savoir plus →</a>
</div>
</div>
</section>
<!-- ============================================= -->
<!-- CONTACT SECTION -->
<!-- ============================================= -->
<section class="contact" id="contact">
<div class="contact-conteneur">
<div class="contact-info">
<span class="contact-badge">Contact</span>
<h2>Parlons de votre projet</h2>
<p>Une question ? Un projet en tête ? N'hésitez pas à nous contacter.</p>
<ul class="contact-details">
<li>📧 <a href="mailto:contact@monagence.com">contact@monagence.com</a></li>
<li>📞 <a href="tel:+33123456789">01 23 45 67 89</a></li>
<li>📍 123 rue du Web, 75000 Paris</li>
</ul>
</div>
<form class="contact-form">
<div class="form-row">
<div class="form-group">
<label for="nom">Nom complet</label>
<input type="text" id="nom" placeholder="Jean Dupont" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" placeholder="jean@email.com" required>
</div>
</div>
<div class="form-group">
<label for="sujet">Sujet</label>
<select id="sujet">
<option value="devis">Demande de devis</option>
<option value="information">Demande d'information</option>
<option value="autre">Autre</option>
</select>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea id="message" rows="5" placeholder="Décrivez votre projet..." required></textarea>
</div>
<div class="form-checkbox">
<input type="checkbox" id="rgpd" required>
<label for="rgpd">J'accepte la politique de confidentialité</label>
</div>
<button type="submit" class="btn-submit">
✉️ Envoyer le message
</button>
</form>
</div>
</section>
<!-- ============================================= -->
<!-- FOOTER -->
<!-- ============================================= -->
<footer class="footer">
<div class="footer-contenu">
<div class="footer-colonne">
<h4>🚀 MonAgence</h4>
<p>Agence digitale créative au service de vos projets web.</p>
</div>
<div class="footer-colonne">
<h4>Liens rapides</h4>
<ul>
<li><a href="#">Accueil</a></li>
<li><a href="#services">Services</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div>
<div class="footer-colonne">
<h4>Suivez-nous</h4>
<div class="footer-reseaux">
<a href="#">🐦 Twitter</a>
<a href="#">📘 LinkedIn</a>
<a href="#">📸 Instagram</a>
</div>
</div>
</div>
<div class="footer-bottom">
<p>© 2026 MonAgence — Tous droits réservés.</p>
</div>
</footer>
</body>
</html>
14.4. Code complet — CSS
/* ============================================= */
/* RESET ET BASE */
/* ============================================= */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #1a1a2e;
background: #f8f9fc;
line-height: 1.7;
}
/* ============================================= */
/* NAVBAR */
/* ============================================= */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 30px;
background: #1a1a2e;
color: white;
position: sticky;
top: 0;
z-index: 100;
box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}
.logo {
font-size: 24px;
font-weight: 700;
letter-spacing: -0.5px;
}
.nav-links {
display: flex;
list-style: none;
gap: 30px;
}
.nav-links a {
color: rgba(255,255,255,0.7);
text-decoration: none;
font-weight: 500;
padding: 6px 0;
border-bottom: 2px solid transparent;
transition: color 0.3s, border-color 0.3s;
}
.nav-links a:hover,
.nav-links a.active {
color: white;
border-bottom-color: #4361ee;
}
.menu-toggle,
.menu-hamburger {
display: none;
}
/* ============================================= */
/* HERO SECTION */
/* ============================================= */
.hero {
background: linear-gradient(135deg, #1a1a2e 0%, #3a0ca3 50%, #4361ee 100%);
color: white;
text-align: center;
padding: 80px 20px 60px;
}
.hero-contenu h1 {
font-size: 48px;
font-weight: 800;
margin-bottom: 20px;
line-height: 1.2;
}
.hero-contenu h1 span {
color: #f7d794;
}
.hero-contenu p {
font-size: 20px;
max-width: 600px;
margin: 0 auto 30px;
opacity: 0.9;
}
.btn-cta {
display: inline-block;
padding: 16px 40px;
background: white;
color: #1a1a2e;
text-decoration: none;
border-radius: 50px;
font-weight: 700;
font-size: 18px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.btn-cta:hover {
transform: translateY(-3px) scale(1.02);
box-shadow: 0 15px 35px rgba(0,0,0,0.25);
}
.hero-statistiques {
display: flex;
justify-content: center;
gap: 60px;
margin-top: 50px;
}
.stat {
display: flex;
flex-direction: column;
}
.stat-nombre {
font-size: 32px;
font-weight: 800;
color: #f7d794;
}
.stat-label {
font-size: 14px;
opacity: 0.8;
}
/* ============================================= */
/* SERVICES SECTION */
/* ============================================= */
.services {
padding: 70px 30px;
max-width: 1200px;
margin: 0 auto;
}
.services-header {
text-align: center;
margin-bottom: 50px;
}
.services-badge {
display: inline-block;
background: #eef2ff;
color: #4361ee;
padding: 4px 18px;
border-radius: 50px;
font-size: 14px;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.services-header h2 {
font-size: 38px;
margin: 12px 0 8px;
}
.services-header p {
color: #4a4e69;
font-size: 18px;
max-width: 500px;
margin: 0 auto;
}
.grille-services {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
}
.service-card {
background: white;
padding: 32px 28px;
border-radius: 16px;
text-align: center;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
border: 1px solid rgba(0,0,0,0.04);
}
.service-card:hover {
transform: translateY(-8px);
box-shadow: 0 20px 50px rgba(67, 97, 238, 0.12);
}
.service-icone {
font-size: 48px;
margin-bottom: 16px;
}
.service-card h3 {
font-size: 20px;
margin-bottom: 10px;
color: #1a1a2e;
}
.service-card p {
color: #4a4e69;
font-size: 14px;
margin-bottom: 16px;
}
.service-lien {
color: #4361ee;
text-decoration: none;
font-weight: 600;
transition: color 0.3s;
}
.service-lien:hover {
color: #3a0ca3;
}
/* ============================================= */
/* CONTACT SECTION */
/* ============================================= */
.contact {
background: #1a1a2e;
color: white;
padding: 70px 30px;
}
.contact-conteneur {
max-width: 1100px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1.5fr;
gap: 50px;
}
.contact-badge {
display: inline-block;
background: rgba(67, 97, 238, 0.2);
color: #4361ee;
padding: 4px 18px;
border-radius: 50px;
font-size: 14px;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.contact-info h2 {
font-size: 36px;
margin: 12px 0 8px;
}
.contact-info p {
opacity: 0.8;
margin-bottom: 25px;
}
.contact-details {
list-style: none;
padding: 0;
}
.contact-details li {
margin-bottom: 12px;
}
.contact-details a {
color: #4361ee;
text-decoration: none;
}
.contact-details a:hover {
text-decoration: underline;
}
.contact-form {
background: white;
color: #1a1a2e;
padding: 35px 40px;
border-radius: 16px;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-weight: 600;
font-size: 14px;
margin-bottom: 6px;
}
.form-group input,
.form-group textarea,
.form-group 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;
}
.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
border-color: #4361ee;
box-shadow: 0 0 0 4px rgba(67, 97, 238, 0.12);
outline: none;
background: white;
}
.form-group textarea {
resize: vertical;
min-height: 120px;
}
.form-checkbox {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 22px;
}
.form-checkbox input {
width: 18px;
height: 18px;
accent-color: #4361ee;
cursor: pointer;
}
.form-checkbox label {
font-size: 14px;
cursor: pointer;
}
.btn-submit {
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;
}
.btn-submit:hover {
background: #3a0ca3;
transform: translateY(-2px);
}
.btn-submit:active {
transform: scale(0.97);
}
/* ============================================= */
/* FOOTER */
/* ============================================= */
.footer {
background: #0d0d1a;
color: rgba(255,255,255,0.7);
padding: 40px 30px 0;
}
.footer-contenu {
max-width: 1100px;
margin: 0 auto;
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: 40px;
padding-bottom: 30px;
border-bottom: 1px solid rgba(255,255,255,0.06);
}
.footer-colonne h4 {
color: white;
font-size: 18px;
margin-bottom: 14px;
}
.footer-colonne p {
font-size: 14px;
line-height: 1.6;
}
.footer-colonne ul {
list-style: none;
padding: 0;
}
.footer-colonne ul li {
margin-bottom: 8px;
}
.footer-colonne ul a {
color: rgba(255,255,255,0.6);
text-decoration: none;
transition: color 0.3s;
}
.footer-colonne ul a:hover {
color: white;
}
.footer-reseaux {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.footer-reseaux a {
color: rgba(255,255,255,0.6);
text-decoration: none;
transition: color 0.3s;
}
.footer-reseaux a:hover {
color: white;
}
.footer-bottom {
text-align: center;
padding: 20px;
font-size: 14px;
opacity: 0.6;
}
/* ============================================= */
/* RESPONSIVE — TABLETTES */
/* ============================================= */
@media (max-width: 992px) {
.grille-services {
grid-template-columns: repeat(2, 1fr);
}
.contact-conteneur {
grid-template-columns: 1fr;
gap: 30px;
}
.footer-contenu {
grid-template-columns: 1fr 1fr;
}
}
/* ============================================= */
/* RESPONSIVE — MOBILES */
/* ============================================= */
@media (max-width: 768px) {
/* Navbar burger */
.menu-hamburger {
display: flex;
flex-direction: column;
gap: 5px;
cursor: pointer;
padding: 5px;
z-index: 10;
}
.menu-hamburger span {
display: block;
width: 28px;
height: 3px;
background: white;
border-radius: 2px;
transition: 0.3s ease;
}
.menu-toggle:checked + .menu-hamburger span:nth-child(1) {
transform: rotate(45deg) translate(5px, 6px);
}
.menu-toggle:checked + .menu-hamburger span:nth-child(2) {
opacity: 0;
}
.menu-toggle:checked + .menu-hamburger span:nth-child(3) {
transform: rotate(-45deg) translate(5px, -6px);
}
.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.06);
}
.nav-links li {
width: 100%;
}
.nav-links a {
display: block;
padding: 12px 16px;
border-bottom: none;
border-radius: 8px;
font-size: 18px;
}
.nav-links a:hover {
background: rgba(67, 97, 238, 0.15);
border-bottom-color: transparent;
}
.menu-toggle:checked ~ .nav-links {
display: flex;
}
/* Hero */
.hero-contenu h1 {
font-size: 30px;
}
.hero-contenu p {
font-size: 17px;
}
.hero-statistiques {
flex-direction: column;
gap: 20px;
align-items: center;
}
/* Services */
.grille-services {
grid-template-columns: 1fr;
gap: 20px;
}
.services-header h2 {
font-size: 28px;
}
/* Contact */
.form-row {
grid-template-columns: 1fr;
gap: 0;
}
.contact-form {
padding: 25px 20px;
}
/* Footer */
.footer-contenu {
grid-template-columns: 1fr;
gap: 25px;
}
}
@media (max-width: 480px) {
.navbar {
padding: 12px 16px;
}
.logo {
font-size: 20px;
}
.hero {
padding: 50px 16px 40px;
}
.hero-contenu h1 {
font-size: 26px;
}
.btn-cta {
padding: 14px 28px;
font-size: 16px;
}
.services {
padding: 40px 16px;
}
.contact {
padding: 40px 16px;
}
}