Responsive Layouts skill for Claude Code
Layouts that fit the content, not a device list. Claude builds layouts that reflow on their own using minmax, auto-fill and flex-wrap recipes, saves media queries for genuine page-level changes, and makes reusable components respond to their container rather than the viewport. It also handles the mobile traps that ship broken: 100vh overflow, notches, iOS input zoom and flex children that refuse to shrink.
- name
responsive-layouts - size166 lines · ≈1,900 tokens
- files1
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Builds layouts that adapt by content rather than device lists — mobile-first CSS Grid and Flexbox recipes, intrinsic patterns (stack, cluster, sidebar, switcher), container queries for reusable components, content-driven breakpoints, fluid spacing, dvh and safe-area handling, and subgrid alignment. Use when a page breaks at some width, building a page shell or card grid, making a component work in sidebars and main columns, or replacing a pile of media queries. Try asking
- This page scrolls horizontally on mobile. Find the cause and fix the layout
- Make this card component work in both the sidebar and the main column
- Rebuild our page shell so text stays readable but images can go full width
Use it when
- A page breaks or overflows at certain widths
- Building a page shell, card grid, or sidebar layout
- A component must adapt to different containers
- Too many media queries are fighting each other
Skip it when
- You need cascade layers, naming and specificity strategy, use css-architecture instead
- You are implementing a specific Figma frame pixel by pixel, use figma-to-code instead
How to check the result
A continuous 320 to 1920 pixel sweep shows no overlap or horizontal scroll, and 400% zoom at 1280 pixels reflows into a single readable column.
The common mistake it prevents
Forgetting min-width: 0 on flex and grid children, so one long URL or code line pushes the whole page into horizontal scroll.
A layout is done when it works at every width from 320px to 1920px+ (not just at three device sizes), components adapt to the space they are given rather than the viewport, nothing scrolls horizontally, and the code has few breakpoints because intrinsic sizing does most of the work.
Ground rules
- Mobile-first: base styles are the narrow layout;
min-widthqueries add complexity. - Breakpoints come from content. Drag the viewport until the design breaks; that width is the breakpoint. Device widths are a test list, not a design input.
- Prefer intrinsic sizing (
minmax,auto-fit,flex-wrap,min(),clamp()) over queries. A layout with 15 media queries is fighting the browser. - Component-level adaptation uses container queries; page-level uses media queries.
- Use logical properties (
margin-inline,padding-block,inset-inline-start) so RTL works for free.
Avoid the generic look
| Default reflex | Better |
|---|---|
| Everything centered in a 1200px column | Mix measures: text at 65ch, media breaking wider, full-bleed bands for rhythm |
| Uniform 3-column card grid for every list | Vary emphasis: a 2:1 feature split, a 7/5 asymmetric grid, a lead item spanning two columns |
| Same 64px vertical padding on every section | Section spacing on a scale (64 / 96 / 128) chosen by the section’s importance |
| Hero = left text, right image, at every breakpoint | Decide the mobile order deliberately (often visual after headline, before body) |
| Fixed px gutters | Fluid gutters: clamp(1rem, 4vw, 3rem) |
Workflow
- [ ] 1. Sketch the narrow layout and the wide layout; note what changes between
- [ ] 2. Build the page shell (gutters, max widths, full-bleed escape)
- [ ] 3. Lay out sections with intrinsic grids/flex first
- [ ] 4. Make reusable components container-aware
- [ ] 5. Add the few media queries content still needs
- [ ] 6. Test the sweep: 320 → 1920, zoom 200%, landscape phone
2. Page shell with full-bleed escape
.page {
--gutter: clamp(1rem, 4vw, 3rem);
--content: 68ch;
--wide: 75rem;
display: grid;
grid-template-columns:
[full-start] minmax(var(--gutter), 1fr)
[wide-start] minmax(0, calc((var(--wide) - var(--content)) / 2))
[content-start] min(var(--content), 100% - 2 * var(--gutter)) [content-end]
minmax(0, calc((var(--wide) - var(--content)) / 2)) [wide-end]
minmax(var(--gutter), 1fr) [full-end];
}
.page > * { grid-column: content; }
.page > .wide { grid-column: wide; }
.page > .full { grid-column: full; }
3. Intrinsic recipes (no media queries)
| Need | Recipe |
|---|---|
| Card grid that reflows | grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr)); |
| Vertical rhythm | .stack > * + * { margin-block-start: var(--space, 1rem); } or display:flex; flex-direction:column; gap |
| Inline group that wraps (tags, buttons) | display:flex; flex-wrap:wrap; gap:.5rem; align-items:center; |
| Sidebar + main that stacks when narrow | .with-sidebar{display:flex;flex-wrap:wrap;gap:2rem} .sidebar{flex-basis:18rem;flex-grow:1} .main{flex-basis:0;flex-grow:999;min-inline-size:60%} |
| Row that becomes column below a width | Switcher: .switcher{display:flex;flex-wrap:wrap;gap:1rem} .switcher>*{flex-grow:1;flex-basis:calc((40rem - 100%) * 999)} |
| Fluid spacing | padding-block: clamp(3rem, 8vw, 8rem); |
auto-fill keeps empty tracks (items stay card-sized); auto-fit collapses them (items
stretch to fill). Use auto-fill when a lone item stretching full width would look odd.
min(100%, 16rem) in minmax prevents overflow on screens narrower than the minimum.
4. Container queries for components
.card-list { container-type: inline-size; container-name: cards; }
.card { display: grid; gap: 0.75rem; }
@container cards (min-width: 36rem) {
.card { grid-template-columns: 12rem 1fr; align-items: start; }
}
.card h3 { font-size: clamp(1.1rem, 3.5cqi, 1.5rem); } /* container-relative units */
container-type: inline-sizeon the parent, never on the element you query from inside (an element cannot query itself).- Inline-size containment means the container cannot size to its content’s width; it must get width from its parent (block-level or a grid track).
- Supported in all evergreen browsers since 2023; style queries are less supported, so do not rely on them for core layout.
5. Media queries that remain
Use them for page-level changes: navigation pattern, number of page columns, hero
arrangement. Write them in rem/em so they respond to user font size, and use range
syntax:
@media (width >= 48rem) { .site-nav { display: flex; } .nav-toggle { display: none; } }
Align subcomponents across cards with subgrid:
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr)); gap: 1.5rem; }
.card { display: grid; grid-row: span 3; grid-template-rows: subgrid; } /* title, body, footer align across cards */
Mobile specifics
- Viewport units: use
100dvhfor full-height panels (adapts to browser chrome),100svhwhen you need the smallest stable height (no jump on scroll). Plain100vhoverflows behind mobile toolbars. - Notches: add
viewport-fit=coverto the viewport meta only if you then pad withenv(safe-area-inset-*), e.g.padding-bottom: max(1rem, env(safe-area-inset-bottom)). - Touch targets ≥ 24×24 CSS px (WCAG 2.2 AA), aim for 44×44 on primary actions, with ≥ 8px between adjacent targets.
- Never disable zoom (
user-scalable=no,maximum-scale=1). - Inputs with font-size below 16px trigger iOS zoom on focus.
- Hover-only affordances need a tap path: gate hover effects with
@media (hover: hover) and (pointer: fine).
Gotchas
- Flex/grid children default to
min-width: autoand refuse to shrink below their content: long URLs or code blocks cause horizontal scroll. Addmin-width: 0to the flex/grid child, andoverflow-wrap: anywhereto user content. width: 100vwincludes the scrollbar on desktop and causes horizontal scroll; use the full-bleed grid column orwidth: 100%.- Images need
max-width: 100%; height: auto;pluswidth/heightattributes to reserve space (CLS). - Tables: wrap in a scroll container with a visible affordance, or reflow rows into cards below a container width.
- Reordering with
orderorgrid-areachanges visual but not tab/reading order; keep DOM order meaningful (WCAG 1.3.2, 2.4.3). - Fixed headers eat small-landscape screens; keep them ≤ 56px or hide on scroll down.
Verification
- Sweep: in DevTools responsive mode, drag width continuously from 320 to 1920 and watch for overlaps, orphaned items, and line lengths over 80ch.
- Check horizontal overflow programmatically in the console:
[...document.querySelectorAll('*')].filter(e => e.scrollWidth > document.documentElement.clientWidth). - Test at 1280px with 200% and 400% zoom (400% ≈ 320px reflow, WCAG 1.4.10).
- Test a real phone in portrait and landscape, with the on-screen keyboard open on forms.
- Playwright screenshots at 375, 768, 1024, 1440 for regressions (see
visual-regression).
Output contract
## Layout notes
Shell: content 68ch / wide 75rem / full-bleed; gutter clamp(1rem, 4vw, 3rem)
Breakpoints (content-derived): 48rem nav switch, 64rem 2-col article
Container-aware components: Card (36rem), ProductTile (28rem)
Tested: 320–1920 sweep, 200%/400% zoom, iOS Safari portrait/landscape About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.