|$ curl https://forge-ai.dev/api/markdown?path=docs/css/responsive
$cat docs/responsive-design.md
updated Recently·26 min read·published

Responsive Design

CSSResponsiveIntermediateIntermediate
Introduction

Responsive Web Design (RWD) is an approach that ensures web pages render well across all devices — from small phones to large desktop monitors. The core principles, defined by Ethan Marcotte in 2010, are three pillars: fluid grids, flexible images, and media queries.

Modern responsive design has evolved to include container queries, viewport units, clamp(), responsive typography, and responsive images with srcset. The goal is one codebase that adapts to any context rather than building separate mobile and desktop sites.

responsive-foundation.css
CSS
1/* Fluid grid foundation */
2.container {
3 width: 100%;
4 max-width: 1200px;
5 margin-inline: auto;
6 padding-inline: 1rem;
7}
8
9/* Flexible images */
10img, video, iframe {
11 max-width: 100%;
12 height: auto;
13}
14
15/* Media query for larger screens */
16@media (min-width: 768px) {
17 .container {
18 padding-inline: 2rem;
19 }
20}
preview
Viewport Meta Tag

The viewport meta tag controls how a webpage is displayed on mobile devices. Without it, mobile browsers render pages at a desktop width (typically 980px) and then zoom out — resulting in tiny, unreadable text.

viewport.html
HTML
1<!-- Standard viewport configuration (recommended) -->
2<meta name="viewport" content="width=device-width, initial-scale=1.0">
3
4<!-- With user-scalable=no (not recommended for accessibility) -->
5<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
6
7<!-- With maximum-scale restriction -->
8<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
9
10<!-- Minimum viable viewport tag -->
AttributeValuesDescription
widthdevice-width | <number>Sets the viewport width. device-width matches the device screen width.
initial-scale0.1 — 10Initial zoom level. 1.0 = no zoom.
minimum-scale0.1 — 10Minimum allowed zoom level.
maximum-scale0.1 — 10Maximum allowed zoom level.
user-scalableyes | noAllow pinch-to-zoom. Setting no is an accessibility violation.

warning

Never set user-scalable=no or maximum-scale=1.0. Blocking zoom is an accessibility violation — users with low vision depend on pinch-to-zoom. If you must restrict scaling, use maximum-scale=5 to allow some zoom.
Media Queries

Media queries apply CSS conditionally based on device characteristics, viewport size, or user preferences. They are the backbone of responsive design, enabling different layouts, typography, and interactions across device contexts.

Media Query Syntax

media-queries.css
CSS
1/* @media syntax: @media <media-type> (<feature>: <value>) { ... } */
2
3/* Width-based queries */
4@media (min-width: 768px) { /* tablet and up */ }
5@media (max-width: 767px) { /* mobile only */ }
6@media (width: 1024px) { /* exact width */ }
7
8/* Range syntax (modern browsers) */
9@media (768px <= width <= 1024px) { /* between 768px and 1024px */ }
10@media (width >= 768px) { /* same as min-width: 768px */ }
11@media (width <= 1024px) { /* same as max-width: 1024px */ }
12
13/* Orientation */
14@media (orientation: portrait) { /* height > width */ }
15@media (orientation: landscape) { /* width > height */ }
16
17/* Resolution (for Retina / high-DPI) */
18@media (min-resolution: 2dppx) { /* 2x screens */ }
19
20/* Hover capability */
21@media (hover: hover) { /* device has a hover-capable pointer */ }
22@media (hover: none) { /* touch device — no hover */ }
23
24/* Pointer precision */
25@media (pointer: fine) { /* mouse, stylus */ }
26@media (pointer: coarse) { /* finger */ }
27
28/* User preference queries */
29@media (prefers-color-scheme: dark) { /* dark mode */ }
30@media (prefers-color-scheme: light) { /* light mode */ }
31@media (prefers-reduced-motion: reduce) { /* reduced motion */ }
32@media (prefers-contrast: more) { /* high contrast */ }
33@media (prefers-reduced-data: reduce) { /* data saver */ }
34
35/* Combining conditions */
36@media (min-width: 768px) and (hover: hover) {
37 /* tablet/desktop with mouse */
38}
39
40@media not (pointer: fine) {
41 /* touch or coarse pointer devices */
42}
43
44/* Comma-separated = OR */
45@media (max-width: 480px), (orientation: landscape) {
46 /* either condition */
47}
preview
Fluid Layouts

Fluid layouts use relative units instead of fixed pixel values to adapt to any viewport size. The combination of percentage-based widths, viewport units, max-width, and CSS math functions creates layouts that stretch and compress smoothly.

