본문 바로가기

반응형 디자인 기초

안정적인 HTML 의미 위에 유연한 크기, Flexbox·Grid, 미디어·컨테이너 쿼리를 조합하고 콘텐츠 기준 breakpoint를 검증합니다.

우리는 styled-components로 스타일 규칙을 React 컴포넌트 가까이에 두는 방법을 배웠습니다.

반응형 디자인은 별도의 React 기능이 아니라, 같은 콘텐츠와 동작을 다양한 뷰포트·입력 방식·사용자 설정에서도 읽고 조작할 수 있게 만드는 웹 설계 접근입니다. React는 의미 있는 HTML을 렌더링하고, 브라우저는 CSS의 유연한 크기와 레이아웃 알고리즘, 조건부 쿼리를 계산합니다.

같은 의미와 동작 위에 반응형 CSS를 쌓습니다

RESPONSIVE CSS · STABLE MEANING

같은 의미와 동작 위에 반응형 CSS를 쌓습니다

콘텐츠와 DOM 순서를 기반으로 유연한 크기·레이아웃을 적용합니다. 기본 배치로 해결되지 않는 관계만 환경·컨테이너 조건으로 전환합니다.

본문 ResponsiveLayout · 순서는 그대로

DOM: 제목 → 카드 목록 → 보조 정보
좁은 폭: 목록 다음에 보조 정보
48rem 이상: 보조 정보가 옆 열
DOM 순서와 주요 정보는 유지

48rem은 이 예제의 관계 전환 값입니다. viewport·container·사용자 선호 조건을 구분하며, 확대와 논리적 읽기 순서는 계속 확인합니다.

반응형 설계 책임 레이어환경 신호, 필요한 조건부 규칙, 유연한 배치가 콘텐츠와 DOM이라는 불변 기반 위에 놓입니다. 왼쪽 방향 표시는 기반 쪽으로 내려가는 관계이며 실행 단계의 시간 순서가 아닙니다. L4 · 환경 신호viewport · printpreference · inputL3 · 조건부 CSS@media · @container필요한 관계만 전환L2 · 유연한 배치normal flowFlexbox · Gridintrinsic sizeL1 · 콘텐츠·DOMmeaning · source orderactions · data환경에서 불변 기반으로
반응형 설계 책임 레이어환경 신호, 필요한 조건부 규칙, 유연한 배치가 콘텐츠와 DOM이라는 불변 기반 위에 놓입니다. 왼쪽 방향 표시는 기반 쪽으로 내려가는 관계이며 실행 단계의 시간 순서가 아닙니다. L4 · 환경 신호viewport · printpreference · inputL3 · 조건부 CSS@media · @container필요한 관계만 전환L2 · 유연한 배치normal flowFlexbox · Gridintrinsic sizeL1 · 콘텐츠·DOMmeaning · source orderactions · data환경에서 불변 기반으로

환경 신호, 필요한 조건부 규칙, 유연한 배치가 콘텐츠와 DOM이라는 불변 기반 위에 놓입니다. 왼쪽 방향 표시는 기반 쪽으로 내려가는 관계이며 실행 단계의 시간 순서가 아닙니다.

반응형 설계는 React에서 기기별 DOM을 따로 만드는 일이 아니라, 안정적인 의미 위에 적응형 CSS 표현을 쌓는 일입니다.


먼저 고정할 반응형 계약

화면이 좁아져도 제목·라벨·상태·주요 동작의 의미가 사라지면 안 됩니다. 먼저 CSS가 없어도 읽기 순서와 키보드 이동 순서가 자연스러운 HTML을 만들고, 그 위에 표현 계층을 더합니다.

유연한 크기: 고정된 화면 폭을 가정하지 않고 max-inline-size, %, fr, minmax(), clamp()처럼 주변 공간과의 관계를 표현합니다.

유연한 미디어: 이미지와 영상이 컨테이너를 넘지 않게 합니다. 기본적인 이미지에는 max-inline-size: 100%; block-size: auto;를 적용할 수 있습니다.

조건부 전환: 기본 흐름만으로 해결되지 않는 지점에 미디어 쿼리나 컨테이너 쿼리를 추가합니다.

모든 값을 상대 단위로 바꾸는 것이 목표는 아닙니다. 글자와 여백, 컨테이너, 선 두께처럼 값이 무엇과 관계를 맺는지에 따라 단위를 선택해야 합니다. 특히 글자 크기를 vw만으로 정하면 작은 화면이나 확대 환경에서 지나치게 작아질 수 있으므로 rem과 clamp()를 함께 고려합니다.


