home / skills / supercent-io / skills-template / responsive-design

responsive-design skill

/.agent-skills/responsive-design

This skill helps you design responsive web layouts that adapt across devices using mobile-first breakpoints, CSS Grid, Flexbox, and responsive images.

npx playbooks add skill supercent-io/skills-template --skill responsive-design

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
9.9 KB
---
name: responsive-design
description: Create responsive web designs that work across all devices and screen sizes. Use when building mobile-first layouts, implementing breakpoints, or optimizing for different viewports. Handles CSS Grid, Flexbox, media queries, viewport units, and responsive images.
tags: [responsive, mobile-first, CSS, Flexbox, Grid, media-query, viewport]
platforms: [Claude, ChatGPT, Gemini]
---

# Responsive Design


## When to use this skill

- **새 웹사이트/앱**: 모바일-데스크톱 겸용 레이아웃 설계
- **레거시 개선**: 고정 레이아웃을 반응형으로 전환
- **성능 최적화**: 디바이스별 이미지 최적화
- **다양한 화면**: 태블릿, 데스크톱, 대형 화면 지원

## Instructions

### Step 1: Mobile-First 접근

작은 화면부터 설계하고 점진적으로 확장합니다.

**예시**:
```css
/* 기본: 모바일 (320px~) */
.container {
  padding: 1rem;
  font-size: 14px;
}

.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

/* 태블릿 (768px~) */
@media (min-width: 768px) {
  .container {
    padding: 2rem;
    font-size: 16px;
  }

  .grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
  }
}

/* 데스크톱 (1024px~) */
@media (min-width: 1024px) {
  .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 3rem;
  }

  .grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 2rem;
  }
}

/* 대형 화면 (1440px~) */
@media (min-width: 1440px) {
  .grid {
    grid-template-columns: repeat(4, 1fr);
  }
}
```

### Step 2: Flexbox/Grid 레이아웃

현대적인 CSS 레이아웃 시스템을 활용합니다.

**Flexbox** (1차원 레이아웃):
```css
/* 네비게이션 바 */
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
}

/* 카드 리스트 */
.card-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

@media (min-width: 768px) {
  .card-list {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .card {
    flex: 1 1 calc(50% - 0.5rem);  /* 2 columns */
  }
}

@media (min-width: 1024px) {
  .card {
    flex: 1 1 calc(33.333% - 0.667rem);  /* 3 columns */
  }
}
```

**CSS Grid** (2차원 레이아웃):
```css
/* 대시보드 레이아웃 */
.dashboard {
  display: grid;
  grid-template-areas:
    "header"
    "sidebar"
    "main"
    "footer";
  gap: 1rem;
}

@media (min-width: 768px) {
  .dashboard {
    grid-template-areas:
      "header header"
      "sidebar main"
      "footer footer";
    grid-template-columns: 250px 1fr;
  }
}

@media (min-width: 1024px) {
  .dashboard {
    grid-template-columns: 300px 1fr;
  }
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
```

### Step 3: 반응형 이미지

디바이스에 맞는 이미지를 제공합니다.

**srcset 사용**:
```html
<img
  src="image-800.jpg"
  srcset="
    image-400.jpg 400w,
    image-800.jpg 800w,
    image-1200.jpg 1200w,
    image-1600.jpg 1600w
  "
  sizes="
    (max-width: 600px) 100vw,
    (max-width: 900px) 50vw,
    33vw
  "
  alt="Responsive image"
/>
```

**picture 요소** (Art Direction):
```html
<picture>
  <!-- 모바일: 세로 이미지 -->
  <source media="(max-width: 767px)" srcset="portrait.jpg">

  <!-- 태블릿: 정사각형 이미지 -->
  <source media="(max-width: 1023px)" srcset="square.jpg">

  <!-- 데스크톱: 가로 이미지 -->
  <img src="landscape.jpg" alt="Art direction example">
</picture>
```

**CSS 배경 이미지**:
```css
.hero {
  background-image: url('hero-mobile.jpg');
}

@media (min-width: 768px) {
  .hero {
    background-image: url('hero-tablet.jpg');
  }
}

@media (min-width: 1024px) {
  .hero {
    background-image: url('hero-desktop.jpg');
  }
}

/* 또는 image-set() 사용 */
.hero {
  background-image: image-set(
    url('hero-1x.jpg') 1x,
    url('hero-2x.jpg') 2x
  );
}
```