fluid-layouts.css
CSS
1/* Fluid container */
2.container {
3 width: min(100% - 2rem, 1200px);
4 margin-inline: auto;
5}
6
7/* Fluid columns */
8.sidebar {
9 width: 30%; /* always 30% of parent */
10 max-width: 300px; /* but never wider than 300px */
11 min-width: 200px; /* never narrower than 200px */
12}
13
14.main {
15 width: 70%;
16 min-width: 0; /* allow shrinking below content size */
17}
18
19/* Using calc() for fluid sizing */
20.half-gap {
21 width: calc(50% - 12px); /* half minus a gap */
22}
23
24/* Using clamp() for fluid sizing */
25.responsive-box {
26 width: clamp(280px, 50%, 600px);
27 /* minimum 280px, preferred 50%, maximum 600px */
28}
29
30/* Full-bleed sections */
31.full-bleed {
32 width: 100vw;
33 margin-inline: calc(-50vw + 50%);
34}
35
36/* Aspect ratio boxes */
37.square { aspect-ratio: 1 / 1; }
38.video { aspect-ratio: 16 / 9; }
39.card { aspect-ratio: 3 / 4; }
preview
Flexbox & Grid for Responsive Layouts

Modern CSS layout methods (Flexbox and Grid) have built-in responsive capabilities that reduce or eliminate the need for media queries in common patterns.

Auto-fill vs Auto-fit

KeywordBehaviorResult
auto-fillCreates as many tracks as fit, even if emptyTrack space is preserved (may leave empty gaps)
auto-fitCreates tracks and collapses empty onesItems stretch to fill the container
responsive-flexbox-grid.css
CSS
1/* Responsive Grid — no media queries needed */
2.card-grid {
3 display: grid;
4 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
5 gap: 1.5rem;
6 /* Automatically adjusts columns based on available width */
7}
8
9/* Flexbox wrapping row */
10.flex-row {
11 display: flex;
12 flex-wrap: wrap;
13 gap: 1rem;
14}
15
16.flex-row > * {
17 flex: 1 1 250px; /* grow, shrink, basis */
18 /* Minimum width of 250px, wraps when narrower */
19}
20
21/* Flex shorthand for responsive items */
22.sidebar { flex: 0 1 280px; } /* fixed-ish sidebar */
23.content { flex: 1 1 0%; } /* fills remaining space */
24.nav-item { flex: 0 1 auto; } /* sized by content */
25
26/* minmax() for responsive grids */
27.grid {
28 grid-template-columns:
29 repeat(auto-fit, minmax(min(280px, 100%), 1fr));
30 /* Safer — never overflows on very small screens */
31}
preview
Responsive Images

Responsive images deliver the right image size for the user's device and viewport, saving bandwidth and improving load times. The srcset and sizes attributes, along with the <picture> element, give you fine control over image delivery.

srcset & sizes

responsive-image.html
HTML
1<!-- srcset: list of image files with their widths -->
2<img
3 src="photo-800.jpg"
4 srcset="
5 photo-400.jpg 400w,
6 photo-800.jpg 800w,
7 photo-1200.jpg 1200w"
8 sizes="
9 (max-width: 600px) 100vw,
10 (max-width: 1200px) 50vw,
11 800px"
12 alt="Responsive image example"
13>
14
15<!-- Density descriptors (2x, 3x for Retina) -->
16<img
17 src="photo.jpg"
18 srcset="
19 photo.jpg 1x,
20 photo-2x.jpg 2x,
21 photo-3x.jpg 3x"
22 alt="Retina responsive image"
23>

The picture element

picture-element.html
HTML
1<!-- <picture> for art direction — different crops per breakpoint -->
2<picture>
3 <source media="(min-width: 1200px)" srcset="hero-desktop.jpg">
4 <source media="(min-width: 768px)" srcset="hero-tablet.jpg">
5 <source media="(min-width: 480px)" srcset="hero-phone.jpg">
6 <img src="hero-fallback.jpg" alt="Hero image">
7</picture>
8
9<!-- WebP with fallback -->
10<picture>
11 <source type="image/webp" srcset="image.webp">
12 <source type="image/avif" srcset="image.avif">
13 <img src="image.jpg" alt="Image with modern format fallback">
14</picture>

CSS Image Techniques

responsive-image-css.css
CSS
1/* Aspect ratio containers */
2.image-wrapper {
3 aspect-ratio: 16 / 9;
4 overflow: hidden;
5}
6
7.image-wrapper img {
8 width: 100%;
9 height: 100%;
10 object-fit: cover; /* crop to fill */
11 object-position: center; /* center crop */
12}
13
14/* Object-fit options */
15.contain { object-fit: contain; } /* fit within, may have letterbox */
16.cover { object-fit: cover; } /* fill container, may crop */
17.fill { object-fit: fill; } /* stretch to fill */
18.none { object-fit: none; } /* original size */
19.scale-down { object-fit: scale-down; } /* smaller of contain or none */
20
21/* image-set() for resolution-based backgrounds */
22.hero {
23 background-image: image-set(
24 url("hero-1x.jpg") 1x,
25 url("hero-2x.jpg") 2x,
26 url("hero-3x.jpg") 3x
27 );
28 background-size: cover;
29}
🔥

