Design responsive avec Claude Code : CSS mobile-first et verification Playwright
Design responsive avec Claude Code: CSS mobile-first, clamp, grilles, images, navigation, tableaux et Playwright.
Fixer les criteres avant de modifier le CSS
Le design responsive ne consiste pas a reduire une page desktop jusqu’a ce qu’elle tienne sur un telephone. Une page publiable doit tenir compte de la largeur d’ecran, des zones tactiles, du poids des images, de la priorite de navigation, de la lisibilite des tableaux, des annonces et des CTA de conversion. Si vous demandez seulement a Claude Code de “rendre la page mobile”, il peut corriger une largeur precise tout en laissant du scroll horizontal, des cartes a largeur fixe, une image hero trop lourde, une navigation trop serree ou un bouton d’achat enfoui plus bas.
La meilleure approche est de donner un contrat court et verifiable. Le CSS mobile-first signifie que la version etroite est la base, puis que les grands ecrans ajoutent des ameliorations. clamp() est une fonction CSS qui definit une valeur minimale, ideale et maximale. Les container queries permettent a un composant de reagir a la largeur de son conteneur, pas seulement a celle du viewport. Ces definitions simples evitent beaucoup de demandes floues et rendent le diff de Claude Code plus facile a relire.
Pour les references officielles, utilisez MDN: Responsive design, @container, clamp() et responsive images. Pour la verification, appuyez-vous sur Playwright Screenshots et Visual comparisons. Les pages officielles Claude Code overview et How Claude Code works decrivent Claude Code comme un outil qui lit le code, modifie des fichiers, lance des commandes et verifie le resultat. C’est exactement le bon cadre pour ce travail.
Pour completer, consultez aussi les design systems avec Claude Code, l’accessibilite avec Claude Code et les tests Playwright avec Claude Code.
Plan d’implementation
Un correctif responsive echoue souvent quand le CSS arrive comme un patch final. Demandez a Claude Code d’inspecter la page existante, d’identifier les largeurs ou chaque composant casse, puis de modifier CSS, images et tests ensemble.
flowchart LR
A["Lire la page existante"] --> B["Base CSS mobile-first"]
B --> C["Grille fluide et clamp()"]
C --> D["Composants avec container query"]
D --> E["Images et tableaux responsives"]
E --> F["Captures Playwright"]
Voici un prompt de depart:
Rends la page existante /responsive-demo responsive.
Exigences:
- Utiliser du CSS mobile-first.
- Eviter le scroll horizontal en 320px, 390px, 768px, 1024px et 1440px.
- La navigation, les cartes, le tableau de prix, le CTA et le footer ne doivent pas se chevaucher.
- Les images de contenu doivent avoir width/height, srcset, sizes, loading et un alt utile.
- Prioriser CSS Grid, clamp() et @container avant d'ajouter du JavaScript pour detecter la largeur.
- Apres modification, lancer des captures Playwright et une assertion d'overflow.
A ne pas faire:
- Ne pas casser les URLs, les liens de conversion ni la hierarchie accessible des titres.
- Ne pas ajouter de grands min-width fixes qui creent un scroll horizontal sur toute la page.
Le prompt donne un objectif, des limites et une preuve. Il devient simple de refuser une solution qui ne fonctionne qu’en desktop.
HTML pret a copier
Cet exemple couvre les problemes courants: navigation, hero, image, cartes, panneau lateral et tableau comparatif. Remplacez les chemins d’images par ceux de votre projet et utilisez le CSS de la section suivante.
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Responsive Demo</title>
<link rel="stylesheet" href="./responsive-demo.css" />
</head>
<body>
<header class="site-nav">
<a class="brand" href="/">ClaudeCodeLab</a>
<nav class="nav-links" aria-label="Navigation principale">
<a href="/fr/blog/">Articles</a>
<a href="/en/products/">Produits</a>
<a href="/en/training/">Conseil</a>
</nav>
</header>
<main class="page-shell">
<section class="hero">
<div>
<p class="eyebrow">Responsive Design</p>
<h1>Concevoir d'abord le petit ecran, puis laisser grandir la mise en page</h1>
<p class="lead">
Mettez en place CSS mobile-first, grilles fluides, images responsives et controles Playwright dans un seul workflow.
</p>
<a class="primary-cta" href="/en/products/">Voir les templates de prompts</a>
</div>
<picture class="hero-media">
<source
type="image/avif"
srcset="/images/responsive-demo-640.avif 640w, /images/responsive-demo-1280.avif 1280w"
sizes="(width < 768px) 92vw, 40vw"
/>
<img
src="/images/responsive-demo-1280.jpg"
alt="Un telephone et un ordinateur affichant la meme page responsive"
width="1280"
height="900"
loading="eager"
decoding="async"
/>
</picture>
</section>
<div class="layout-grid">
<aside class="side-panel" aria-label="Checklist viewport">
<h2>Largeurs a verifier</h2>
<ul>
<li>320px: petit telephone</li>
<li>390px: telephone courant</li>
<li>768px: tablette</li>
<li>1024px et plus: desktop</li>
</ul>
</aside>
<section class="cards" aria-label="Cartes d'amelioration">
<article class="card featured">
<img src="/images/card-layout.jpg" alt="" width="720" height="480" loading="lazy" />
<div class="card-body">
<h2>Les cartes reagissent au conteneur</h2>
<p>Un composant reutilisable doit adapter sa densite selon l'espace disponible autour de lui.</p>
</div>
</article>
<article class="card">
<div class="card-body">
<h2>La navigation peut passer a la ligne</h2>
<p>Ne compressez pas tous les liens desktop dans une seule ligne mobile.</p>
</div>
</article>
<article class="card">
<div class="card-body">
<h2>Le tableau garde son sens</h2>
<p>Sur petit ecran, les lignes deviennent des cartes et `data-label` conserve le nom de colonne.</p>
</div>
</article>
</section>
</div>
<section class="comparison">
<h2>Comparaison des offres</h2>
<table class="responsive-table">
<thead>
<tr>
<th scope="col">Element</th>
<th scope="col">Solo</th>
<th scope="col">Equipe</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Element">Objectif</td>
<td data-label="Solo">Apprentissage et petites ameliorations</td>
<td data-label="Equipe">Standards de review coherents</td>
</tr>
<tr>
<td data-label="Element">Preuve</td>
<td data-label="Solo">Playwright local</td>
<td data-label="Equipe">Captures en CI</td>
</tr>
</tbody>
</table>
</section>
</main>
</body>
</html>
CSS mobile-first, grille fluide et clamp
La base CSS correspond au petit ecran. Les colonnes et le layout plus dense arrivent seulement quand la largeur le permet. Les cartes utilisent repeat(auto-fit, minmax(...)), les tailles utilisent clamp(), et la carte mise en avant change quand son propre conteneur est assez large.
* {
box-sizing: border-box;
}
body {
margin: 0;
color: #172033;
background: #f7f8fb;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
img {
display: block;
max-width: 100%;
height: auto;
}
.site-nav,
.page-shell {
width: min(100% - 2rem, 72rem);
margin-inline: auto;
}
.site-nav {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
flex-wrap: wrap;
padding-block: 1rem;
}
.brand,
.nav-links a,
.primary-cta {
min-height: 44px;
display: inline-flex;
align-items: center;
}
.nav-links {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.nav-links a {
padding-inline: 0.75rem;
color: inherit;
text-decoration: none;
}
.page-shell {
padding-block: clamp(1rem, 4vw, 3rem);
}
.hero {
display: grid;
gap: clamp(1rem, 4vw, 2.5rem);
align-items: center;
}
.hero h1 {
max-width: 11ch;
margin: 0;
font-size: clamp(2.25rem, 10vw, 5rem);
line-height: 1.02;
}
.lead {
max-width: 62ch;
font-size: clamp(1rem, 2vw, 1.25rem);
line-height: 1.8;
}
.primary-cta {
width: fit-content;
border-radius: 0.5rem;
padding: 0.75rem 1rem;
background: #172033;
color: white;
text-decoration: none;
font-weight: 700;
}
.layout-grid {
display: grid;
gap: clamp(1rem, 3vw, 2rem);
margin-block-start: 2rem;
}
.cards {
container: cards / inline-size;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
gap: 1rem;
}
.side-panel,
.card,
.comparison {
background: white;
border: 1px solid #dbe3ef;
border-radius: 0.75rem;
}
.card {
overflow: hidden;
}
.card-body,
.side-panel,
.comparison {
padding: 1rem;
}
@container cards (width >= 42rem) {
.card.featured {
grid-column: span 2;
display: grid;
grid-template-columns: minmax(14rem, 0.8fr) 1fr;
}
.card.featured img {
height: 100%;
object-fit: cover;
}
}
.comparison {
margin-block-start: 2rem;
overflow-x: auto;
}
.responsive-table {
width: 100%;
border-collapse: collapse;
}
.responsive-table th,
.responsive-table td {
padding: 0.875rem;
border-block-end: 1px solid #dbe3ef;
text-align: left;
}
@media (width < 48rem) {
.responsive-table thead {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
}
.responsive-table,
.responsive-table tbody,
.responsive-table tr,
.responsive-table td {
display: block;
width: 100%;
}
.responsive-table tr {
border: 1px solid #dbe3ef;
border-radius: 0.5rem;
margin-block: 0.75rem;
overflow: hidden;
}
.responsive-table td {
display: grid;
grid-template-columns: minmax(7rem, 40%) 1fr;
gap: 1rem;
}
.responsive-table td::before {
content: attr(data-label);
font-weight: 700;
color: #526071;
}
}
@media (width >= 64rem) {
.hero {
grid-template-columns: minmax(0, 1.1fr) minmax(18rem, 0.9fr);
}
.layout-grid {
grid-template-columns: 16rem minmax(0, 1fr);
}
}
Le point critique est l’absence de grandes largeurs fixes. width: min(100% - 2rem, 72rem) garde une marge sur mobile et limite la largeur de lecture sur desktop. minmax(min(100%, 18rem), 1fr) evite qu’une carte impose une largeur minimale trop grande.
Images, navigation, cartes et tableaux
Donnez a Claude Code des criteres par composant.
| Composant | Probleme courant | Correction a demander |
|---|---|---|
| Navigation | Liens desktop comprimes sur mobile | Autoriser le retour ligne, garder les zones tactiles et aria-label |
| Cartes | width: 320px ou grand min-width cree un overflow | Utiliser auto-fit, minmax() et container queries |
| Images | Le mobile charge le meme grand JPEG | Ajouter srcset, sizes, width, height, loading et alt |
| Tableaux | Colonnes illisibles | Choisir scroll du wrapper ou cartes par ligne avec data-label |
| CTA | Le lien de revenu est enterre | Verifier le premier scroll mobile et la fin d’article |
Un petit menu n’a pas toujours besoin d’un hamburger. Trois liens qui passent a la ligne peuvent etre plus efficaces. Un tableau de prix peut necessiter une comparaison horizontale, alors qu’une liste de tickets se lit mieux ligne par ligne sous forme de cartes.
Cas d’usage a verifier
Premier cas: un dashboard SaaS. Sidebar, filtres, cartes KPI, graphiques et tableau coexistent. En mobile, il faut afficher les KPI prioritaires, replier les filtres secondaires et transformer les lignes detaillees en cartes lisibles.
Deuxieme cas: un blog ou site media. Largeur du texte, sommaire, publicite, articles lies et CTA PDF gratuit se disputent l’espace. Verifiez la longueur de ligne, le chargement des images, les blocs de code et la visibilite du CTA.
Troisieme cas: une page e-commerce ou de vente de formation. Cartes produit, comparaison de prix, bouton d’achat et FAQ ont un impact direct sur le revenu. Si le prix ou le bouton descend trop bas sur mobile, la conversion baisse.
Quatrieme cas: une interface interne. Les utilisateurs quotidiens veulent surtout recherche, filtres, clavier et tableaux lisibles. Le responsive doit proteger leur ordre de travail.
Verifier avec Playwright
Ne terminez pas la tache parce que “ca a l’air bon” dans un navigateur. Playwright peut tester plusieurs largeurs, verifier la visibilite des elements, detecter l’overflow horizontal et enregistrer des captures.
import { expect, test } from "@playwright/test";
const baseUrl = process.env.PLAYWRIGHT_BASE_URL ?? "http://127.0.0.1:3000";
const viewports = [
{ name: "mobile-320", width: 320, height: 740 },
{ name: "mobile-390", width: 390, height: 844 },
{ name: "tablet-768", width: 768, height: 1024 },
{ name: "desktop-1440", width: 1440, height: 1000 },
];
for (const viewport of viewports) {
test(`responsive demo has no horizontal overflow at ${viewport.name}`, async ({ page }) => {
await page.setViewportSize({ width: viewport.width, height: viewport.height });
await page.goto(`${baseUrl}/responsive-demo`);
await expect(page.getByRole("navigation", { name: "Navigation principale" })).toBeVisible();
await expect(page.getByRole("link", { name: "Voir les templates de prompts" })).toBeVisible();
const hasHorizontalOverflow = await page.evaluate(() => {
return document.documentElement.scrollWidth > document.documentElement.clientWidth;
});
expect(hasHorizontalOverflow).toBe(false);
await expect(page).toHaveScreenshot(`responsive-${viewport.name}.png`, {
fullPage: true,
maxDiffPixels: 300,
});
});
}
La premiere execution cree les captures de reference. Mettez-les a jour avec npx playwright test --update-snapshots seulement quand le changement visuel est voulu. Les captures dependent de l’OS, du rendu des polices, du GPU et du mode headless; comparez-les dans le meme environnement CI.
Pieges frequents
Le premier piege est le CSS desktop-first surcharge par des correctifs mobiles. Cela fonctionne au debut, puis la cascade devient opaque. Demandez a Claude Code de replacer le petit ecran dans les regles de base et d’ajouter les colonnes ensuite.
Le deuxieme piege est l’oubli de <meta name="viewport">. Sans lui, un navigateur mobile peut rendre la page avec une largeur virtuelle de desktop.
Le troisieme piege est la largeur fixe cachee dans une carte, un tableau, une image ou un embed. min-width: 960px peut passer inapercu sur desktop et casser tous les telephones. Si un tableau doit scroller, appliquez overflow-x: auto a son wrapper seulement.
Le quatrieme piege est srcset sans sizes. Le navigateur a besoin des candidats et d’un indice sur la taille rendue. Revoyez srcset, sizes, width, height et alt ensemble.
Le cinquieme piege est de tout confier aux captures. Elles sont utiles, mais les annonces, dates, animations et widgets tiers creent du bruit. Ajoutez des assertions DOM pour l’overflow, les CTA visibles et les landmarks de navigation.
Inclure le chemin de revenu
Le responsive doit aussi proteger l’objectif business. Sur ClaudeCodeLab, un lecteur mobile doit pouvoir trouver le PDF gratuit, les produits Gumroad et la consultation. Pour des workflows reutilisables, consultez Claude Code products. Pour travailler sur de vrais ecrans avec regles de review et verification Playwright, consultez Claude Code training.
Ajoutez le chemin de conversion dans le brief donne a Claude Code. Une page propre qui cache le bouton d’achat ou le lien de contact n’est pas terminee.
Conclusion
Le workflow pratique est: definir le contrat mobile-first, construire des grilles fluides, utiliser clamp() pour tailles et espacements, appliquer les container queries aux composants reutilisables, traiter les images, adapter navigation et tableaux, puis verifier avec Playwright.
J’ai teste le modele de cet article en 320px, 390px, 768px et 1440px. La navigation passe a la ligne sans overflow, les cartes deviennent une colonne sur mobile, le tableau se lit comme des cartes par ligne et l’assertion Playwright d’overflow passe. Le retour terrain de Masa est simple: Claude Code devient beaucoup plus utile quand il implemente puis relit les largeurs fixes, les hints d’image, la position du CTA, le comportement des tableaux et les differences de captures.
PDF gratuit: cheatsheet Claude Code
Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.
Nous protégeons vos données et n'envoyons pas de spam.
À propos de l'auteur
Masa
Ingénieur spécialisé dans les workflows pratiques avec Claude Code.
Articles liés
Échelle de sécurité des permissions Claude Code
Passer du read-only aux éditions limitées, preuves et checks de déploiement sans perdre le contrôle.
Claude Code Small PR Proof Pack : rendre les petits changements reviewables
Un pack de preuve pour PR Claude Code : diff, vérifications, URL publique, CTA et rollback.
Gate de review avant commit avec Claude Code
Review avant commit avec Claude Code : diff, build, URL publique, liens Gumroad, CTA consultation, tests manquants et fichiers hors scope.