# Responsive Patterns

> When to activate: responsive design, mobile-first, breakpoints, fluid typography, container queries, viewport units, clamp

- Skill: `mattakushi432/responsive-patterns` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mattakushi432/responsive-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mattakushi432/responsive-patterns/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: Mattakushi432 (https://skillmd.com/u/mattakushi432)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mattakushi432/responsive-patterns

---

# Responsive Patterns

## Mobile-First Breakpoints

```css
/* Define breakpoints as custom media (PostCSS or native) */
:root {
  --bp-sm: 640px;
  --bp-md: 768px;
  --bp-lg: 1024px;
  --bp-xl: 1280px;
}

/* Mobile first — add complexity upward */
.card { flex-direction: column; }
@media (min-width: 768px) { .card { flex-direction: row; } }

/* Avoid max-width overrides — they lead to specificity wars */
```

## Fluid Typography with clamp()

```css
/* clamp(min, preferred, max) — no breakpoints needed */
:root {
  --text-base: clamp(1rem, 0.9rem + 0.4vw, 1.125rem);
  --text-xl:   clamp(1.25rem, 1rem + 1vw, 2rem);
  --text-hero: clamp(2rem, 1rem + 5vw, 5rem);
  --space-section: clamp(3rem, 2rem + 5vw, 8rem);
}
```

## Container Queries (Preferred Over Media Queries for Components)

```css
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

/* Style based on available space, not viewport */
@container card (min-width: 500px) {
  .card { display: grid; grid-template-columns: 200px 1fr; }
}
@container card (max-width: 300px) {
  .card__meta { display: none; }
}
```

## Viewport Units

```css
/* dvh accounts for mobile browser chrome */
.hero { min-height: 100dvh; }
.modal { max-height: 90dvh; overflow-y: auto; }

/* svh = small viewport height (most restrictive) */
/* lvh = large viewport height (most generous) */

/* Fluid spacing without media queries */
.section { padding-block: clamp(3rem, 5dvh, 8rem); }
```

## Intrinsic Responsive Grid

```css
/* Auto-fill columns — no breakpoints needed */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: clamp(1rem, 2vw, 2rem);
}
```

## Responsive Images

```html
<img
  srcset="img-400.webp 400w, img-800.webp 800w, img-1200.webp 1200w"
  sizes="(max-width: 640px) 100vw,
         (max-width: 1024px) 50vw,
         33vw"
  src="img-800.webp"
  alt="" width="800" height="600" loading="lazy">
```

## Aspect Ratio

```css
/* Maintain ratio without padding-top hack */
.video-embed {
  aspect-ratio: 16 / 9;
  width: 100%;
}
.avatar {
  aspect-ratio: 1;
  width: clamp(40px, 8vw, 80px);
  border-radius: 50%;
}
```

## Touch Targets

```css
/* WCAG 2.5.5: touch targets >= 44x44px */
.icon-button {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
```

## Responsive Table

```css
/* Scroll on small screens */
.table-wrapper {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
table { min-width: 600px; }

/* Or stack with data attributes */
@media (max-width: 640px) {
  thead { display: none; }
  tr    { display: block; border: 1px solid var(--color-border); margin-block: 1rem; }
  td    { display: flex; justify-content: space-between; }
  td::before { content: attr(data-label); font-weight: bold; }
}
```