메타 뷰포트 태그

좁은 화면의 모바일 브라우저가 데스크톱용 가상 뷰포트로 페이지를 축소해 보여 주면, 작성한 작은 폭용 CSS가 예상대로 선택되지 않을 수 있습니다. 반응형 페이지의 HTML <head>에는 일반적으로 다음 설정을 둡니다.

Vite 프로젝트에서는 public 폴더가 아니라 프로젝트 루트의 index.html이 기본 HTML 진입점입니다.

index.html
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
  • width=device-width는 레이아웃 뷰포트 폭을 기기 화면 폭의 CSS 픽셀 기준에 맞춥니다.
  • initial-scale=1은 문서를 의도한 크기의 100% 초기 배율로 표시하라는 힌트입니다. 하드웨어 픽셀과 CSS 픽셀이 항상 1:1이라는 뜻은 아닙니다.

사용자의 확대를 막는 user-scalable=no나 과도한 maximum-scale 제한은 추가하지 않습니다. 확대는 작은 글자를 읽는 중요한 접근성 수단입니다.


미디어 쿼리와 breakpoint

미디어 쿼리는 뷰포트 폭뿐 아니라 출력 매체, 방향, 해상도, hover·pointer 같은 입력 특성, 모션 감소 같은 사용자 선호를 조건으로 CSS를 선택합니다.

/* 좁은 폭의 한 열이 기본값 */
.page-layout {
  display: grid;
  gap: 1rem;
}

