← Retour aux tutoriels

Créer des designs web responsives avec CSS : guide pour débutants

cssdesign responsiveweb designmedia queriesflexboxcss gridmobile-firstdebutants

Créer des designs web responsives avec CSS : guide pour débutants

Le web est consulté sur une immense variété d’écrans : mobiles, tablettes, ordinateurs portables, écrans 4K, téléviseurs, etc. Un design responsive (adaptatif) est un design qui s’ajuste automatiquement à la taille de l’écran, à l’orientation (portrait/paysage), et parfois même aux capacités de l’appareil (densité de pixels, préférences d’accessibilité, etc.).
Ce guide vise à expliquer en profondeur les bases et les bonnes pratiques du responsive design avec CSS, en partant de zéro, avec des exemples concrets et des commandes réelles.


Sommaire

  1. Pré-requis et objectifs
  2. Créer un petit projet (structure de fichiers)
  3. Comprendre la base : viewport, unités, flux du document
  4. Approche recommandée : mobile-first
  5. Mise en page flexible avec Flexbox
  6. Mise en page en grille avec CSS Grid
  7. Media queries : adapter selon la largeur et plus
  8. Images et médias responsives
  9. Typographie responsive (lisibilité)
  10. Conteneurs, largeurs max et centrage
  11. Navigation responsive (exemple simple)
  12. Débogage et tests
  13. Checklist de bonnes pratiques
  14. Exemple complet (HTML + CSS)

Pré-requis et objectifs

Ce que vous allez apprendre

Ce dont vous avez besoin


Créer un petit projet (structure de fichiers)

Créez un dossier de projet et des fichiers de base.

Commandes réelles (terminal)

mkdir tuto-responsive-css
cd tuto-responsive-css
mkdir css img
touch index.html css/styles.css

Optionnel mais très utile : lancer un serveur local. Si vous avez Python :

python3 -m http.server 8000

Ensuite ouvrez dans le navigateur :

Pourquoi un serveur local ? Certains navigateurs limitent des fonctionnalités quand on ouvre un fichier en file://. Un serveur local reproduit mieux un contexte réel.


Comprendre la base : viewport, unités, flux du document

1) Le viewport (zone visible)

Sur mobile, si vous ne définissez pas le viewport, le navigateur peut “simuler” une largeur plus grande et ensuite zoomer, ce qui casse souvent le responsive.

Dans votre index.html, mettez :

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

2) Le flux du document

Par défaut, les éléments HTML suivent un flux :

Le responsive design exploite ce flux naturel : plutôt que de forcer des positions rigides, on laisse le contenu se réorganiser.

3) Unités : éviter les pièges

Le responsive dépend énormément des unités.

Exemple de base :

html {
  font-size: 16px;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  line-height: 1.5;
}

Approche recommandée : mobile-first

Pourquoi mobile-first ?

Mobile-first signifie : on écrit d’abord le CSS pour petits écrans, puis on améliore pour les écrans plus larges via des media queries min-width.

Avantages :

Exemple de logique :

/* Base : mobile */
.card-list {
  display: grid;
  gap: 1rem;
}

/* À partir de 768px : tablette */
@media (min-width: 768px) {
  .card-list {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* À partir de 1024px : desktop */
@media (min-width: 1024px) {
  .card-list {
    grid-template-columns: repeat(3, 1fr);
  }
}

Mise en page flexible avec Flexbox

Flexbox est idéal pour aligner des éléments sur un axe (ligne ou colonne), gérer l’espace disponible, et créer des composants responsives.

Exemple : une barre d’actions qui s’adapte

HTML :

<div class="actions">
  <a class="btn" href="#">Télécharger</a>
  <a class="btn btn--secondary" href="#">Documentation</a>
  <a class="btn btn--ghost" href="#">Contact</a>
</div>

CSS :

.actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap; /* permet de passer à la ligne si manque de place */
}

.btn {
  display: inline-block;
  padding: 0.75rem 1rem;
  border-radius: 0.75rem;
  background: #1f6feb;
  color: white;
  text-decoration: none;
  font-weight: 600;
}

.btn--secondary { background: #2ea043; }
.btn--ghost {
  background: transparent;
  color: #1f6feb;
  border: 2px solid #1f6feb;
}

Points clés :

Exemple : en-tête avec logo à gauche et menu à droite

Sur mobile, on peut empiler.

.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem;
}

@media (max-width: 480px) {
  .header {
    flex-direction: column;
    align-items: stretch;
  }
}

Ici, on montre un cas max-width (adaptation spécifique aux très petits écrans). En pratique, vous pouvez aussi faire mobile-first avec min-width, selon votre préférence.


Mise en page en grille avec CSS Grid

CSS Grid est parfait pour des mises en page en deux dimensions : lignes et colonnes. C’est souvent la meilleure solution pour des pages complètes (sections, cartes, sidebar, etc.).

Exemple : grille de cartes responsive sans media queries complexes

HTML :

<section class="grid">
  <article class="card">Carte 1</article>
  <article class="card">Carte 2</article>
  <article class="card">Carte 3</article>
  <article class="card">Carte 4</article>
  <article class="card">Carte 5</article>
</section>

CSS :

.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.card {
  padding: 1rem;
  border: 1px solid #e5e7eb;
  border-radius: 1rem;
  background: white;
}

Explication profonde :

C’est une technique extrêmement efficace pour les galeries, listes de produits, cartes de blog, etc.


Media queries : adapter selon la largeur et plus

Les media queries permettent d’appliquer des styles selon des conditions : largeur, hauteur, orientation, préférences utilisateur.

1) Breakpoints (points de rupture)

