Skip to content

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 where needed TYPOGRAPHY: fluid sizing ensures readability without manual breakpoint overrides

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