/* 실제 콘텐츠가 두 열을 감당하는 지점부터 확장 */
@media (min-width: 48rem) {
  .page-layout {
    grid-template-columns: minmax(0, 1fr) 18rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .animated-item {
    transition: none;
  }
}

48rem은 특정 태블릿 모델의 이름이 아니라 이 예제 콘텐츠에서 두 열이 편안해지는 경계입니다. 가장 긴 제목, 번역된 문구, 실제 숫자와 URL을 넣고 폭을 연속해서 바꿔 보며 줄바꿈·overflow·조작 문제가 처음 생기는 지점을 찾습니다.

콘텐츠가 요구하는 경계에서만 breakpoint를 추가합니다

BREAKPOINT · CONTENT CONTRACT

콘텐츠가 요구하는 경계에서만 breakpoint를 추가합니다

좁은 폭의 기본 배치를 실제 제목·URL·숫자·빈 상태로 확인합니다. 읽기·조작·줄바꿈이 유지되는 분기와 깨져 전환이 필요한 분기를 모두 검증합니다.

본문 48rem · 목록과 보조 영역의 관계

기본: page-layout 한 열
min-width: 48rem → 본문 + 18rem 보조 열
auto-fit 카드 열은 공간에 따라 자동 조정

카드마다 query를 넣는 예제가 아닙니다. 전환 바로 아래·위, 중간 폭과 확대에서 긴 실제 제목의 읽기·조작을 다시 확인합니다.

콘텐츠 기반 breakpoint 선택 흐름실제 콘텐츠를 넣어 읽기와 조작이 유지되면 query 없이 종결합니다. 깨지는 분기에서만 경계를 추가하고 그 양쪽과 중간 폭을 다시 검증합니다. 48rem은 예제의 목록과 보조 영역 관계를 바꾸는 조건입니다. 좁은 폭 기본값논리적 DOM 순서실제 콘텐츠 검증긴 제목·URL·숫자연속해서 폭 바꾸기읽기·조작·줄바꿈유지되는가?query 없이 유지유연한 배치로 충분경계에 query 추가필요한 관계만 전환경계 전후 재검증바로 아래·위·중간유지깨짐
콘텐츠 기반 breakpoint 선택 흐름실제 콘텐츠를 넣어 읽기와 조작이 유지되면 query 없이 종결합니다. 깨지는 분기에서만 경계를 추가하고 그 양쪽과 중간 폭을 다시 검증합니다. 48rem은 예제의 목록과 보조 영역 관계를 바꾸는 조건입니다. 좁은 폭 기본값논리적 DOM 순서실제 콘텐츠 검증긴 제목·URL·숫자연속해서 폭 바꾸기읽기·조작·줄바꿈유지되는가?query 없이 유지유연한 배치로 충분경계에 query 추가필요한 관계만 전환경계 전후 재검증바로 아래·위·중간유지깨짐

실제 콘텐츠를 넣어 읽기와 조작이 유지되면 query 없이 종결합니다. 깨지는 분기에서만 경계를 추가하고 그 양쪽과 중간 폭을 다시 검증합니다. 48rem은 예제의 목록과 보조 영역 관계를 바꾸는 조건입니다.

기기 이름은 검증 대상이지 계약이 아님
48rem 같은 값은 예제 콘텐츠의 경계입니다. 새로운 폭과 확대 환경도 계속 통과해야 합니다.
breakpoint 수보다 빈 구간이 중요
등록한 몇 개 폭만 캡처하지 말고 두 breakpoint 사이에서 overflow와 어색한 밀도가 없는지 확인합니다.

좋은 breakpoint는 특정 기기 목록을 외운 숫자가 아니라 콘텐츠, 레이아웃, 조작 계약의 검증 결과입니다.

모바일 우선은 좁은 폭의 단순한 규칙을 기본값으로 두고 min-width 조건에서 넓은 폭의 레이아웃을 더하는 작성 순서입니다. override 관계를 단순하게 만드는 데 도움이 될 수 있지만, 그 자체가 더 빠른 페이지를 보장하지는 않습니다.

예제: 유연한 Grid와 콘텐츠 기준 전환

src/components/ResponsiveLayout.jsx와 src/components/ResponsiveLayout.css를 만듭니다.

src/components/ResponsiveLayout.jsx
import './ResponsiveLayout.css';

export default function ResponsiveLayout() {
  return (
    <section className="responsive-container" aria-label="반응형 카드 목록">
      <h2>반응형 카드 목록</h2>
      <div className="page-layout">
        <ul className="boxes-wrapper" role="list">
          <li className="box">가장 긴 실제 제목</li>
          <li className="box">상태와 요약</li>
          <li className="box">주요 동작</li>
        </ul>
        <aside className="supporting-info">
          넓은 폭에서는 옆 열에 놓이고, 좁은 폭에서는 목록 뒤에 이어집니다.
        </aside>
      </div>
    </section>
  );
}
src/components/ResponsiveLayout.css
.responsive-container {
  inline-size: min(calc(100% - 2rem), 75rem);
  margin-inline: auto;
  padding-block: clamp(1rem, 3vw, 2rem);
}

.page-layout {
  display: grid;
  gap: 1rem;
}

.boxes-wrapper {
  display: grid;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, 15rem), 1fr)
  );
  gap: clamp(0.75rem, 2vw, 1.25rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

.box,
.supporting-info {
  border: 1px solid #cbd5e1;
  border-radius: 0.5rem;
  padding: 1rem;
}

.box {
  min-block-size: 7.5rem;
}

@media (min-width: 48rem) {
  .page-layout {
    grid-template-columns: minmax(0, 1fr) 18rem;
    align-items: start;
  }
}

auto-fit과 minmax()가 카드 열을 가능한 범위에서 자동으로 바꾸므로 카드마다 별도 breakpoint가 필요하지 않습니다. 미디어 쿼리는 목록과 보조 영역의 관계가 실제로 바뀌는 지점에만 사용했습니다.


Flexbox와 Grid 선택

Flexbox는 한 번에 한 축, 즉 행 또는 열에서 공간을 분배하고 정렬하는 1차원 레이아웃 모델입니다. 버튼 행, 내비게이션, 한 줄의 메타 정보처럼 한 방향의 흐름이 중심일 때 적합합니다.

Grid는 행과 열을 함께 제어하는 2차원 레이아웃 모델입니다. 카드 열을 맞추거나 본문과 사이드바처럼 두 축의 관계가 중요한 배치에 적합합니다.

.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(100%, 16rem), 1fr)
  );
  gap: 1rem;
}
축과 정렬 관계에 맞춰 Flexbox·Grid를 고릅니다

CSS LAYOUT · AXIS & RELATIONSHIP

축과 정렬 관계에 맞춰 Flexbox·Grid를 고릅니다

한 축의 공간 분배와 정렬, 행·열을 함께 맞추는 관계, 별도 배치가 필요 없는 문서 흐름을 구별합니다. 두 도구는 서로 다른 컨테이너에서 함께 쓸 수 있습니다.

본문 레이아웃 · 컨테이너별 책임

.action-row → flex + flex-wrap: wrap
.card-grid  → grid + auto-fit / minmax
읽기·키보드 순서 → 논리적인 DOM

Flexbox는 한 번에 한 축을 제어합니다. 여러 줄로 감싸도 Grid처럼 줄 사이 track 정렬을 공유하는 모델은 아닙니다.

