Les bases du CSS
Syntaxe, sélecteurs, modèle de boîte
Ouvrir le cours
Créez des interfaces qui s’adaptent parfaitement à tous les appareils. Mobile, tablette, bureau : une seule base de code, tous les écrans.
Un même site est lu sur un téléphone tenu d’une main et sur un écran de bureau. Les contraintes ne sont pas les mêmes — la feuille de style doit le savoir.
Parts de trafic mondial relevées en juillet 2026 (StatCounter).
53 % du trafic web
1,5 % du trafic
46 % du trafic
css
/* Base : Mobile (320px+) */
.container {
padding: 1rem;
font-size: 16px;
}
/* Tablette (768px+) */
@media (min-width: 768px) {
.container {
padding: 2rem;
font-size: 18px;
}
}
/* Desktop (1200px+) */
@media (min-width: 1200px) {
.container {
padding: 3rem;
font-size: 20px;
}
}
css
/* Base : Desktop (1200px+) */
.container {
padding: 3rem;
font-size: 20px;
}
/* Tablette (max 1199px) */
@media (max-width: 1199px) {
.container {
padding: 2rem;
font-size: 18px;
}
}
/* Mobile (max 767px) */
@media (max-width: 767px) {
.container {
padding: 1rem;
font-size: 16px;
}
}
Une media query pose une condition sur l’appareil. Tant qu’elle est vraie, ses règles s’appliquent ; sinon elles sont ignorées.
largeur simulée
Optimisé pour mobile
Navigation complète
Article complet avec sidebar visible
Widgets et liens
Largeur simulée : . Media query active : @media (max-width: 768px) @media (min-width: 769px)
/* Mobile */ .layout { flex-direction: column; gap: 1rem; } .sidebar { order: 3; }
/* Desktop */ .layout { display: flex; gap: 2rem; }
La largeur n’est qu’un moyen : ce qui se déclenche, c’est la media query affichée sous le cadre.
La largeur est le critère le plus employé, mais ce n’est pas le seul : une media query peut interroger l’orientation, la finesse de l’écran ou une préférence du lecteur.
css
/* Largeur minimale */
@media (min-width: 768px) { }
/* Largeur maximale */
@media (max-width: 767px) { }
/* Plage de largeur */
@media (min-width: 768px) and (max-width: 1023px) { }
css
/* Orientation */
@media (orientation: landscape) { }
@media (orientation: portrait) { }
/* Résolution */
@media (-webkit-min-device-pixel-ratio: 2) { }
/* Préférence utilisateur */
@media (prefers-color-scheme: dark) { }
📱 Mobile
320 px – 767 px
📱 Tablette
768 px – 1023 px
💻 Bureau
1024 px – 1199 px
🖥️ Large
1200 px et plus
largeur simulée
Largeur simulée : . Media query active : @media (max-width: 768px) @media (min-width: 769px)
/* Navigation mobile */ @media (max-width: 768px) { .nav-menu { display: none; } .hamburger { display: block; } }
/* Navigation desktop */ .nav-menu { display: flex; gap: 2rem; }
Sous 768 px, le menu disparaît et le hamburger prend sa place. Il s’ouvre au clic, comme sur un vrai site.
Les media queries posent des paliers. Les unités et les fonctions fluides, elles, évitent d’avoir à en poser.
css
/* Unités relatives */
.container {
width: 90%; /* Pourcentage */
max-width: 1200px;
padding: 2rem; /* Basé sur root */
margin: 1em; /* Basé sur parent */
}
/* Unités viewport */
.hero {
height: 100vh; /* Hauteur écran */
width: 100vw; /* Largeur écran */
font-size: 4vw; /* Proportionnel */
}
Elles calculent une valeur au lieu de la fixer : plus de palier à écrire, la taille suit d’elle-même.
clamp(min, préféré, max) — une taille fluide, bornée des deux côtés.
css
/* Typographie fluide */
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
}
/* Container adaptatif */
.container {
width: clamp(300px, 90%, 1200px);
}
La plus petite, ou la plus grande, de deux valeurs.
css
/* Largeur maximum */
.box {
width: min(90%, 600px);
}
/* Hauteur minimum */
.card {
height: max(200px, 20vh);
}
/* Taille de texte minimum */
.text {
font-size: max(16px, 1rem);
}
Une condition sur le PARENT, et non sur la fenêtre. Support récent des navigateurs.
css
/* Conteneur queryable */
.sidebar {
container-type: inline-size;
}
/* Query sur le container */
@container (min-width: 300px) {
.card {
display: flex;
}
}
Comment une image occupe le cadre qu’on lui donne.
css
/* Object-fit pour conteneurs */
.image-container img {
width: 100%;
height: 200px;
object-fit: cover;
}
font-size
font-size: ;
Élargissez ou rétrécissez la fenêtre : la taille suit, sans jamais sortir des deux bornes.
Les mêmes techniques, appliquées à ce qu’on rencontre sur de vrais sites.
auto-fill crée autant de colonnes que la place le permet, minmax garantit une largeur minimale, clamp fait respirer les espacements. Aucune media query.
css
/* Grille adaptative moderne */
.products-grid {
display: grid;
grid-template-columns:
repeat(auto-fill, minmax(280px, 1fr));
gap: clamp(1rem, 3vw, 2rem);
padding: clamp(1rem, 4vw, 3rem);
}
.product-card {
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
transition: transform 0.2s ease;
}
.product-card:hover {
transform: translateY(-4px);
}
Une colonne sur mobile, deux à partir de 768 px. Et un détail qui compte : font-size: max(16px, 1rem) empêche iOS de zoomer au moment de la saisie.
css
/* Layout de formulaire adaptatif */
.form-container {
max-width: 600px;
margin: 0 auto;
padding: clamp(1rem, 4vw, 2rem);
}
.form-row {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
margin-bottom: 1.5rem;
}
@media (min-width: 768px) {
.form-row.two-cols {
grid-template-columns: 1fr 1fr;
}
}
.form-input {
width: 100%;
font-size: max(16px, 1rem);
}
Les zones nommées se redessinent d’un palier à l’autre : empilées sur mobile, réparties en trois colonnes sur bureau. Le balisage, lui, ne bouge pas.
css
/* Dashboard avec Grid Areas */
.dashboard {
display: grid;
gap: 1rem;
padding: 1rem;
min-height: 100vh;
}
/* Mobile : Stack vertical */
.dashboard {
grid-template-areas:
"header"
"stats"
"chart"
"sidebar";
}
/* Desktop : Layout complexe */
@media (min-width: 1024px) {
.dashboard {
grid-template-columns: 250px 1fr 300px;
grid-template-rows: 60px 1fr;
grid-template-areas:
"sidebar header stats"
"sidebar chart stats";
}
}
Créez un site e-commerce complet qui s’adapte parfaitement à tous les appareils avec une expérience utilisateur optimisée.
html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ShopResponsive - E-commerce Adaptatif</title>
<style>
/* Reset et base */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
color: #333;
}
/* Container responsive */
.container {
width: min(90%, 1200px);
margin: 0 auto;
padding: 0 clamp(1rem, 4vw, 2rem);
}
/* Header responsive */
.header {
background: white;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 100;
}
.nav {
/* TODO: Flex layout pour header responsive */
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 0;
}
.nav-menu {
/* TODO: Navigation qui se cache sur mobile */
display: none;
}
.hamburger {
/* TODO: Menu hamburger pour mobile */
display: block;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
}
/* Hero section */
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
text-align: center;
padding: clamp(3rem, 8vw, 6rem) 0;
}
.hero h1 {
/* TODO: Typographie fluide avec clamp */
font-size: clamp(2rem, 5vw, 3.5rem);
margin-bottom: 1rem;
}
.hero p {
font-size: clamp(1rem, 2.5vw, 1.25rem);
margin-bottom: 2rem;
opacity: 0.9;
}
.cta-button {
/* TODO: Bouton responsive */
display: inline-block;
background: white;
color: #667eea;
padding: clamp(0.75rem, 2vw, 1rem) clamp(1.5rem, 4vw, 2rem);
text-decoration: none;
border-radius: 50px;
font-weight: bold;
transition: transform 0.2s ease;
}
/* Grille produits */
.products-section {
padding: clamp(3rem, 6vw, 5rem) 0;
}
.products-grid {
/* TODO: Grille adaptive sans media queries */
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: clamp(1rem, 3vw, 2rem);
margin-top: 2rem;
}
.product-card {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
transition: transform 0.2s ease;
}
.product-card:hover {
transform: translateY(-4px);
}
.product-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.product-info {
padding: 1.5rem;
}
/* Media Queries */
@media (min-width: 768px) {
.nav-menu {
display: flex;
gap: 2rem;
}
.hamburger {
display: none;
}
.hero {
text-align: left;
}
/* TODO: Layout desktop avec sidebar filtres */
}
@media (min-width: 1024px) {
.main-layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 2rem;
}
.filters-sidebar {
background: #f8f9fa;
padding: 2rem;
border-radius: 12px;
height: fit-content;
position: sticky;
top: 100px;
}
}
/* Formulaire responsive */
.contact-form {
max-width: 600px;
margin: 0 auto;
}
.form-group {
display: grid;
gap: 1rem;
margin-bottom: 1.5rem;
}
.form-group.two-cols {
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.form-group.two-cols {
grid-template-columns: 1fr 1fr;
}
}
.form-input {
width: 100%;
padding: 0.75rem;
font-size: max(16px, 1rem); /* Évite le zoom iOS */
border: 2px solid #e2e8f0;
border-radius: 8px;
transition: border-color 0.2s ease;
}
.form-input:focus {
outline: none;
border-color: #667eea;
}
/* Footer responsive */
.footer {
background: #1a1a1a;
color: white;
padding: clamp(2rem, 4vw, 3rem) 0;
}
.footer-content {
display: grid;
gap: 2rem;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.footer-content {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
}
</style>
</head>
<body>
<header class="header">
<div class="container">
<nav class="nav">
<div class="logo">
<h1>ShopResponsive</h1>
</div>
<div class="nav-menu">
<a href="#">Accueil</a>
<a href="#products">Produits</a>
<a href="#contact">Contact</a>
</div>
<div class="nav-actions">
<button class="hamburger">☰</button>
<a href="#" class="cart">🛒 Panier (0)</a>
</div>
</nav>
</div>
</header>
<section class="hero">
<div class="container">
<h1>Découvrez nos Produits</h1>
<p>Une sélection unique de produits de qualité</p>
<a href="#products" class="cta-button">Voir les Produits</a>
</div>
</section>
<section id="products" class="products-section">
<div class="container">
<h2>Nos Produits</h2>
<div class="main-layout">
<aside class="filters-sidebar">
<h3>Filtres</h3>
<!-- TODO: Ajouter filtres -->
</aside>
<div class="products-grid">
<div class="product-card">
<img src="https://via.placeholder.com/300x200" alt="Produit" class="product-image" loading="lazy">
<div class="product-info">
<h3>Produit Exemple</h3>
<p>Description du produit...</p>
<div class="price">29,99 €</div>
<button>Ajouter au Panier</button>
</div>
</div>
<!-- TODO: Répéter pour plus de produits -->
</div>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="footer-content">
<div>
<h4>ShopResponsive</h4>
<p>Votre boutique en ligne de confiance</p>
</div>
<div>
<h4>Liens Utiles</h4>
<ul>
<li><a href="#">À propos</a></li>
<li><a href="#">Contact</a></li>
</ul>
</div>
</div>
</div>
</footer>
<script>
// TODO: JavaScript pour menu mobile
document.querySelector('.hamburger').addEventListener('click', function() {
// Toggle menu mobile
});
</script>
</body>
</html>
Vous savez poser des paliers, choisir des unités qui suivent l’écran et laisser les fonctions fluides faire le reste. Une seule base de code, tous les appareils.
Commencez toujours par le mobile, puis enrichissez
clamp(), min(), max() pour des tailles fluides
Trois suffisent presque toujours : 768, 1024, 1200
Syntaxe, sélecteurs, modèle de boîte
Ouvrir le coursAligner sur un axe
Ouvrir le coursComposer en deux dimensions
Ouvrir le coursMettre en mouvement
Ouvrir le cours