Claude-skill-registry layout-grid
Design-focused grid layout system with fluid scaling, responsive columns, and resolution-independent patterns. Use when creating page layouts, card grids, or multi-column designs.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/layout-grid" ~/.claude/skills/majiayu000-claude-skill-registry-layout-grid && rm -rf "$T"
skills/data/layout-grid/SKILL.mdLayout Grid Skill
This skill covers design grid systems for page layout—fluid, resolution-independent grids that scale proportionally across all viewport sizes without fixed breakpoints.
Philosophy
Layout grids should:
- Scale fluidly - No fixed pixel values; use relative units throughout
- Work at any resolution - Single grid system, not breakpoint-specific grids
- Maintain proportions - Gutters and margins scale with content
- Support composition - Enable both rigid alignment and flexible content areas
Fluid Grid Token System
Define grid properties as fluid custom properties that scale between viewport bounds.
Core Grid Tokens
@layer tokens { :root { /* ==================== GRID FOUNDATION ==================== */ /* Viewport bounds for fluid calculations */ --grid-min-width: 20rem; /* 320px - mobile */ --grid-max-width: 90rem; /* 1440px - large desktop */ /* Content max-width (readable area) */ --content-max-width: 75rem; /* 1200px */ /* ==================== FLUID GUTTER ==================== */ /* Gutter scales from 1rem to 2rem based on viewport */ --grid-gutter: clamp(1rem, 0.5rem + 2vw, 2rem); /* ==================== FLUID MARGIN ==================== */ /* Page margin scales from 1rem to 4rem */ --grid-margin: clamp(1rem, -0.5rem + 6vw, 4rem); /* ==================== COLUMN SYSTEM ==================== */ --grid-columns: 12; /* Single column width (fluid) */ --grid-column-width: calc( (100% - (var(--grid-columns) - 1) * var(--grid-gutter)) / var(--grid-columns) ); } }
The Fluid Scaling Formula
Fluid values use
clamp() with a calculated preferred value:
clamp(min, preferred, max) preferred = min + (max - min) × viewport-factor viewport-factor = (100vw - min-viewport) / (max-viewport - min-viewport)
Simplified pattern:
/* Scale from 1rem (320px) to 2rem (1440px) */ --value: clamp(1rem, calc(0.5rem + 1.5vw), 2rem);
Page Layout Container
The Fluid Container
@layer layout { /* Main content container */ body > * { --_container-width: min( var(--content-max-width), 100% - var(--grid-margin) * 2 ); width: var(--_container-width); margin-inline: auto; } /* Full-bleed sections */ [data-layout="full"] { width: 100%; padding-inline: var(--grid-margin); } /* Wide sections (larger than content, not full) */ [data-layout="wide"] { --_container-width: min( var(--grid-max-width), 100% - var(--grid-margin) * 2 ); } }
Named Grid Areas for Page Layout
@layer layout { body { display: grid; grid-template-columns: [full-start] var(--grid-margin) [wide-start] minmax(0, 1fr) [content-start] min(var(--content-max-width), 100%) [content-end] minmax(0, 1fr) [wide-end] var(--grid-margin) [full-end]; grid-template-rows: auto 1fr auto; } /* Content aligns to content area */ body > * { grid-column: content; } /* Full-bleed elements span full width */ body > [data-layout="full"] { grid-column: full; } /* Wide elements extend past content */ body > [data-layout="wide"] { grid-column: wide; } }
Responsive Card Grids
Auto-Fit Pattern (Recommended)
Cards flow into available columns automatically:
@layer components { card-grid { display: grid; grid-template-columns: repeat( auto-fit, minmax(min(100%, 18rem), 1fr) ); gap: var(--grid-gutter); } }
How it works:
creates as many columns as fitauto-fit
ensures cards are at least 18rem but stretch to fill spaceminmax(min(100%, 18rem), 1fr)
prevents overflow on narrow viewportsmin(100%, 18rem)
Auto-Fill vs Auto-Fit
| Property | Behavior | Use When |
|---|---|---|
| Collapses empty tracks | Cards should stretch to fill row |
| Keeps empty tracks | Maintain consistent column widths |
/* auto-fit: cards stretch */ grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); /* auto-fill: consistent widths, may leave gaps */ grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
Constrained Column Count
Limit maximum columns while staying fluid:
card-grid { --_min-card-width: 18rem; --_max-columns: 4; display: grid; grid-template-columns: repeat( auto-fit, minmax( max( var(--_min-card-width), calc((100% - var(--grid-gutter) * (var(--_max-columns) - 1)) / var(--_max-columns)) ), 1fr ) ); gap: var(--grid-gutter); }
Explicit Column Grids
12-Column Grid
@layer layout { [data-grid="12"] { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--grid-gutter); } /* Span utilities */ [data-span="1"] { grid-column: span 1; } [data-span="2"] { grid-column: span 2; } [data-span="3"] { grid-column: span 3; } [data-span="4"] { grid-column: span 4; } [data-span="5"] { grid-column: span 5; } [data-span="6"] { grid-column: span 6; } [data-span="7"] { grid-column: span 7; } [data-span="8"] { grid-column: span 8; } [data-span="9"] { grid-column: span 9; } [data-span="10"] { grid-column: span 10; } [data-span="11"] { grid-column: span 11; } [data-span="12"] { grid-column: span 12; } }
Responsive Column Spans
Use container queries for component-level responsiveness:
@layer components { feature-grid { container-type: inline-size; display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--grid-gutter); } feature-grid > * { grid-column: span 12; /* Full width by default */ } @container (min-width: 30rem) { feature-grid > * { grid-column: span 6; /* Half width */ } } @container (min-width: 50rem) { feature-grid > * { grid-column: span 4; /* Third width */ } feature-grid > :first-child { grid-column: span 8; /* Featured item wider */ } } }
Subgrid for Alignment
Subgrid enables nested elements to align with parent grid tracks.
Card Grid with Aligned Content
@layer components { /* Parent defines the column structure */ product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); /* Define row tracks for card internals */ grid-auto-rows: auto 1fr auto; /* image, content, actions */ gap: var(--grid-gutter); } /* Cards span 3 rows and inherit row tracks */ product-card { display: grid; grid-row: span 3; grid-template-rows: subgrid; gap: var(--spacing-md); } product-card img { grid-row: 1; } product-card .content { grid-row: 2; } product-card .actions { grid-row: 3; } }
Form Alignment with Subgrid
@layer components { form { display: grid; grid-template-columns: max-content 1fr; gap: var(--spacing-md); } form-field { display: grid; grid-column: span 2; grid-template-columns: subgrid; } form-field label { grid-column: 1; } form-field input, form-field select { grid-column: 2; } }
Asymmetric Layouts
Content + Sidebar
@layer layout { [data-layout="sidebar"] { display: grid; grid-template-columns: 1fr min(20rem, 30%); gap: var(--grid-gutter); } /* Responsive: stack on narrow */ @container (max-width: 50rem) { [data-layout="sidebar"] { grid-template-columns: 1fr; } } }
Golden Ratio Split
@layer layout { [data-layout="golden"] { display: grid; /* 1.618:1 ratio */ grid-template-columns: 1.618fr 1fr; gap: var(--grid-gutter); } }
Feature + Gallery
@layer layout { [data-layout="feature-gallery"] { display: grid; grid-template-columns: 2fr 1fr 1fr; grid-template-rows: 1fr 1fr; gap: var(--grid-gutter); } [data-layout="feature-gallery"] > :first-child { grid-row: span 2; } }
Fluid Gap Scaling
Gap Token Scale
:root { /* Gaps scale with viewport */ --gap-xs: clamp(0.25rem, 0.125rem + 0.5vw, 0.5rem); --gap-sm: clamp(0.5rem, 0.25rem + 1vw, 1rem); --gap-md: clamp(1rem, 0.5rem + 2vw, 2rem); --gap-lg: clamp(1.5rem, 0.75rem + 3vw, 3rem); --gap-xl: clamp(2rem, 1rem + 4vw, 4rem); }
Using Gap Tokens
card-grid { gap: var(--gap-md); } section-grid { gap: var(--gap-lg); } icon-grid { gap: var(--gap-sm); }
Resolution-Independent Patterns
Using Proportional Units
| Unit | Use For | Example |
|---|---|---|
| Flexible column widths | |
| Proportional within container | |
| Viewport-relative | |
| Container-relative | |
| Root-relative sizing | |
| Character-based width | |
Never Use Fixed Pixels For:
- Column widths
- Gutters and gaps
- Margins and padding
- Container max-widths (use
instead)rem
Pixel-Safe Uses:
- Border widths (
,1px
)2px - Box shadows
- Fine visual details
Common Layout Patterns
Holy Grail Layout
body { display: grid; grid-template: "header header header" auto "nav main aside" 1fr "footer footer footer" auto / minmax(10rem, 15rem) 1fr minmax(10rem, 20rem); min-height: 100vh; gap: var(--grid-gutter); } header { grid-area: header; } nav { grid-area: nav; } main { grid-area: main; } aside { grid-area: aside; } footer { grid-area: footer; } /* Stack on mobile */ @media (max-width: 60rem) { body { grid-template: "header" auto "nav" auto "main" 1fr "aside" auto "footer" auto / 1fr; } }
Magazine Layout
article-layout { display: grid; grid-template-columns: [full-start] 1fr [main-start] minmax(0, 65ch) [main-end] 1fr [full-end]; gap: var(--grid-gutter); } article-layout > * { grid-column: main; } article-layout > figure, article-layout > blockquote { grid-column: full; }
Masonry-Style (CSS Grid Approximation)
masonry-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); grid-auto-rows: 1rem; gap: var(--grid-gutter); } masonry-grid > * { /* Items span variable rows based on content */ grid-row: span var(--rows, 10); }
Note: True masonry requires JavaScript to calculate
--rows or wait for CSS masonry property support.
Integration with Container Queries
Component-Level Grid Responsiveness
@layer components { dashboard-widget { container-type: inline-size; display: grid; gap: var(--spacing-md); } /* Single column by default */ dashboard-widget { grid-template-columns: 1fr; } /* Two columns when widget is wide enough */ @container (min-width: 25rem) { dashboard-widget { grid-template-columns: 1fr 1fr; } } /* Three columns with sidebar */ @container (min-width: 45rem) { dashboard-widget { grid-template-columns: 2fr 1fr 1fr; } } }
Debug Grid Overlay
Visualize grid during development:
/* Add to :root for development */ :root { --debug-grid: 0; } [data-grid], [data-layout] { position: relative; } [data-grid]::before, [data-layout]::before { content: ""; position: absolute; inset: 0; pointer-events: none; background: repeating-linear-gradient( 90deg, oklch(60% 0.15 250 / 0.1) 0, oklch(60% 0.15 250 / 0.1) var(--grid-column-width), transparent var(--grid-column-width), transparent calc(var(--grid-column-width) + var(--grid-gutter)) ); opacity: var(--debug-grid); z-index: 9999; }
Toggle with:
document.documentElement.style.setProperty('--debug-grid', '1')
Checklist
When implementing grid layouts:
Tokens
- Grid gutter uses
for fluid scalingclamp() - Page margin scales with viewport
- No fixed pixel values for layout dimensions
- Content max-width defined in
rem
Grid Structure
- Use
/auto-fit
for card gridsauto-fill -
includesminmax()
to prevent overflowmin(100%, value) - Named grid areas for page layout
-
units for flexible column widthsfr
Responsiveness
- Container queries for component-level changes
- Media queries only for page-level layout shifts
- Single grid system works across all viewports
- Test at arbitrary widths, not just standard breakpoints
Alignment
- Subgrid used for nested element alignment
- Consistent gap tokens throughout
- Items align to baseline grid where appropriate
Related Skills
- css-author - @layer organization, container queries, @scope
- typography - Baseline grid, vertical rhythm
- responsive-images - Images in grid contexts
- progressive-enhancement - CSS-only responsive patterns