Il n’existe pas de breakpoints universels parfaits. L’approche recommandée :

Exemple classique :

@media (min-width: 640px) { /* petit */
}

@media (min-width: 768px) { /* moyen */
}

@media (min-width: 1024px) { /* grand */
}

2) Orientation

Utile pour certains éléments (ex : vidéo, hero, mise en page d’un jeu).

@media (orientation: landscape) {
  .hero {
    min-height: 70vh;
  }
}

3) Préférences d’accessibilité : réduction des animations

Respecter prefers-reduced-motion est une excellente pratique.

@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
    transition: none !important;
    animation: none !important;
  }
}

4) Mode sombre

Vous pouvez adapter automatiquement au thème du système.

:root {
  --bg: #ffffff;
  --text: #111827;
  --card: #ffffff;
  --border: #e5e7eb;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b1220;
    --text: #e5e7eb;
    --card: #0f172a;
    --border: #243244;
  }
}

body {
  background: var(--bg);
  color: var(--text);
}

Images et médias responsives

Les images sont souvent la cause principale de pages non responsives (débordement horizontal, lenteur, flou).

1) Empêcher les images de dépasser leur conteneur

img, video {
  max-width: 100%;
  height: auto;
  display: block;
}

2) Utiliser srcset pour des images adaptées

Le navigateur peut choisir une image plus petite sur mobile, plus grande sur desktop.

<img
  src="img/photo-800.jpg"
  srcset="img/photo-400.jpg 400w, img/photo-800.jpg 800w, img/photo-1200.jpg 1200w"
  sizes="(max-width: 600px) 100vw, (max-width: 1024px) 50vw, 33vw"
  alt="Paysage de montagne"
/>

Explication :

3) Images de fond : attention

Les images en background-image ne bénéficient pas de srcset directement. Pour les héros, il vaut parfois mieux utiliser un <img> positionné, ou des techniques avancées. Pour débuter, privilégiez <img> quand l’image est du contenu important.


Typographie responsive (lisibilité)

Un design responsive, ce n’est pas seulement “ça rentre”. C’est aussi :

1) Limiter la longueur de ligne

Un texte trop large sur desktop fatigue la lecture. Utilisez une largeur max.

.prose {
  max-width: 65ch; /* environ 65 caractères par ligne */
}

ch est basé sur la largeur du caractère “0” de la police, ce qui donne une approximation pratique.

2) Taille de police fluide avec clamp()

h1 {
  font-size: clamp(1.8rem, 1.2rem + 2vw, 3rem);
  line-height: 1.1;
}

p {
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
}

Interprétation :

3) Espacements cohérents avec rem

Évitez de tout mettre en px. Utilisez rem pour que tout grandisse harmonieusement si l’utilisateur augmente la taille de police.

.section {
  padding: 2rem 1rem;
}

@media (min-width: 768px) {
  .section {
    padding: 3rem 2rem;
  }
}

Conteneurs, largeurs max et centrage

Une technique essentielle : créer un conteneur central qui limite la largeur sur grands écrans tout en restant fluide.

.container {
  width: min(1100px, 100% - 2rem);
  margin-inline: auto;
}

Explication :


Une navigation “hamburger” complète nécessite souvent un peu de JavaScript. Mais on peut déjà faire une navigation responsive simple :

HTML :

<header class="site-header">
  <div class="container header-inner">
    <a class="brand" href="#">MonSite</a>
    <nav class="nav">
      <a href="#features">Fonctionnalités</a>
      <a href="#pricing">Tarifs</a>
      <a href="#contact">Contact</a>
    </nav>
  </div>
</header>

CSS :

.site-header {
  position: sticky;
  top: 0;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0;
}

.brand {
  font-weight: 800;
  text-decoration: none;
  color: var(--text);
}