### Step 4: 반응형 타이포그래피

화면 크기에 따라 텍스트 크기를 조정합니다.

**clamp() 함수** (유동적 크기):
```css
:root {
  /* min, preferred, max */
  --font-size-body: clamp(14px, 2.5vw, 18px);
  --font-size-h1: clamp(24px, 5vw, 48px);
  --font-size-h2: clamp(20px, 4vw, 36px);
}

body {
  font-size: var(--font-size-body);
}

h1 {
  font-size: var(--font-size-h1);
  line-height: 1.2;
}

h2 {
  font-size: var(--font-size-h2);
  line-height: 1.3;
}
```

**미디어 쿼리 방식**:
```css
body {
  font-size: 14px;
  line-height: 1.6;
}

@media (min-width: 768px) {
  body { font-size: 16px; }
}

@media (min-width: 1024px) {
  body { font-size: 18px; }
}
```

### Step 5: Container Queries (신기능)

부모 컨테이너 크기에 따라 스타일 적용합니다.

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

.card {
  padding: 1rem;
}

.card h2 {
  font-size: 1.2rem;
}

/* 컨테이너가 400px 이상일 때 */
@container card (min-width: 400px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
    padding: 1.5rem;
  }

  .card h2 {
    font-size: 1.5rem;
  }
}

/* 컨테이너가 600px 이상일 때 */
@container card (min-width: 600px) {
  .card {
    grid-template-columns: 300px 1fr;
    padding: 2rem;
  }
}
```

## Output format

### 표준 브레이크포인트

```css
/* Mobile (default): 320px ~ 767px */
/* Tablet: 768px ~ 1023px */
/* Desktop: 1024px ~ 1439px */
/* Large: 1440px+ */

:root {
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;
  --breakpoint-2xl: 1536px;
}

/* 사용 예시 */
@media (min-width: 768px) { /* Tablet */ }
@media (min-width: 1024px) { /* Desktop */ }
```

## Constraints

### 필수 규칙 (MUST)

1. **Viewport 메타태그**: HTML에 반드시 포함
   ```html
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   ```

2. **Mobile-First**: 모바일 기본, min-width 미디어 쿼리 사용
   - ✅ `@media (min-width: 768px)`
   - ❌ `@media (max-width: 767px)` (Desktop-first)

3. **상대 단위**: px 대신 rem, em, %, vw/vh 사용
   - font-size: rem
   - padding/margin: rem 또는 em
   - width: % 또는 vw

### 금지 사항 (MUST NOT)

1. **고정 너비 금지**: `width: 1200px` 지양
   - `max-width: 1200px` 사용

2. **중복 코드**: 모든 브레이크포인트에 같은 스타일 반복 금지
   - 공통 스타일은 기본으로, 차이만 미디어 쿼리에

## Examples

### 예시 1: 반응형 네비게이션

```tsx
function ResponsiveNav() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <nav className="navbar">
      {/* 로고 */}
      <a href="/" className="logo">MyApp</a>

      {/* 햄버거 버튼 (모바일) */}
      <button
        className="menu-toggle"
        onClick={() => setIsOpen(!isOpen)}
        aria-label="Toggle menu"
        aria-expanded={isOpen}
      >
        <span></span>
        <span></span>
        <span></span>
      </button>

      {/* 네비게이션 링크 */}
      <ul className={`nav-links ${isOpen ? 'active' : ''}`}>
        <li><a href="/about">About</a></li>
        <li><a href="/services">Services</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>
  );
}
```

```css
.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
}