Flexbox와 Grid 선택 흐름한 축의 분배는 Flexbox, 두 축의 track 관계는 Grid, 별도 관계가 없으면 normal flow로 끝납니다. 두 도구는 다른 컨테이너에서 함께 사용할 수 있으며 시각 배치가 논리적 DOM 순서를 바꾸지는 않습니다. 설계할 역할바꾸려는 계약 확인한 축에서분배·정렬하는가?두 축의 track을함께 맞추는가?Flexbox한 번에 행 또는 열wrap도 한 축 기준Grid행·열 track 관계normal flow별도 배치가 불필요예아니오예아니오
Flexbox와 Grid 선택 흐름한 축의 분배는 Flexbox, 두 축의 track 관계는 Grid, 별도 관계가 없으면 normal flow로 끝납니다. 두 도구는 다른 컨테이너에서 함께 사용할 수 있으며 시각 배치가 논리적 DOM 순서를 바꾸지는 않습니다. 설계할 역할바꾸려는 계약 확인한 축에서분배·정렬하는가?두 축의 track을함께 맞추는가?Flexbox한 번에 행 또는 열wrap도 한 축 기준Grid행·열 track 관계normal flow별도 배치가 불필요예아니오예아니오

한 축의 분배는 Flexbox, 두 축의 track 관계는 Grid, 별도 관계가 없으면 normal flow로 끝납니다. 두 도구는 다른 컨테이너에서 함께 사용할 수 있으며 시각 배치가 논리적 DOM 순서를 바꾸지는 않습니다.

CSS 배치가 source order를 대신하지 않습니다.

order, reverse 방향, Grid placement는 보이는 위치를 바꿀 수 있지만 기본 읽기·키보드 탐색 순서를 논리적으로 고치지 않습니다.

Flexbox와 Grid는 함께 쓸 수 있습니다. 다만 각 컨테이너에서는 먼저 지배적인 축과 관계를 정하고, 조건부 query는 그 관계가 실제로 바뀌는 경우에만 추가합니다.

Flexbox의 order, row-reverse나 Grid 배치로 시각 순서만 바꿔도 기본 DOM 읽기 순서와 키보드 탐색 순서가 함께 바뀌지는 않습니다. 논리적인 순서는 HTML 소스에 먼저 반영하고, CSS 재배치는 의미를 바꾸지 않는 표현 조정에만 사용합니다.


미디어 쿼리와 컨테이너 쿼리

페이지 전체의 열 수처럼 뷰포트나 사용자 환경에 반응해야 하면 @media가 알맞습니다. 같은 카드가 넓은 본문과 좁은 사이드바에 동시에 놓일 수 있다면 뷰포트 폭만으로는 카드가 실제로 받은 공간을 알 수 없습니다. 이때 size container를 선언하고 @container로 조상 컨테이너의 inline size를 질의할 수 있습니다.

.card-region {
  container-type: inline-size;
}

.responsive-card {
  display: grid;
  gap: 1rem;
}

@container (min-width: 32rem) {
  .responsive-card {
    grid-template-columns: 8rem minmax(0, 1fr);
  }
}

size query는 자신이 아니라 가장 가까운 적합한 조상 query container를 기준으로 그 안의 요소에 스타일을 적용합니다. 따라서 위 예제에서는 .card-region이 폭을 제공하고 그 자손인 .responsive-card가 전환됩니다.


styled-components에서 반응형 CSS 사용

웹용 styled-components는 실제 stylesheet를 만들며 일반 CSS와 nesting을 지원합니다. 따라서 template literal 안에 @media와 @container를 직접 작성할 수 있고, 단순한 예제에 별도 JavaScript viewport state나 helper가 필요하지 않습니다.

src/components/StyledResponsiveExample.jsx
import styled from 'styled-components';

const PageLayout = styled.div`
  display: grid;
  gap: 1rem;

  @media (min-width: 48rem) {
    grid-template-columns: minmax(0, 1fr) 18rem;
  }
`;

const CardRegion = styled.section`
  container-type: inline-size;
`;

const ResponsiveCard = styled.article`
  display: grid;
  gap: 1rem;
  border: 1px solid #cbd5e1;
  border-radius: 0.5rem;
  padding: 1rem;

  @container (min-width: 32rem) {
    grid-template-columns: 8rem minmax(0, 1fr);
  }
`;