.nav {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.nav a {
  text-decoration: none;
  color: var(--text);
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
}

.nav a:hover {
  background: color-mix(in srgb, var(--text) 8%, transparent);
}

@media (max-width: 420px) {
  .header-inner {
    flex-direction: column;
    align-items: stretch;
  }

  .nav {
    justify-content: flex-start;
  }
}

Ici, on obtient un comportement simple, robuste, sans script : sur très petit écran, le logo et la nav s’empilent.


Débogage et tests

1) Utiliser le mode responsive du navigateur

Dans les outils de développement :

Testez :

2) Chercher les débordements horizontaux

Un problème fréquent : une section dépasse la largeur et crée une barre de défilement horizontale.

Astuce CSS temporaire :

* {
  outline: 1px solid color-mix(in srgb, red 35%, transparent);
}

Ou utilisez l’inspecteur pour repérer l’élément trop large. Causes typiques :

Pour les mots trop longs :

.prose {
  overflow-wrap: anywhere;
}

3) Tester l’accessibilité de base


Checklist de bonnes pratiques


Exemple complet (HTML + CSS)

Cet exemple assemble les concepts : conteneur, grille responsive, typographie fluide, images adaptatives, et media queries.

index.html

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Design responsive CSS</title>
    <link rel="stylesheet" href="css/styles.css" />
  </head>

  <body>
    <header class="site-header">
      <div class="container header-inner">
        <a class="brand" href="#">AtelierCSS</a>
        <nav class="nav">
          <a href="#features">Fonctionnalités</a>
          <a href="#gallery">Galerie</a>
          <a href="#contact">Contact</a>
        </nav>
      </div>
    </header>

    <main>
      <section class="hero section">
        <div class="container hero-inner">
          <div class="hero-text">
            <h1>Construisez une page qui s’adapte à tous les écrans</h1>
            <p class="lead">
              Apprenez les bases du responsive design avec des techniques modernes :
              unités fluides, Flexbox, Grid, media queries et images optimisées.
            </p>
            <div class="actions">
              <a class="btn" href="#features">Découvrir</a>
              <a class="btn btn--ghost" href="#gallery">Voir des exemples</a>
            </div>
          </div>

          <div class="hero-media">
            <img
              src="img/hero-800.jpg"
              srcset="img/hero-400.jpg 400w, img/hero-800.jpg 800w, img/hero-1200.jpg 1200w"
              sizes="(max-width: 900px) 100vw, 45vw"
              alt="Aperçu d’une interface web"
              loading="lazy"
            />
          </div>
        </div>
      </section>

      <section id="features" class="section">
        <div class="container">
          <h2>Fonctionnalités clés</h2>
          <p class="prose">
            Un bon responsive design s’appuie sur des mises en page flexibles et sur
            des règles simples. Ci-dessous, une grille qui s’adapte automatiquement
            grâce à <code>auto-fit</code> et <code>minmax()</code>.
          </p>

          <div class="grid cards">
            <article class="card">
              <h3>Mobile-first</h3>
              <p>Commencez petit, puis améliorez pour les écrans plus larges.</p>
            </article>
            <article class="card">
              <h3>Grilles fluides</h3>
              <p>Utilisez CSS Grid pour des colonnes qui apparaissent quand l’espace le permet.</p>
            </article>
            <article class="card">
              <h3>Typographie lisible</h3>
              <p>Limitez la longueur des lignes et utilisez <code>clamp()</code>.</p>
            </article>
            <article class="card">
              <h3>Médias adaptatifs</h3>
              <p>Évitez les images trop lourdes et empêchez les débordements.</p>
            </article>
          </div>
        </div>
      </section>

      <section id="gallery" class="section section--alt">
        <div class="container">
          <h2>Galerie responsive</h2>
          <p class="prose">
            Cette galerie utilise une grille automatique. Redimensionnez la fenêtre :
            le nombre de colonnes change sans breakpoints explicites.
          </p>

          <div class="grid gallery">
            <figure class="tile"><img src="img/pic-1-800.jpg" alt="Exemple 1" loading="lazy" /></figure>
            <figure class="tile"><img src="img/pic-2-800.jpg" alt="Exemple 2" loading="lazy" /></figure>
            <figure class="tile"><img src="img/pic-3-800.jpg" alt="Exemple 3" loading="lazy" /></figure>
            <figure class="tile"><img src="img/pic-4-800.jpg" alt="Exemple 4" loading="lazy" /></figure>
            <figure class="tile"><img src="img/pic-5-800.jpg" alt="Exemple 5" loading="lazy" /></figure>
            <figure class="tile"><img src="img/pic-6-800.jpg" alt="Exemple 6" loading="lazy" /></figure>
          </div>
        </div>
      </section>

      <section id="contact" class="section">
        <div class="container">
          <h2>Contact</h2>
          <p class="prose">
            Exemple de formulaire simple. Remarquez l’utilisation de <code>grid</code> pour
            aligner les champs sur grand écran, tout en restant en une colonne sur mobile.
          </p>

          <form class="form">
            <label>
              Nom
              <input type="text" name="name" autocomplete="name" />
            </label>

            <label>
              Email
              <input type="email" name="email" autocomplete="email" />
            </label>

            <label class="form-full">
              Message
              <textarea name="message" rows="5"></textarea>
            </label>

            <div class="form-full">
              <button class="btn" type="submit">Envoyer</button>
            </div>
          </form>
        </div>
      </section>
    </main>

    <footer class="footer">
      <div class="container">
        <p>© <span id="year">2026</span> AtelierCSS — Démo responsive CSS.</p>
      </div>
    </footer>
  </body>