pro tip

Always provide a width and height on images to prevent Cumulative Layout Shift (CLS). Set height: auto in CSS to maintain the aspect ratio while respecting the HTML dimensions.
Responsive Typography

Typography must adapt to screen size to maintain readability. Small screens need smaller text (less viewing distance) while preserving a comfortable line length. Fluid typography using clamp() eliminates the need for breakpoint-specific font sizes.

responsive-typography.css
CSS
1/* Fluid type scale using clamp() */
2:root {
3 --text-sm: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
4 --text-base: clamp(0.875rem, 0.8rem + 0.5vw, 1rem);
5 --text-lg: clamp(1rem, 0.9rem + 0.8vw, 1.25rem);
6 --text-xl: clamp(1.25rem, 1.1rem + 1.2vw, 1.75rem);
7 --text-2xl: clamp(1.5rem, 1.2rem + 2vw, 2.5rem);
8 --text-3xl: clamp(2rem, 1.5rem + 3vw, 4rem);
9}
10
11body {
12 font-size: var(--text-base);
13 line-height: 1.6;
14}
15
16h1 { font-size: var(--text-3xl); line-height: 1.1; }
17h2 { font-size: var(--text-2xl); line-height: 1.15; }
18h3 { font-size: var(--text-xl); line-height: 1.2; }
19
20/* Line length control */
21p {
22 max-width: 65ch; /* optimal line length */
23}
24
25/* Adjust line-height for different viewports */
26@media (max-width: 480px) {
27 p {
28 line-height: 1.7; /* more spacing on small screens */
29 }
30}
31
32/* Modular scale for headings */
33:root {
34 --modular-ratio: 1.25; /* major third */
35}
36
37h1 { font-size: clamp(2rem, 1.5rem + 2vw, calc(1rem * var(--modular-ratio) * 4)); }
38h2 { font-size: clamp(1.5rem, 1.2rem + 1.5vw, calc(1rem * var(--modular-ratio) * 3)); }
39h3 { font-size: clamp(1.25rem, 1rem + 1vw, calc(1rem * var(--modular-ratio) * 2)); }
preview
Breakpoints

Breakpoints are viewport widths where the layout changes to accommodate the screen size. Choose breakpoints based on your content, not specific devices. Mobile-first (min-width) is the recommended approach.

Common Breakpoint Ranges

NameWidthTypical Devices
Mobile320px — 480pxSmall phones
Mobile+481px — 767pxLarge phones, small tablets
Tablet768px — 1023pxiPads, Android tablets (portrait)
Desktop1024px — 1439pxLaptops, desktops
Wide1440px+Large monitors, ultra-wide

Mobile-First vs Desktop-First

breakpoints.css
CSS
1/* Mobile-first approach — recommended */
2/* Base styles = mobile */
3.layout {
4 display: flex;
5 flex-direction: column;
6 gap: 1rem;
7}
8
9/* Tablet */
10@media (min-width: 768px) {
11 .layout {
12 flex-direction: row;
13 flex-wrap: wrap;
14 }
15 .sidebar { flex: 0 0 250px; }
16 .main { flex: 1 1 0%; }
17}
18
19/* Desktop */
20@media (min-width: 1024px) {
21 .layout {
22 max-width: 1200px;
23 margin-inline: auto;
24 }
25}
26
27/* Desktop-first approach (not recommended) */
28/* Base styles = desktop */
29.layout-desktop-first {
30 display: grid;
31 grid-template-columns: 250px 1fr;
32 gap: 2rem;
33}
34
35/* Tablet — override desktop */
36@media (max-width: 1023px) {
37 .layout-desktop-first {
38 grid-template-columns: 200px 1fr;
39 gap: 1.5rem;
40 }
41}
42
43/* Mobile — full override */
44@media (max-width: 767px) {
45 .layout-desktop-first {
46 grid-template-columns: 1fr;
47 }
48}

Content-Driven Breakpoints

Rather than targeting specific devices, add a breakpoint when the content demands it — when a line becomes too long, when a sidebar gets too narrow, or when a card row wraps awkwardly.

content-driven-breakpoints.css
CSS
1/* Content-driven approach — breakpoints at content limits */
2.card-grid {
3 display: grid;
4 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
5 gap: 1.5rem;
6 /* Already responsive — no media query needed */
7}
8
9/* Add a media query only when content breaks */
10@media (min-width: 1000px) {
11 /* At this width, the sidebar has enough space */
12 .sidebar {
13 display: block; /* show previously hidden sidebar */
14 }
15}
16
17@media (min-width: 72rem) {
18 /* At this width, the hero text fits on one line */
19 .hero-title {
20 white-space: nowrap;
21 }
22}