export default function StyledResponsiveExample() {
  return (
    <PageLayout>
      <CardRegion>
        <ResponsiveCard>
          <div aria-hidden="true">미리보기</div>
          <div>
            <h2>컨테이너 폭에 반응하는 카드</h2>
            <p>같은 뷰포트에서도 실제로 받은 공간에 따라 배치가 달라집니다.</p>
          </div>
        </ResponsiveCard>
      </CardRegion>
      <aside>보조 정보</aside>
    </PageLayout>
  );
}

여러 곳에서 함수 보간이 포함된 CSS 조각을 조합해야 할 때는 styled-components의 css helper를 사용할 수 있으며, 그 경우 import styled, { css } from 'styled-components';처럼 명시적으로 가져와야 합니다. 단순히 breakpoint 문자열을 감추기 위한 추상화부터 만들 필요는 없습니다.


반응형 컴포넌트 검수

반응형 컴포넌트의 계약은 “몇 px에서 몇 열인가”만으로 끝나지 않습니다. 폭이 달라도 같은 정보와 동작을 찾을 수 있어야 하고, 표현 변경이 DOM 의미나 탐색 순서를 깨뜨리지 않아야 합니다.

폭이 바뀌어도 의미·정보·조작 계약을 유지합니다

RESPONSIVE COMPONENT · INVARIANTS

폭이 바뀌어도 의미·정보·조작 계약을 유지합니다

열·간격·보조 설명 위치는 바꿀 수 있습니다. 핵심 값·상태·동작의 도달 경로와 DOM·focus 순서, 구조화 데이터의 관계는 모든 폭에서 확인합니다.

본문 반응형 카드 · 같은 계약, 다른 배치

카드 목록 + 보조 정보 → 좁은 폭 한 열
같은 제목·상태·동작 → 넓은 폭 두 영역
긴 문구·중간 폭·확대·키보드로 확인

카드 모양으로 바꾸는 표현과 표의 header/cell 의미 보존은 다른 문제입니다. 전체 데이터와 주요 동작에 도달할 경로를 유지합니다.

폭·입력 환경이 바뀌어도 지켜야 할 계약과 검증 방법
계약 유지할 것 바꿀 수 있는 것 검증
의미와 순서 heading·label·control 의미, 논리적 DOM과 focus 순서 열, 정렬, 간격 같은 시각 배치 CSS를 끄고 읽기, keyboard-only 탐색
핵심 정보와 동작 주요 값, 상태, 완료해야 할 task와 도달 경로 밀도, 보조 설명 위치, 명확한 접기·펼치기 작은 폭에서 정보·기능 누락 확인
레이아웃 콘텐츠 관계와 읽을 수 있는 최소 공간 Flex·Grid 방향, track 수, gap, wrapping 긴 실제 copy, zoom, 중간 폭 overflow
query 경계 전환이 해결해야 할 구체적인 layout 문제 @media 환경 조건, @container 조상 크기 조건 경계 바로 아래·위와 query 없는 구간
입력과 조작 keyboard, pointer, touch에서 같은 기능 target 크기·간격, hover 보조 표현 hover 없는 환경, focus 표시, 오작동 간격
구조화 데이터 table header와 cell 관계, 전체 데이터 접근 가로 scroll 또는 별도의 접근 가능한 표현 화면만 카드처럼 바꾸며 의미가 사라지지 않는지 확인
의미와 순서
유지 heading·label·control 의미와 논리적 DOM·focus 순서
변경 열, 정렬, 간격 같은 시각 배치
검증 CSS 없이 읽고 keyboard만으로 이동
핵심 정보와 동작
유지 주요 값·상태·task와 도달 경로
변경 밀도, 보조 설명 위치, 명확한 접기·펼치기
검증 작은 폭의 정보·기능 누락 확인
레이아웃
유지 콘텐츠 관계와 읽을 수 있는 최소 공간
변경 Flex·Grid 방향, track 수, gap, wrapping
검증 긴 실제 copy, zoom, 중간 폭 overflow
query 경계
유지 전환이 해결할 구체적인 layout 문제
변경 @media 환경 또는 @container 조상 크기 조건
검증 경계 바로 아래·위와 query 없는 구간
입력과 조작
유지 keyboard, pointer, touch에서 같은 기능
변경 target 크기·간격과 hover 보조 표현
검증 hover 없는 환경, focus 표시, 오작동 간격
구조화 데이터
유지 table header·cell 관계와 전체 데이터 접근
변경 가로 scroll 또는 별도의 접근 가능한 표현
검증 카드 모양으로 바꾸며 데이터 의미가 사라지지 않는지 확인