/* 햄버거 버튼 (모바일만) */
.menu-toggle {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.nav-links {
  display: none;
  position: absolute;
  top: 60px;
  left: 0;
  right: 0;
  background: white;
  flex-direction: column;
}

.nav-links.active {
  display: flex;
}

/* 태블릿 이상: 햄버거 숨기고 항상 표시 */
@media (min-width: 768px) {
  .menu-toggle {
    display: none;
  }

  .nav-links {
    display: flex;
    position: static;
    flex-direction: row;
    gap: 2rem;
  }
}
```

### 예시 2: 반응형 그리드 카드

```tsx
function ProductGrid({ products }) {
  return (
    <div className="product-grid">
      {products.map(product => (
        <div key={product.id} className="product-card">
          <img src={product.image} alt={product.name} />
          <h3>{product.name}</h3>
          <p className="price">${product.price}</p>
          <button>Add to Cart</button>
        </div>
      ))}
    </div>
  );
}
```

```css
.product-grid {
  display: grid;
  grid-template-columns: 1fr;  /* 모바일: 1 column */
  gap: 1rem;
  padding: 1rem;
}

@media (min-width: 640px) {
  .product-grid {
    grid-template-columns: repeat(2, 1fr);  /* 2 columns */
  }
}

@media (min-width: 1024px) {
  .product-grid {
    grid-template-columns: repeat(3, 1fr);  /* 3 columns */
    gap: 1.5rem;
  }
}

@media (min-width: 1440px) {
  .product-grid {
    grid-template-columns: repeat(4, 1fr);  /* 4 columns */
    gap: 2rem;
  }
}

.product-card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 1rem;
}

.product-card img {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}
```

## Best practices

1. **컨테이너 쿼리 우선**: 가능하면 미디어 쿼리 대신 컨테이너 쿼리
2. **Flexbox vs Grid**: 1차원은 Flexbox, 2차원은 Grid
3. **성능**: 이미지 lazy loading, WebP 포맷 사용
4. **테스트**: Chrome DevTools Device Mode, BrowserStack

## References

- [MDN Responsive Design](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design)
- [CSS Grid Guide](https://css-tricks.com/snippets/css/complete-guide-grid/)
- [Flexbox Guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
- [Container Queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries)

## Metadata

### 버전
- **현재 버전**: 1.0.0
- **최종 업데이트**: 2025-01-01
- **호환 플랫폼**: Claude, ChatGPT, Gemini

### 관련 스킬
- [ui-component-patterns](../ui-component-patterns/SKILL.md): 반응형 컴포넌트
- [web-accessibility](../web-accessibility/SKILL.md): 접근성과 함께 고려

### 태그
`#responsive` `#mobile-first` `#CSS` `#Flexbox` `#Grid` `#media-query` `#frontend`

Overview

This skill creates responsive web designs that adapt across devices and screen sizes using mobile-first techniques. It covers CSS Grid, Flexbox, media queries, viewport units, responsive images, typography scaling, and container queries. Use it to build layouts that scale smoothly from phones to large displays while preserving performance and accessibility.

How this skill works

Design starts mobile-first with base styles and adds breakpoints via min-width media queries to progressively enhance layouts. It recommends Flexbox for one-dimensional flows and CSS Grid for two-dimensional layouts, plus responsive images (srcset/picture) and clamp() or container queries for fluid typography and component-aware adjustments. The skill enforces relative units, viewport meta, max-width over fixed widths, and avoids redundant breakpoint code.

When to use it

  • Starting a new website or app with mobile-first layouts
  • Converting fixed-width legacy layouts to responsive designs
  • Optimizing images and assets per device for performance
  • Designing dashboards or complex interfaces that need grid/flex control
  • Implementing component-aware styles using container queries

Best practices

  • Always include the viewport meta tag: <meta name="viewport" content="width=device-width, initial-scale=1.0">
  • Design mobile-first and use @media (min-width: ...) for breakpoints
  • Prefer relative units (rem, em, %, vw) and use max-width instead of fixed widths
  • Use Flexbox for linear layouts and Grid for complex two-dimensional layouts
  • Serve responsive images with srcset/picture and lazy-load heavy assets
  • Favor container queries for component-driven responsiveness when supported

Example use cases

  • Responsive navigation that shows a hamburger menu on mobile and horizontal links on tablet/desktop
  • Product grid that moves from 1 column on mobile to 2–4 columns across breakpoints
  • Dashboard layout that rearranges header, sidebar, and main content with CSS Grid
  • Hero images that switch art direction via picture or background-image media queries
  • Cards that adjust internal layout using container queries when their parent changes size

FAQ

What breakpoint strategy should I use?

Use a mobile-first approach with semantic breakpoints based on content needs (not device models) and implement them with @media (min-width: ...).

When should I use Flexbox vs Grid?

Use Flexbox for single-row/column flows and small component layouts; use Grid for full-page or two-dimensional arrangements where rows and columns interact.