DOMAIN:DESIGN:RESPONSIVE_DESIGN¶
OWNER: alexander (Design System Engineer, shared) ALSO_USED_BY: floris, floor, felice UPDATED: 2026-03-26 SCOPE: breakpoint strategy, fluid typography, container queries, layout patterns, touch targets, mobile-first
RESPONSIVE:OVERVIEW¶
APPROACH: mobile-first — design and build for smallest screen, enhance upward REASON: forces focus on essential content and interactions REASON: progressive enhancement is more robust than graceful degradation REASON: mobile traffic exceeds desktop for most SME client projects
RESPONSIVE:BREAKPOINT_STRATEGY¶
GE_STANDARD_BREAKPOINTS¶
| Name | Width | Target |
|---|---|---|
| xs | 0–479px | small phones |
| sm | 480–767px | large phones, small tablets |
| md | 768–1023px | tablets |
| lg | 1024–1279px | small laptops |
| xl | 1280–1535px | laptops, desktops |
| 2xl | 1536px+ | large desktops |
TAILWIND_IMPLEMENTATION¶
// tailwind.config.js — matches GE standard breakpoints
module.exports = {
theme: {
screens: {
'sm': '480px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
},
},
};
CSS_IMPLEMENTATION¶
/* Mobile-first: base styles = mobile */
.card-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-4);
}
/* Tablet */
@media (min-width: 768px) {
.card-grid {
grid-template-columns: repeat(2, 1fr);
gap: var(--spacing-6);
}
}
/* Desktop */
@media (min-width: 1024px) {
.card-grid {
grid-template-columns: repeat(3, 1fr);
}
}
RULES¶
RULE: always use min-width queries (mobile-first) — never max-width RULE: breakpoints are guidelines, not absolutes — adjust if content requires RULE: test at actual breakpoint values AND at in-between values (e.g., 900px) RULE: never hide critical content at any breakpoint — restructure instead
RESPONSIVE:FLUID_TYPOGRAPHY¶
APPROACH¶
METHOD: clamp() function for smooth scaling between minimum and maximum sizes WHY: avoids abrupt size jumps at breakpoints WHY: scales continuously with viewport width
IMPLEMENTATION¶
:root {
/* clamp(min, preferred, max) */
--font-size-body: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
--font-size-heading-page: clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem);
--font-size-heading-section: clamp(1.25rem, 1.1rem + 0.75vw, 1.75rem);
--font-size-heading-subsection: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
--font-size-caption: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
}
CALCULATION_METHOD¶
FORMULA: clamp(minSize, preferredSize, maxSize)
PREFERRED: minSize + (maxSize - minSize) * ((100vw - minViewport) / (maxViewport - minViewport))
SIMPLIFIED: use a clamp generator tool or this pattern:
min viewport: 320px
max viewport: 1280px
min font: 16px (1rem)
max font: 18px (1.125rem)
→ clamp(1rem, 0.95rem + 0.25vw, 1.125rem)
RULES¶
RULE: body text minimum 16px (1rem) — never smaller on any viewport RULE: line length 45-75 characters for readability — use max-width on text containers RULE: heading sizes should be noticeably larger than body text at all viewports RULE: do not use vw units alone — always clamp between min and max
RESPONSIVE:CONTAINER_QUERIES¶
WHAT¶
DEFINITION: style components based on their CONTAINER size, not the viewport WHY: components may be placed in sidebars, modals, or grid cells of varying widths WHY: viewport queries do not account for the component's actual available space
IMPLEMENTATION¶
/* Define a container */
.card-container {
container-type: inline-size;
container-name: card;
}
/* Style based on container width */
@container card (min-width: 400px) {
.card {
display: flex;
flex-direction: row;
gap: var(--spacing-4);
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
gap: var(--spacing-2);
}
}
WHEN_TO_USE¶
USE: reusable components that appear in different layout contexts USE: cards, widgets, data panels that may be in grid, sidebar, or full-width USE: dashboard layouts where widget sizes vary
DO_NOT_USE: page-level layout decisions (use viewport queries) DO_NOT_USE: when the component always has the same container width
BROWSER_SUPPORT¶
STATUS: supported in all modern browsers (Chrome 105+, Firefox 110+, Safari 16+) POLYFILL: not needed for GE's browser support targets
RESPONSIVE:LAYOUT_PATTERNS¶
CSS_GRID — PRIMARY_LAYOUT_TOOL¶
USE_FOR: page-level layouts, card grids, dashboard widget arrangements ADVANTAGE: two-dimensional control (rows AND columns) ADVANTAGE: fr units handle proportional sizing
PATTERN — AUTO_FIT_GRID:
/* Cards automatically fill available space */
.auto-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--spacing-6);
}
PATTERN — SIDEBAR_LAYOUT:
.sidebar-layout {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-6);
}
@media (min-width: 1024px) {
.sidebar-layout {
grid-template-columns: 280px 1fr;
}
}
PATTERN — DASHBOARD_GRID:
.dashboard {
display: grid;
grid-template-columns: 1fr;
gap: var(--spacing-4);
}
@media (min-width: 768px) {
.dashboard {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1280px) {
.dashboard {
grid-template-columns: repeat(4, 1fr);
}
.dashboard .widget-wide {
grid-column: span 2;
}
}
FLEXBOX — COMPONENT_LEVEL_LAYOUT¶
USE_FOR: component internals, navigation bars, form rows, button groups ADVANTAGE: one-dimensional flow with wrapping ADVANTAGE: alignment and distribution controls
PATTERN — NAV_BAR:
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--spacing-stack-sm) var(--spacing-inline-md);
gap: var(--spacing-inline-md);
}
.navbar-links {
display: flex;
gap: var(--spacing-inline-sm);
flex-wrap: wrap;
}
PATTERN — BUTTON_GROUP:
.button-group {
display: flex;
gap: var(--spacing-inline-sm);
flex-wrap: wrap;
}
/* Stack on mobile */
@media (max-width: 479px) {
.button-group {
flex-direction: column;
}
.button-group > * {
width: 100%;
}
}
GRID_VS_FLEXBOX_DECISION¶
USE_GRID: when you need rows AND columns controlled together USE_GRID: when you have a defined grid structure (dashboard, card layout) USE_FLEXBOX: when content flows in ONE direction (nav, toolbar, form row) USE_FLEXBOX: when items should wrap naturally based on available space
RESPONSIVE:TOUCH_TARGETS¶
SIZE_REQUIREMENTS¶
WCAG_2_2_AA: minimum 24x24 CSS pixels (2.5.8 Target Size Minimum) APPLE_HIG: recommended 44x44 points MATERIAL_DESIGN: recommended 48x48 dp GE_STANDARD: 44x44 CSS pixels for touch interfaces, 24x24 minimum for all interfaces
IMPLEMENTATION¶
/* Base — all interfaces */
button, a, [role="button"],
input[type="checkbox"], input[type="radio"],
select, summary {
min-width: 24px;
min-height: 24px;
}
/* Touch interfaces */
@media (pointer: coarse) {
button, a, [role="button"],
input[type="checkbox"], input[type="radio"],
select, summary {
min-width: 44px;
min-height: 44px;
}
}
SPACING_BETWEEN_TARGETS¶
RULE: adjacent touch targets must have at least 8px gap
REASON: prevents accidental activation of adjacent targets
IMPLEMENTATION: gap: var(--spacing-2) minimum between interactive elements
COMMON_ISSUES¶
ISSUE: icon-only buttons too small (16x16 or 20x20) FIX: add padding to increase touch target even if icon stays small
ISSUE: table row action buttons cramped together FIX: increase cell padding or use dropdown menu for actions
ISSUE: inline links in dense text EXCEPTION: inline links are exempt from target size requirements per WCAG 2.5.8
RESPONSIVE:MOBILE_FIRST_IMPLEMENTATION¶
PRINCIPLES¶
PRINCIPLE: start with single-column layout — add complexity as space increases PRINCIPLE: essential content first — supplementary content revealed at larger viewports PRINCIPLE: interactive elements thumb-friendly in mobile (bottom of screen for primary actions) PRINCIPLE: avoid hover-dependent interactions on mobile — use click/tap
MOBILE_SPECIFIC_CONSIDERATIONS¶
NAVIGATION: hamburger menu on mobile, horizontal nav on desktop
TABLES: stack cells or horizontal scroll on mobile (see component-patterns.md)
FORMS: single-column form layout on mobile, multi-column on desktop
MODALS: full-screen on mobile, centered overlay on desktop
IMAGES: responsive sizes with srcset, art direction with
VIEWPORT_META_TAG¶
REQUIRED: <meta name="viewport" content="width=device-width, initial-scale=1">
NEVER: user-scalable=no or maximum-scale=1 — violates WCAG 1.4.4 Resize Text
REASON: users must be able to zoom to 200% minimum
RESPONSIVE:TESTING_PROTOCOL¶
DEVICES_TO_TEST¶
| Category | Device / Width | Priority |
|---|---|---|
| Mobile small | 320px (iPhone SE) | PRIMARY |
| Mobile large | 390px (iPhone 14) | PRIMARY |
| Tablet portrait | 768px (iPad) | PRIMARY |
| Tablet landscape | 1024px (iPad landscape) | SECONDARY |
| Laptop | 1280px | PRIMARY |
| Desktop | 1440px | PRIMARY |
| Large desktop | 1920px | SECONDARY |
CHECKLIST¶
CHECK: content readable at 320px without horizontal scroll (WCAG 1.4.10) CHECK: no content hidden or clipped at any breakpoint CHECK: touch targets 44x44 on mobile (pointer: coarse) CHECK: navigation accessible at all breakpoints CHECK: forms usable at all breakpoints CHECK: data tables readable at all breakpoints CHECK: images scale appropriately CHECK: typography readable at all sizes CHECK: modals and dialogs work at all sizes CHECK: no fixed-width elements causing overflow
TOOLS¶
TOOL: browser DevTools responsive mode (Chrome, Firefox, Safari) TOOL: real device testing for touch interactions (cannot simulate with DevTools) TOOL: Playwright viewport testing for automated regression
RESPONSIVE:AGENT_INSTRUCTIONS¶
FOR alexander: - specify responsive behavior for every screen in DESIGN.md - define layout changes at each breakpoint explicitly - use fluid typography tokens — do not specify fixed sizes per breakpoint - design touch-friendly layouts for mobile viewport
FOR floris, floor: - implement mobile-first — write base styles for smallest screen - use Tailwind responsive prefixes (sm:, md:, lg:) for breakpoint overrides - use auto-fit/auto-fill grid where possible — reduces breakpoint code - test at 320px width — this is the WCAG reflow requirement - never use viewport units for font sizes without clamp()
FOR felice: - test responsive behavior at all breakpoints in the testing table - verify on real mobile device (not just DevTools) for touch interactions - flag content that is hidden on mobile but visible on desktop — should it be?
READ_ALSO: domains/design/design-system-engineering.md, domains/design/design-tokens.md, domains/design/component-library.md, domains/accessibility/wcag-2-2.md