반응형 검수는 대표 기기 캡처만 확인하는 일이 아닙니다. 의미·정보·동작의 불변 조건을 실제 콘텐츠와 여러 입력 방식으로 증명합니다.

다음 조건을 breakpoint 바로 아래와 위뿐 아니라 중간 폭에서도 확인합니다.

  • 긴 한국어 제목, 끊기 어려운 URL, 큰 숫자와 빈 상태를 넣어 overflow와 줄바꿈을 확인합니다.
  • 브라우저 확대와 글자 크기 변경 후에도 콘텐츠와 조작 요소가 잘리거나 겹치지 않는지 봅니다.
  • 마우스 없이 키보드로 이동하며 시각 순서와 focus 순서가 자연스러운지 확인합니다.
  • hover가 없거나 정밀하지 않은 pointer에서도 같은 기능을 사용할 수 있게 합니다.
  • 작은 화면에서 핵심 정보를 단순히 숨기지 않습니다. 접거나 요약한다면 전체 정보에 도달할 수 있는 명확한 경로를 제공합니다.
  • 데이터 표를 카드처럼 보이게 바꿀 때는 header와 cell의 관계를 잃지 않아야 합니다. 우선 의미 있는 table을 유지한 채 가로 스크롤이나 별도의 접근 가능한 표현이 필요한지 검토합니다.

반응형 디자인 기초는 여기까지입니다.

핵심은 기기 이름별 화면을 따로 만드는 것이 아닙니다. 의미 있는 HTML을 기반으로 유연한 CSS를 먼저 사용하고, 실제 콘텐츠가 요구하는 경계에만 viewport·preference media query 또는 container query를 추가합니다. 이로써 5장 스타일링과 CSS를 마칩니다.

공식 문서

48rem 양쪽에서 실제 공간 계산하기

앞의 ResponsiveLayout을 App.jsx에서 렌더하고, 이 계산에서는 기본 글꼴 크기 1rem = 16px, body 여백 0, 예제 밖의 추가 폭 제한이 없다고 가정합니다. 카드 내용은 제공된 짧은 문자열 그대로입니다.

뷰포트가 767px이면 컨테이너 폭은 767 − 32 = 735px입니다. 48rem 경계인 768px보다 좁아 보조 정보는 목록 다음에 옵니다. 카드 간격은 2vw = 15.34px이고 최소 열 폭은 240px이므로 두 열의 최소 요구 폭은 240 × 2 + 15.34 = 495.34px, 세 열은 240 × 3 + 15.34 × 2 = 750.68px입니다. 세 카드가 있을 때 두 열까지만 들어갑니다.

뷰포트가 768px이 되면 컨테이너는 736px이지만 새 보조 열 288px과 바깥 Grid 간격 16px을 먼저 사용합니다. 목록에 남는 폭은 736 − 288 − 16 = 432px입니다. 따라서 카드 두 열에 필요한 495.36px을 확보하지 못해 목록은 한 열입니다. 뷰포트가 넓어졌어도 보조 영역이 옆에 생기면 카드 열 수는 줄 수 있습니다. 미디어 쿼리의 두 영역과 안쪽 auto-fit의 카드 열 수를 같은 값으로 생각하지 않습니다.

CSS를 끈 읽기 순서는 두 경우 모두 제목, 목록, 보조 정보입니다. 개발자 도구에서 바깥 .page-layout과 안쪽 .boxes-wrapper의 Grid를 각각 선택해 계산을 대조합니다. root 글자 크기나 주변 padding을 바꾸면 수치도 다시 계산해야 합니다.

어느 크기에 반응하는가?

같은 1000px 뷰포트에서 .card-region 두 개가 각각 400px과 600px의 inline size를 제공한다고 가정합니다. root 글자 크기는 16px입니다. 어느 카드가 @container (min-width: 32rem)의 두 열을 적용할까요? 카드가 받은 공간 대신 viewport width를 JavaScript state로 읽으면 이 차이를 구별할 수 있을까요?

컨테이너 기준의 해설

32rem은 512px이므로 600px 조상 컨테이너의 카드만 두 열을 적용합니다. 400px 쪽은 기본 한 열입니다. 뷰포트 값은 둘 다 1000px이라 그 값 하나로 각 카드가 실제 받은 공간을 구별하지 못합니다. size query를 제공하는 조상과 규칙을 적용받는 자손도 구별합니다.