</html>

css/styles.css

:root {
  --bg: #ffffff;
  --text: #0f172a;
  --muted: #475569;
  --card: #ffffff;
  --border: #e5e7eb;
  --brand: #1f6feb;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b1220;
    --text: #e5e7eb;
    --muted: #a5b4fc;
    --card: #0f172a;
    --border: #243244;
    --brand: #60a5fa;
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 16px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  line-height: 1.5;
}

img, video {
  max-width: 100%;
  height: auto;
  display: block;
}

.container {
  width: min(1100px, 100% - 2rem);
  margin-inline: auto;
}

.section {
  padding: 2.5rem 0;
}

.section--alt {
  background: color-mix(in srgb, var(--text) 4%, transparent);
}

h1 {
  font-size: clamp(2rem, 1.2rem + 3vw, 3.25rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 1rem;
}

h2 {
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.2rem);
  margin: 0 0 0.75rem;
}

h3 {
  margin: 0 0 0.5rem;
}

p {
  margin: 0 0 1rem;
  color: var(--text);
}

.lead {
  font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem);
  color: var(--muted);
}

.prose {
  max-width: 65ch;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0;
}

.brand {
  font-weight: 900;
  text-decoration: none;
  color: var(--text);
}

.nav {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.nav a {
  text-decoration: none;
  color: var(--text);
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
}

.nav a:hover {
  background: color-mix(in srgb, var(--text) 10%, transparent);
}

.hero-inner {
  display: grid;
  gap: 1.5rem;
  align-items: center;
}

/* Mobile-first : une colonne par défaut */
.hero-media img {
  border-radius: 1.25rem;
  border: 1px solid var(--border);
}

/* À partir de 900px : deux colonnes */
@media (min-width: 900px) {
  .hero-inner {
    grid-template-columns: 1.1fr 0.9fr;
  }
}

.actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.btn {
  display: inline-block;
  padding: 0.75rem 1rem;
  border-radius: 0.9rem;
  background: var(--brand);
  color: #ffffff;
  text-decoration: none;
  font-weight: 700;
  border: 2px solid transparent;
}

.btn--ghost {
  background: transparent;
  color: var(--brand);
  border-color: var(--brand);
}

.grid {
  display: grid;
  gap: 1rem;
}

.cards {
  margin-top: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 1rem;
  padding: 1rem;
}

.gallery {
  margin-top: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}

.tile {
  margin: 0;
  border-radius: 1rem;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--card);
}

.tile img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.form {
  margin-top: 1rem;
  display: grid;
  gap: 1rem;
}

/* Mobile-first : une colonne */
.form label {
  display: grid;
  gap: 0.5rem;
  color: var(--muted);
  font-weight: 600;
}

input, textarea {
  width: 100%;
  padding: 0.75rem 0.9rem;
  border-radius: 0.9rem;
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  color: var(--text);
  font: inherit;
}

input:focus, textarea:focus {
  outline: 3px solid color-mix(in srgb, var(--brand) 35%, transparent);
  border-color: color-mix(in srgb, var(--brand) 60%, var(--border));
}

.form-full {
  grid-column: 1 / -1;
}

/* À partir de 700px : formulaire en deux colonnes */
@media (min-width: 700px) {
  .form {
    grid-template-columns: repeat(2, 1fr);
  }
}

.footer {
  border-top: 1px solid var(--border);
  padding: 1.5rem 0;
  color: var(--muted);
}

/* Ajustement pour très petits écrans */
@media (max-width: 420px) {
  .header-inner {
    flex-direction: column;
    align-items: stretch;
  }

  .nav {
    justify-content: flex-start;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
    transition: none !important;
    animation: none !important;
  }
}

Comment aller plus loin

Une fois ces bases maîtrisées, vous pouvez approfondir :

Si vous voulez, décrivez le type de page que vous souhaitez rendre responsive (blog, portfolio, boutique, landing page) et je peux proposer une structure de sections, des breakpoints adaptés au contenu, et une grille CSS prête à l’emploi.