best practice

Use min-width (mobile-first) over max-width (desktop-first). Mobile-first styles are simpler, cascade naturally, and force you to prioritize essential content. Desktop-first requires overriding more styles as the viewport shrinks.
Container Queries

Container queries allow you to style elements based on their parent container's size rather than the viewport. This is a paradigm shift — components can adapt to their available space regardless of the overall viewport size. Perfect for reusable components that appear in different contexts.

container-queries.css
CSS
1/* Step 1: Define a containment context */
2.card-container {
3 container-type: inline-size;
4 container-name: card;
5}
6
7/* Step 2: Query the container */
8@container card (min-width: 400px) {
9 .card {
10 display: grid;
11 grid-template-columns: 200px 1fr;
12 gap: 1rem;
13 }
14
15 .card-image {
16 aspect-ratio: 1;
17 }
18
19 .card-title {
20 font-size: 1.5rem;
21 }
22}
23
24@container card (max-width: 399px) {
25 .card {
26 display: flex;
27 flex-direction: column;
28 }
29
30 .card-title {
31 font-size: 1.125rem;
32 }
33
34 .card-cta {
35 width: 100%;
36 }
37}
38
39/* Container query shorthand */
40@container (min-width: 500px) {
41 /* affects nearest container */
42}
43
44/* container-type values */
45.wrapper {
46 container-type: normal; /* no containment */
47 container-type: inline-size; /* query width (most common) */
48 container-type: size; /* query width AND height */
49}
50
51/* container shorthand */
52.component {
53 container: card / inline-size;
54}

Container Queries vs Media Queries

AspectMedia QueriesContainer Queries
ReferenceViewport / deviceParent container
Component reuseComponent may break in different contextsComponent adapts to ANY context
ScopeGlobal — affects entire pageScoped — only affects children of the container
Use casePage layout, device-specific adjustmentsSelf-contained components, sidebars, widgets
Browser support Universal Chrome 105+, Safari 16+, Firefox 110+
preview
Testing Responsive Designs

Testing responsive designs requires multiple approaches: browser DevTools for quick iteration, real device testing for accuracy, and automated tools for coverage. No emulator is a perfect substitute for testing on actual hardware.

Testing Tools

ToolBest ForNotes
Chrome DevToolsRapid prototyping, device emulationDevice toolbar, responsive mode, throttling
Safari Web InspectoriOS testing, WebKit quirksResponsive design mode, iCloud device sync
Firefox Responsive ModeCSS Grid/Flexbox debuggingBest grid inspector, network throttling
BrowserStackCross-browser, real devicesCloud-based real device testing, 3000+ devices
LighthousePerformance, best practices auditMobile/desktop audits, accessibility checks
Playwright/CypressAutomated responsive testingProgrammatic viewport testing, visual regression

Testing Checklist

Test on real devices: an iPhone, an Android phone, and a tablet
Rotate devices to test both portrait and landscape orientations
Test with browser zoom at 200% and 300% (accessibility requirement)
Test with system font size set to Large (many users increase text size)
Verify touch targets are at least 44x44px on mobile
Test on slow network connections (3G throttling) to evaluate loading behavior
Check for horizontal scrollbars at every common breakpoint
Verify tap/click targets are not overlapping on small screens
Best Practices
Start with mobile-first CSS — base styles for mobile, then add min-width media queries
Use auto-fill + minmax() for responsive grids without media queries
Use clamp() for fluid typography and sizing — fewer breakpoints needed
Apply max-width: 100% and height: auto to all images for basic responsiveness
Use relative units (rem, %, vw, vh) instead of fixed px where possible
Use container queries for reusable components — they adapt to any context
Always include the viewport meta tag: width=device-width, initial-scale=1.0
Never disable user zoom — it's an accessibility requirement (WCAG 1.4.4)
Design touch targets at minimum 44x44px (WCAG AAA recommendation)
Test breakpoints by resizing the browser — add breakpoints where content breaks, not for specific devices
Use CSS Grid for two-dimensional page layouts and Flexbox for component-level responsive patterns
Consider data-saver users: use prefers-reduced-data to serve smaller images and fewer fonts

info

Responsive design is not just about screen sizes — consider input methods (touch vs mouse), network conditions (fast vs slow), accessibility needs (reduced motion, high contrast), and data preferences. The modern web must adapt to the user's entire context, not just their viewport dimensions.
$Blueprint — Engineering Documentation·Section ID: CSS-05·Revision: 1.0