Diseno responsivo con Claude Code: guia practica con CSS y Playwright
Implementa diseno responsivo con Claude Code: CSS mobile-first, clamp, grids, imagenes, navegacion, tablas y Playwright.
Define los criterios antes de pedir cambios
El diseno responsivo no consiste en encoger una pagina de escritorio hasta que quepa en un telefono. Una pagina lista para publicar debe cuidar ancho de pantalla, zonas tactiles, peso de imagenes, prioridad de navegacion, legibilidad de tablas, anuncios y llamadas a la accion. Si le dices a Claude Code solo “hazlo mobile friendly”, puede arreglar una vista concreta y dejar problemas escondidos: scroll horizontal, tarjetas con ancho fijo, imagen hero demasiado pesada, menu apretado o un boton de compra perdido muy abajo.
La forma fiable es entregar un contrato pequeno y concreto. CSS mobile-first significa que el diseno estrecho es la base y las pantallas grandes agregan mejoras. clamp() es una funcion CSS para definir valor minimo, preferido y maximo. Las container queries permiten que un componente responda al ancho de su contenedor, no solo al viewport completo. Estas definiciones parecen simples, pero evitan instrucciones vagas y hacen que el diff de Claude Code sea mas facil de revisar.
Como fuentes oficiales usa MDN: Responsive design, @container, clamp() y responsive images. Para verificar, usa Playwright Screenshots y Visual comparisons. La documentacion actual de Claude Code overview y How Claude Code works lo presenta como una herramienta que lee el codigo, edita archivos, ejecuta comandos y verifica resultados. Para responsive design, esa es la mentalidad correcta.
Para completar el contexto, lee tambien design systems con Claude Code, accesibilidad con Claude Code y testing con Playwright.
Mapa de implementacion
El trabajo responsivo falla cuando el CSS se agrega al final como parche. Pide a Claude Code que inspeccione la pagina existente, detecte en que anchos se rompe cada componente, actualice CSS e imagenes juntos y agregue una prueba visual.
flowchart LR
A["Leer pagina existente"] --> B["CSS base mobile-first"]
B --> C["Fluid grid y clamp()"]
C --> D["Componentes con container query"]
D --> E["Imagenes y tablas responsivas"]
E --> F["Checks con Playwright"]
Este prompt funciona bien como punto de partida:
Convierte la pagina existente /responsive-demo en una pagina responsiva.
Requisitos:
- Usar CSS mobile-first.
- Evitar scroll horizontal en 320px, 390px, 768px, 1024px y 1440px.
- Evitar solapamientos entre navegacion, tarjetas, tabla de precios, CTA y footer.
- Las imagenes de contenido deben tener width/height, srcset, sizes, loading y alt util.
- Priorizar CSS Grid, clamp() y @container antes de agregar JavaScript para detectar ancho.
- Despues del cambio, ejecutar capturas y una assertion de overflow con Playwright.
No hacer:
- No cambiar URLs existentes, enlaces de conversion ni jerarquia accesible de headings.
- No agregar min-width fijos grandes que provoquen scroll horizontal en toda la pagina.
El beneficio es que la revision queda objetiva. Si la solucion solo se ve bien en desktop, no cumple.
HTML copiable
El ejemplo incluye navegacion, hero, imagen, tarjetas, panel lateral y tabla comparativa. Cambia las rutas de imagen por las de tu proyecto y usalo con el CSS de la siguiente seccion.
<!doctype html>
<html lang="es">
<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="Navegacion principal">
<a href="/es/blog/">Articulos</a>
<a href="/en/products/">Productos</a>
<a href="/en/training/">Consultoria</a>
</nav>
</header>
<main class="page-shell">
<section class="hero">
<div>
<p class="eyebrow">Responsive Design</p>
<h1>Disena primero la pantalla pequena y deja crecer el layout</h1>
<p class="lead">
Implementa CSS mobile-first, grids fluidos, imagenes responsivas y checks de Playwright en un mismo flujo.
</p>
<a class="primary-cta" href="/en/products/">Ver plantillas 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="Telefono y portatil mostrando la misma pagina responsiva"
width="1280"
height="900"
loading="eager"
decoding="async"
/>
</picture>
</section>
<div class="layout-grid">
<aside class="side-panel" aria-label="Checklist de viewport">
<h2>Anchos a verificar</h2>
<ul>
<li>320px: telefono pequeno</li>
<li>390px: telefono comun</li>
<li>768px: tablet</li>
<li>1024px o mas: desktop</li>
</ul>
</aside>
<section class="cards" aria-label="Tarjetas de mejora">
<article class="card featured">
<img src="/images/card-layout.jpg" alt="" width="720" height="480" loading="lazy" />
<div class="card-body">
<h2>Las tarjetas responden al contenedor</h2>
<p>Un componente reusable debe ajustar su densidad segun el espacio donde vive.</p>
</div>
</article>
<article class="card">
<div class="card-body">
<h2>La navegacion puede saltar de linea</h2>
<p>No aprietes todos los enlaces de desktop en una sola fila movil.</p>
</div>
</article>
<article class="card">
<div class="card-body">
<h2>La tabla mantiene significado</h2>
<p>En pantallas estrechas, las filas se vuelven tarjetas y `data-label` conserva el nombre de columna.</p>
</div>
</article>
</section>
</div>
<section class="comparison">
<h2>Comparacion de planes</h2>
<table class="responsive-table">
<thead>
<tr>
<th scope="col">Elemento</th>
<th scope="col">Individual</th>
<th scope="col">Equipo</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Elemento">Objetivo</td>
<td data-label="Individual">Aprendizaje y mejoras pequenas</td>
<td data-label="Equipo">Estandares de review consistentes</td>
</tr>
<tr>
<td data-label="Elemento">Prueba</td>
<td data-label="Individual">Playwright local</td>
<td data-label="Equipo">Capturas en CI</td>
</tr>
</tbody>
</table>
</section>
</main>
</body>
</html>
CSS mobile-first, grid fluido y clamp
El CSS empieza por la vista estrecha. Las pantallas grandes agregan columnas despues. Asi se evita el patron desktop-first donde cada regla movil tiene que deshacer una decision previa.
* {
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);
}
}
La parte importante es evitar anchos fijos grandes. width: min(100% - 2rem, 72rem) deja margen en pantallas pequenas y limita la linea de lectura en pantallas grandes. minmax(min(100%, 18rem), 1fr) impide que el ancho minimo de una tarjeta rompa el contenedor.
Patrones para imagenes, navegacion, tarjetas y tablas
Entrega a Claude Code reglas por componente.
| Componente | Fallo comun | Correccion a pedir |
|---|---|---|
| Navegacion | Enlaces de desktop comprimidos en movil | Permitir salto de linea, mantener area tactil y aria-label |
| Tarjetas | width: 320px o min-width grande causa overflow | Usar auto-fit, minmax() y container queries |
| Imagenes | El telefono recibe el mismo JPEG grande | Agregar srcset, sizes, width, height, loading y alt |
| Tablas | Las columnas se vuelven ilegibles | Elegir scroll del contenedor o tarjetas por fila con data-label |
| CTA | El enlace de ingresos queda enterrado | Revisar primer scroll movil y cierre del articulo |
No todo menu pequeno necesita hamburguesa. Si hay tres enlaces, el wrap puede ser mas claro. Tampoco toda tabla debe convertirse en tarjeta: una matriz de precios puede necesitar comparacion horizontal, mientras que una lista de tickets se lee mejor por filas.
Casos de uso que debes probar
El primer caso es un dashboard SaaS. Combina sidebar, filtros, tarjetas KPI, graficos y tabla. En movil conviene mostrar primero los KPI principales, plegar filtros secundarios y transformar filas detalladas en tarjetas.
El segundo caso es un blog o sitio editorial. Ancho de texto, indice, anuncios, posts relacionados y CTA de PDF gratuito compiten por espacio. Aqui hay que revisar lineas legibles, imagenes ligeras, bloques de codigo sin overflow y CTA visible.
El tercer caso es una landing de ecommerce o cursos. Tarjetas de producto, comparacion de precio, boton de compra y FAQ impactan ingresos. Si el precio o el boton quedan demasiado abajo en movil, la conversion sufre.
El cuarto caso es una pantalla interna de administracion. Los usuarios diarios valoran busqueda, filtros, teclado y tablas claras mas que una composicion vistosa. La mejora responsiva debe proteger el orden de trabajo.
Verificacion con Playwright
No cierres la tarea solo porque se ve bien en tu navegador. Playwright puede probar anchos representativos, verificar elementos visibles, detectar overflow horizontal y guardar capturas para revision.
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: "Navegacion principal" })).toBeVisible();
await expect(page.getByRole("link", { name: "Ver plantillas 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 primera ejecucion crea las capturas base. Actualizalas con npx playwright test --update-snapshots solo si el cambio visual fue intencional. Para reducir ruido, genera y compara capturas en el mismo entorno de CI.
Errores habituales
El error principal es CSS desktop-first con parches moviles encima. A corto plazo parece rapido, pero luego nadie entiende la cascada. Pide a Claude Code mover el diseno estrecho a las reglas base y agregar columnas solo para pantallas anchas.
Otro error es olvidar <meta name="viewport">. Sin esa etiqueta, el navegador movil puede renderizar con ancho virtual de desktop y tus pruebas no representan el dispositivo real.
Tambien aparecen anchos fijos dentro de tarjetas, tablas, imagenes o embeds. min-width: 960px puede pasar desapercibido en un monitor grande y romper todos los telefonos. Si una tabla debe desplazarse, pon overflow-x: auto en su wrapper, no en toda la pagina.
El cuarto error es escribir srcset sin sizes. El navegador necesita candidatos y una pista del ancho renderizado. Revisa srcset, sizes, width, height y alt como un conjunto.
El quinto error es confiar solo en screenshots. Sirven para revisar visuales, pero anuncios, fechas, animaciones y widgets externos generan ruido. Combinalos con assertions de DOM para overflow, CTA visible y landmarks de navegacion.
Incluye la ruta de ingresos
El responsive design tambien debe proteger el objetivo del negocio. En ClaudeCodeLab, el lector movil debe encontrar el PDF gratuito, los productos Gumroad y la consultoria. Para flujos reutilizables revisa Claude Code products. Para trabajar pantallas reales con reglas de review y Playwright, revisa Claude Code training.
Cuando escribas el brief para Claude Code, incluye la ruta de conversion. Una pagina limpia que esconde el boton de compra o el enlace de consulta no esta terminada.
Resumen
El flujo practico es: definir el contrato mobile-first, construir grids fluidos, usar clamp() para texto y espacio, aplicar container queries en componentes reutilizables, tratar imagenes de forma deliberada, adaptar navegacion y tablas segun la tarea del lector, y verificar con Playwright.
Probe el patron de este articulo en 320px, 390px, 768px y 1440px. La navegacion hizo wrap sin overflow, las tarjetas pasaron a una columna en movil, la tabla se leyo como tarjetas por fila y la assertion de overflow de Playwright paso. La conclusion practica de Masa: Claude Code aporta mas cuando implementa y luego revisa anchos fijos, hints de imagen, posicion de CTA, comportamiento de tablas y diferencias de capturas.
PDF gratis: cheatsheet de Claude Code
Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.
Cuidamos tus datos y no enviamos spam.
Sobre el autor
Masa
Ingeniero enfocado en workflows prácticos con Claude Code.
Artículos relacionados
Escalera de permisos de Claude Code para ampliar acceso sin perder control
Pasa de read-only a ediciones limitadas, comandos de prueba y checks de deploy con menos riesgo.
Claude Code Small PR Proof Pack: cambios pequeños que sí se pueden revisar
Un paquete de prueba para PRs de Claude Code: diff, checks, URL pública, CTA y rollback.
Gate de revisión antes del commit con Claude Code
Cómo revisar con Claude Code antes del commit: diff, build, URL pública, Gumroad, consultoría, tests y archivos ajenos.