Layout SystemP1 본문

레이아웃 시스템

4·8·12컬럼 반응형 그리드, 6단계 브레이크포인트, 컨테이너 규칙, 8px 스페이싱 리듬, 그리고 표준 화면 레이아웃 패턴을 정의합니다.

마지막 업데이트 2026-06-28

레이아웃 원칙#

  • 화이트스페이스가 위계를 만든다 — 구분선과 박스보다 여백을 먼저 사용합니다
  • 8px 그리드 — 모든 간격은 --wds-space-* 토큰의 배수입니다
  • 콘텐츠 폭 우선 — 화면이 넓어져도 본문 가독 폭을 유지합니다
  • 모바일에서 깨지지 않는다 — 320px이 최소 보장 폭입니다

레이아웃 프리미티브#

문서가 정의한 레이아웃을 재사용 가능한 토큰 백킹 컴포넌트로 제공합니다 — 모두 무상태(RSC 가능)입니다.

  • <Stack> — flex 1D 적층. gap--wds-space-* 스케일, direction·align·justify·wrap.
  • <Container> — 중앙 정렬 폭 제한. size(content 1200 · prose 760 · full) + padding(거터).
  • <Grid> / <GridItem> — 12컬럼(기본) 그리드. GridItemspan·start로 컬럼 점유.
  • <Split> — 52/48 분할. compact(600px 미만)에서 세로로 적층.
direction="vertical"gap=3 · 12px
요소 A
요소 B
요소 C
direction="horizontal"gap=4 · 16px
요소 A
요소 B
요소 C

박스는 자리표시용 자식입니다 — 보이는 건 박스가 아니라 그 사이 간격이며, 값은 --wds-space-* 토큰으로 정합니다.

Stack — 자식을 1D로 쌓고, 사이 간격은 gap 토큰으로

반응형 그리드#

컬럼 수는 Material window size class(ADR-012)와 정합합니다 — compact 4 · medium 8 · expanded 12. 1280px 미만에서는 마진이 고정되고 컨테이너가 유동하며, 1280px부터는 컨테이너가 1200px로 고정되고 마진이 가변합니다.

구간컬럼거터마진컨테이너
compact600px 미만416px16px 고정유동
medium600–840px824px24px 고정유동
expanded840px 이상1224px24px 고정유동 (1200px까지)
데스크톱1280px 이상1224px가변1200px 고정

핸들을 직접 끌어 보세요 — 뷰포트가 320↔1920px로 연속 변하며 컬럼이 4 → 8 → 12로 reflow되고 모든 수치가 실시간 갱신됩니다. 아래 실제 적용은 같은 뷰포트로 실물 Grid/GridItem 카드 레이아웃이 재배치되는 미리보기입니다 — 각 카드의 span이 size class별 규칙(stat 3→4→4 · main 8→8→4 · aside 4→8→4)으로 살아서 바뀝니다. size class 판정은 라이브러리 실물(windowSizeClass)을 그대로 사용합니다.

1280px viewportexpanded컬럼 12 × 78px거터 24px마진 40px 가변컨테이너 1200px 고정
실제 적용 — Grid · GridItem 실물 reflow
그리드 리사이즈 랩 — 드래그·←/→(±10px)·Shift(±100px)·마크 점프 + 실물 Grid 적용

기준 폭별 정적 스펙은 디바이스 탭으로 확인합니다.

1280px 이상컬럼 12 × 78px거터 24px컨테이너 1200px 고정 · 마진 가변
wide · 12801280px viewport
1200px · 12 cols
desktop · 14401440px viewport
120px
1200px · 12 cols
120px
max · 19201920px viewport
360px
1200px · 12 cols
360px
컬럼 4 · 8 · 12 거터 16 · 24px 마진 고정 → 1280부터 가변
반응형 그리드 스펙 — 디바이스별 컬럼(4·8·12) · 마진 · 거터 측정

정렬 검수는 오버레이를 실제 콘텐츠 위에 얹어 확인합니다. 자동 모드는 뷰포트가 아니라 프레임 자기 폭@container로 판정합니다 — 웹의 device-breakpoint를 container query로 옮기는 G-C 현대화이자, Flutter WizGrid(LayoutBuilder)와 같은 “컨테이너 기준” 멘탈모델입니다.

컬럼
오버레이

자동 모드는 뷰포트가 아니라 프레임 자기 폭@container로 판정합니다 (compact 4 · medium 8 · expanded 12). 브라우저 창을 좁히거나 넓혀 컬럼 수가 프레임 기준으로 바뀌는지 확인하세요 — Flutter WizGrid(LayoutBuilder)와 같은 멘탈모델입니다.

그리드 검수 오버레이 — 콘텐츠 위 컬럼 밴드 · 자동 @container(4·8·12) · 라이브 readout

이 원리는 라이브러리 실물에도 들어 있습니다. <Grid container>는 뷰포트가 아니라 그리드 자기 배치 폭@container로 판정해 컬럼을 적응시킵니다(compact 4 · medium 8 · expanded 12). 아래 세 격자는 같은 뷰포트에서 서로 다른 폭의 컨테이너에 놓여 각각 다른 컬럼 수로 재배열됩니다 — 뷰포트 기준이라면 불가능한 일입니다.

약 360px compact 4열
1
2
3
4
5
6
7
8
9
10
11
12
약 720px medium 8열
1
2
3
4
5
6
7
8
9
10
11
12
셀 전체 폭 expanded 12열
1
2
3
4
5
6
7
8
9
10
11
12

세 격자는 완전히 같은 뷰포트에서 렌더됩니다 — 컬럼 수를 가르는 것은 뷰포트가 아니라 각 <Grid container>가 놓인 컨테이너 폭입니다. 뷰포트 기준(@media)이라면 셋이 항상 같은 컬럼 수여야 하죠. 사이드바·split·모달 안에서도 실제 배치 폭으로 재배열되는 이유이며, Flutter WizGrid(LayoutBuilder)와 같은 멘탈모델입니다.

Grid container — 같은 뷰포트, 다른 컨테이너 폭 → 4·8·12열 (자기 폭 기준 적응)

중첩 콘텐츠는 <GridItem subgrid>로 부모 격자에 정렬합니다. subgrid 아이템은 자체 트랙을 만들지 않고 부모(master)의 컬럼 라인·거터를 그대로 상속하므로, 여러 master 컬럼을 점유하는 블록 안의 중첩 요소가 전역 그리드 리듬에서 어긋나지 않습니다.

span 2
span 4
span 2
span 2
span 4
span 2

③의 세 카드는 하나의 span 8 아이템 안에 중첩돼 있지만, 그 아이템이 subgrid라 부모의 컬럼 라인·거터를 그대로 물려받습니다 — 그래서 ②(직접 배치)·가이드와 정확히 같은 열에 정렬됩니다. 중첩 그리드가 자체 트랙을 새로 만들면 거터가 어긋나 정렬이 깨지지만, subgrid는 트랙을 상속하므로 어긋날 수 없습니다.

Grid subgrid — span 8 아이템 안의 중첩이 master 12칸 라인에 정렬

subgrid는 행에도 적용됩니다. <GridItem rowSpan={3} subgrid="rows">로 카드가 부모의 행 트랙을 상속하면, 본문 길이가 달라도 여러 카드의 헤더·본문·푸터가 같은 행에 정렬됩니다 — 카드 그리드· 비교 표의 행 리듬을 맞추는 표준 방법입니다. <Grid rows={N}>로 공유 행 트랙 수를 지정합니다.

subgrid="rows" → 헤더·본문·푸터가 행간 정렬
compact
짧은 설명.
span 3
medium
본문 길이가 카드마다 다릅니다. 이 카드는 두세 줄 분량의 설명을 담고 있습니다.
span 3
expanded
보통 길이 설명 한 줄 반.
span 3
일반 카드(flex) → 본문 높이만큼 푸터가 어긋남
compact
짧은 설명.
flex
medium
본문 길이가 카드마다 다릅니다. 이 카드는 두세 줄 분량의 설명을 담고 있습니다.
flex
expanded
보통 길이 설명 한 줄 반.
flex

위 격자의 카드는 각각 rowSpan={3}으로 부모의 3개 행 트랙을 점유하고 subgrid="rows"로 그 트랙을 상속합니다 — 그래서 본문 길이가 달라도 세 카드의 헤더·본문·푸터가 같은 행에 정렬됩니다. 아래 일반 카드는 각자 콘텐츠 높이만큼만 차지해 푸터가 제각각입니다. 행 subgrid는 카드 그리드·비교 표의 행 리듬을 맞추는 표준 방법입니다.

Grid row subgrid — 카드 헤더/본문/푸터 행간 정렬 (vs 일반 flex)

위 리사이즈 랩의 적용 미리보기가 실물 Grid/GridItem을 그대로 렌더하며, 각 카드의 span 라벨(예: span 8 = 12칸 중 8칸 점유)이 size class별로 재배치됩니다.

레이아웃 토큰은 SSOT에서 자동 생성된 표로 확인합니다.

토큰설명

브레이크포인트#

6단계 기준 폭에서 시각 검증을 수행합니다. 이 포털 셸의 반응형 규칙이 기준 구현(Reference)이며, 경계값은 SSOT(tokens/core/breakpoint.json)에서 파생됩니다.

기준 폭구간포털 셸 동작
320px모바일 최소단일 컬럼 · 드로어 내비 · 아이콘 검색
380px모바일헤더 검색이 아이콘 → 풀 입력으로 전환
768px태블릿단일 컬럼 유지 · 헤더 풀 구성
1024px데스크톱 시작좌측 사이드바 고정 노출
1280px와이드 데스크톱우측 TOC 노출 · 본문 폭 고정
1920px최대셸 폭 1920px 캡 — 콘텐츠가 무한히 늘어나지 않음

미디어 쿼리는 모바일 우선이 아닌 구간 명시 방식을 사용합니다 — 숨김/노출이 일어나는 경계(1024 · 1280)를 코드에서 그대로 읽을 수 있어야 합니다. 셸 CSS의 너비 미디어쿼리 리터럴이 이 SSOT와 어긋나면 build-tokens 드리프트 가드(breakpoint-css-parity.test)가 빌드를 실패시킵니다 — 경계는 브레이크포인트 토큰 한 곳에서만 바뀝니다.

셸 전환점 6개와 적응형 window size class 경계 2개(600 · 840)를 하나의 룰러에서 확인합니다 — 두 체계는 서로 다른 레이어입니다.

적응형 window size class — ADR-012
compact · 4컬럼
medium · 8컬럼
expanded · 12컬럼
600px840px
셸 레이아웃 전환점 — 6단계
브레이크포인트 룰러 — 셸 전환점 6 · 적응형 경계 2 (0–1920px)

모바일 목록·필터 규칙#

목록형 화면은 320px에서 페이지 전체 가로 스크롤이 없어야 합니다. 가로로 넘칠 수밖에 없는 데이터 표·코드·비교 매트릭스만 해당 표면 안에서 스크롤합니다.

검색·필터가 함께 있는 화면은 모바일에서 아래 순서를 기본으로 둡니다.

1. 검색
입력을 주 액션으로 두고, compact 폭에서는 필터 트리거를 같은 행의 보조 액션으로 배치
2. 조건 필터
필터 수가 많으면 기본 화면에서는 접고, 펼친 내부에서만 칩 레일 스크롤
3. 결과 헤더
검색 결과 N건을 조건 영역 아래에 분리
4. 결과 도구
목록표시·정렬기준은 compact Select, 보기 전환은 결과 헤더의 아이콘 스위치. 320px에서 잘리면 2열 그리드나 적층으로 재배치
5. 목록
compact 폭에서는 단일 컬럼. 긴 목록은 전체 렌더링하지 않고 페이지네이션

메트릭은 탐색을 밀어내지 않는 보조 정보입니다. 모바일에서는 2열 이하 요약으로 축소하고, 목록을 찾는 작업보다 크게 보이지 않게 합니다.

모바일 테이블 전환 규칙#

표는 “데이터 구조”가 아니라 “읽는 목적”을 기준으로 전환합니다. 좁은 화면에서 단순히 <td>마다 헤더 라벨을 반복하면 상태 목록·메타 정보는 오히려 읽기 어려워집니다.

비교·수치·행렬 데이터
Table/DataGrid를 유지하되, 열 정렬이 의미이므로 표면 내부 스크롤만 허용하고 페이지 전체 가로 스크롤은 금지
결과 목록·엔티티
Card/List로 전환하고 제목, 상태, 보조 메타, 주요 액션만 남김
상태·적용 현황·메타
Definition List로 전환하고 StatusDefinitionList처럼 용어와 값을 한 행으로 묶어 반복 라벨을 만들지 않음
복합 업무 표
Summary + Detail로 나누고 모바일에서는 요약 카드와 Drawer·BottomSheet·상세 화면으로 이동

모바일 폼 액션 규칙#

폼 하단 액션은 모바일에서 메시지와 버튼이 서로 폭을 빼앗지 않도록 분리합니다.

결과 메시지

저장 성공·오류 같은 Tier 2 메시지는 버튼 행 위에서 전체 폭을 사용합니다. 버튼 옆 좁은 칸에 넣어 문장을 세로로 쪼개지 않습니다.

동급 버튼

취소·저장처럼 같은 결정 묶음의 버튼은 2등분 동일 폭을 기본으로 합니다. 한쪽만 내용 폭으로 줄이지 않습니다.

주 버튼 문구

좁은 푸터에서는 주 버튼의 화면 문구를 작업명 중심으로 줄입니다. 단, aria-label이나 주변 문맥으로 전체 의미는 유지합니다.

보조 버튼 크롬

취소는 ghost가 아니라 outline 성격의 secondary를 기본으로 합니다. 주요 버튼과 높이·반경·테두리 체계를 공유해야 버튼 쌍으로 읽힙니다.

레이아웃 안정성

로딩·오류·성공 상태에서도 버튼 폭과 위치를 유지합니다. 메시지만 위 행에 추가하고 버튼 행을 흔들지 않습니다.

모바일 BottomSheet 내부 표면 규칙#

BottomSheet 자체가 이미 모바일의 표면입니다. 그 안에 데스크톱 팝업·모달의 카드 크롬을 다시 넣으면 좁은 화면에서 콘텐츠 폭을 두 번 잃습니다.

중첩 카드 금지

Calendar·선택 목록·짧은 폼 패널은 sheet 내부에서 border·border-radius·shadow·raised background로 다시 가두지 않습니다.

폭 사용

내부 컨텐츠는 시트 본문 폭을 채우고, 44px 전후 터치 타깃을 우선합니다. 양쪽 여백은 시트 본문 padding 한 번만 사용합니다.

컨트롤 예외

검색창·텍스트 필드처럼 입력 자체가 컨트롤인 경우만 자체 border를 허용합니다. Calendar/list/panel의 외곽 테두리와 배경은 제거합니다.

구분 방식

구분이 필요하면 카드 테두리 대신 섹션 간격, 제목, 얇은 separator를 사용합니다.

푸터

확인·취소 같은 하단 액션은 시트 또는 합성 컴포넌트의 sticky footer가 담당하고, safe-area padding을 포함합니다.

예외

여러 독립 선택지를 시각적으로 비교해야 하는 카드 목록은 예외지만, 카드 간 padding을 줄이고 전체 가로 스크롤은 만들지 않습니다.

스크롤바 규칙#

스크롤바는 내용이 실제로 넘칠 때만 보조 단서로 씁니다. 레이아웃을 맞추지 못한 결과를 스크롤바로 숨기지 않습니다.

웹 포인터
필요한 내부 스크롤 표면에만 얇은 thumb를 표시. track은 투명하게 두고, scrollbar gutter는 표면 안쪽에 둠
모바일·터치
스크롤바를 기본으로 숨김. 잘리는 컨트롤은 축약하거나 재배치하고, 칩·탭 레일은 드래그/스와이프와 엣지 단서로 안내
예외
데이터 표·코드·비교 매트릭스처럼 폭 자체가 의미인 콘텐츠만 표면 내부 스크롤 허용

컨테이너와 콘텐츠 폭#

용도근거
마케팅/홈 컨테이너--wds-container-max (1200px)12컬럼 그리드 기준 폭
문서 본문(prose)760px한글 기준 약 38–42자 — 가독 최적
셸 전체1920px 캡와이드 모니터에서 과확장 방지

본문이 760px을 넘는 요소(코드 블록, 넓은 표)는 가로 스크롤 래퍼로 감쌉니다 — 컨테이너를 깨뜨리지 않습니다.

셸 캡 1920px — 와이드 모니터 과확장 방지
컨테이너 1200px — 12컬럼 기준 폭

prose · 760px한 줄에 한글 약 38–42자 — 문서 본문의 가독 최적 폭입니다.

컨테이너 폭 스케일 — 셸 캡 1920 ⊃ 컨테이너 1200 ⊃ prose 760

스페이싱 리듬#

간격은 의미 단위로 선택합니다 — 요소 내부(1–3) · 요소 사이(4–6) · 블록 사이(8–12) · 섹션 사이(16–32).

요소 내부 · 1–3
요소 사이 · 4–6
블록 사이 · 8–12
섹션 사이 · 16–32

4px 베이스 유닛 — 모든 토큰은 4의 배수이며, space-4(16px)가 본문 리듬의 기준 한 칸입니다. 결번(5·7·9 …)은 의도입니다 — 위로 갈수록 성기게 증가해 선택을 단순하게 만듭니다.

8pt 스페이싱 스케일 — 4px 베이스 유닛

원시 토큰 값은 SSOT에서 자동 생성된 표로 확인합니다.

토큰설명

표준 레이아웃 패턴#

사이드바 레이아웃#

문서·관리 화면의 기본형 — 고정 사이드바(264px) + 유동 콘텐츠. 이 포털이 기준 구현입니다. 1024px 미만에서 사이드바는 드로어로 전환됩니다.

분할 레이아웃 (52 / 48)#

로그인·온보딩 화면의 기본형 — 좌측 비주얼·콘텐츠 52%(--wds-split-left), 우측 폼·액션 48%(--wds-split-right). 기존 로그인 화면이 이 비율의 정본이며, P4 Patterns의 Login 패턴으로 재구현됩니다.

디바이스 탭으로 각 뷰포트에서 52/48 비율·px·거터와 compact 적층을 측정값으로 확인합니다 — 위 반응형 그리드 스펙과 같은 블루프린트 방식입니다.

1280px 이상좌 52% · 우 48%split-left / split-right 토큰Feature / Form 역할
wide · 12801280px viewport
비주얼·콘텐츠52%
폼·액션48%
desktop · 14401440px viewport
비주얼·콘텐츠52%
폼·액션48%
비주얼·콘텐츠 52% 폼·액션 48% 거터 12px
분할 레이아웃 스펙 — 디바이스별 52/48 비율 · px · 거터 · compact 적층 측정

비주얼·콘텐츠 · 52%

폼·액션 · 48%

52/48 분할 — 실제 Split 프리미티브 (compact 600px 미만에서 세로 적층)

대시보드 그리드#

12컬럼 위에 카드 위젯을 배치하는 패턴 — 상세 규칙과 라이브 데모는 P4 패턴 섹션에서 정의됩니다.

구성과 정렬#

나란히 놓인 표면은 폭만 같아서는 정렬된 것이 아닙니다. 바깥 박스가 같은 높이여도 내부 콘텐츠 블록이 서로 다른 높이에서 시작·종료하면 시선이 흔들리고, 짧은 카드에 죽은 여백이 생깁니다. 같은 행의 형제(카드·패널·셀)는 바깥 높이뿐 아니라 앵커 지점·내부 리듬·정보 밀도까지 정렬되어야 합니다. 기준 구현은 플레이그라운드 스튜디오 셸(playground.module.css.body)로, 좌측 도구 사이드바와 우측 미리보기 캔버스를 가르는 그리드에 align-items를 두지 않아 기본 stretch(동일 높이)를 얻습니다 — 이 관습을 규칙으로 고정합니다.

동등 배치 통일성#

  • 규칙 — 같이 배치되는 동급 요소(카드·specimen·타일)는 통일합니다: 같은 높이 + 타이틀·내용이 같은 선에서 시작(상단 정렬) + 내용이 짧아도 여백을 살려 크기 유지. 단일 배치는 예외. 동일 높이·앵커 정렬·콘텐츠 패리티를 묶는 상위 원칙이며, 아래는 매직넘버 없이 강제하는 기법입니다.
  • 근거 — 폭만 같고 타이틀·내용 시작점이 제각각이면 “정렬 안 됨”으로 읽힙니다. 짧은 쪽을 콘텐츠 크기로 줄이면(여백 제거) 형제 간 크기가 갈려 통일성이 깨집니다 — 죽은 여백이 아니라 살린 여백이 통일을 만듭니다.
  • 기법
    • 동급 행 동일 높이 — 여러 행 그리드는 grid-template-rows: auto(헤더 행) + grid-auto-rows: 1fr(카드 행). 카드 행이 가장 큰 행에 맞춰 늘어나 전부 동일(auto-height 컨테이너서 1fr = max-content).
    • 별도 셀의 중첩 블록 정렬subgrid로 부모 행을 카드 간 공유: .parent{grid-template-rows:1fr auto auto} + .card{display:grid;grid-row:1/-1;grid-template-rows:subgrid}. specimen·이름·메타 행이 카드 간 정렬돼 내부 텍스트 줄바꿈 편차와 무관합니다 — 구식 “공유 min-height 바닥값”의 재보정 매직넘버를 대체합니다.
    • 캡션 줄 수 편차 — 가변 영역에 flex:1을 줄 때 캡션이 1줄/2줄로 갈리면 그만큼 무대를 잠식합니다. 캡션에 min-height(2줄 ≈ 3em)로 줄 수를 예약해 형제 무대를 통일합니다.
    • specimen 채움 + 상단 정렬 — 미니 카드처럼 풀-박스 specimen은 align-items: stretch로 무대를 채우고 내용을 상단 정렬(짧으면 아래 여백). 단 버튼·태그처럼 내재 크기가 의미인 specimen은 늘이면 안 되므로(세로로 늘어남), 타입이 섞이면 컴포넌트 prop으로 채움 모드를 스코프합니다(예: VariantTokens fillSpecimen) — 전역 CSS 일괄 적용 금지.
  • 검수 — 동급 세트의 바깥 높이·내부 무대 높이·타이틀 y좌표를 getBoundingClientRect로 실측해 px 동일을 확인합니다(육안 “비슷함”으로 끝내지 않음).

동일 높이#

  • 규칙 — 한 행에 나란히 놓인 패널·카드는 같은 높이를 가집니다 — Grid/Flex 기본 stretch에 맡기고, align-items: start로 높이를 끊지 않습니다.
  • 근거 — 들쭉날쭉한 바닥선은 “정렬되지 않음”으로 읽힙니다. 같은 높이는 형제가 같은 위계임을 시각적으로 선언합니다.
  • 기법 — 그리드 컨테이너에 align-items명시하지 않습니다(기본값 stretch). 유일한 예외는 내재 크기가 의미인 칩·뱃지·태그 행으로, 이때만 align-items: center로 콘텐츠 크기를 보존합니다.
  • 내부 박스까지 동일 크기 — 동일 높이는 바깥 카드에서 끝나지 않습니다. 형제 카드 안의 눈에 띄는 내부 박스(명세 박스·데이터 패널·내부 카드)도 콘텐츠 양(행 수 등)이 달라 크기가 갈리면 통일성이 깨집니다. 박스를 콘텐츠에 맞춰 줄이지 말고, 그 박스 자체에 flex: 1을 주어 짧은 쪽을 늘려 형제와 같은 크기로 맞춥니다 — flex: 1은 가변 텍스트가 아니라 크기를 맞출 박스에 둡니다(짧은 카드는 박스 안 아래 여백이 생기는 게 정답).
  • 별도 셀의 하위 블록 — 형제의 하위 영역이 각자 다른 그리드 셀에 있으면(예: 카드마다의 컬러 씬) 묶을 공유 행이 없어 stretch가 닿지 않습니다. 이때는 가장 큰 콘텐츠에 맞춘 공유 min-height 바닥값으로 높이를 맞추되, 더 큰 콘텐츠가 추가되면 바닥값을 재보정해야 하는 제약을 코드에 명시합니다.

앵커 정렬#

  • 규칙 — 형제 카드의 길이가 가변일 때, 구조적 앵커(메타데이터 푸터·레시피 라인·기본 CTA)는 카드 간 같은 선에서 정렬됩니다.
  • 근거 — 같은 높이여도 앵커가 카드 중간에 떠 있으면 비교가 깨집니다. 사용자는 “이 줄은 모든 카드에서 같은 위치”라는 암묵 계약을 읽습니다.
  • 기법 — 카드를 flex 세로 컬럼으로 만들고, 가변 영역(설명문)에 flex: 1 을 주어 빈 공간을 흡수시킵니다. 고정 앵커는 자연스럽게 카드 하단에 핀되어 형제 간 같은 선에 정렬됩니다. 전체 메타 박스에만 flex: 1을 주면 내부 블록이 위로 적층돼 설명 길이차로 푸터가 카드마다 다른 높이에 뜹니다.
  • 한계 — 진짜로 핀되는 건 맨 아래 블록뿐입니다. 그 위의 고정 블록(명세 박스 등)은 자기 아래 콘텐츠(노트 등)의 높이가 형제 간 같을 때만 함께 정렬됩니다 — 그래서 콘텐츠 패리티(노트를 평행한 길이로 유지)가 장식이 아니라 앵커 정렬을 지탱하는 조건입니다. 특정 블록을 반드시 정렬하려면 그 블록을 맨 아래에 두세요.

내부 리듬 일관성#

  • 규칙 — 형제 카드는 같은 내부 섹션 순서, 같은 gap 스케일, 같은 패딩을 공유합니다 — 바깥 크기뿐 아니라 구조의 패리티까지 일치시킵니다.
  • 근거 — 한 카드는 space-3, 옆 카드는 space-4로 호흡하면 같은 행인데 다른 리듬으로 읽혀 정렬감이 무너집니다.
  • 기법 — 형제 카드는 같은 클래스로 gap·padding을 단일 출처에 고정합니다 — 카드별 인라인 오버라이드를 금지합니다. 간격은 스페이싱 리듬(요소 내부 1–3 · 블록 사이 8–12)을 따라 카드 전체가 같은 단계를 씁니다.

콘텐츠 패리티#

  • 규칙 — 형제 카드는 비교 가능한 정보 밀도를 가집니다 — 한 카드가 거의 비어 있고 옆 카드는 가득 찬 상태를 두지 않으며, 카피는 구조적으로 평행합니다.
  • 근거 — 같은 골격·같은 앵커여도 한쪽이 빈약하면 짝이 깨져 보입니다. 정렬은 픽셀만의 문제가 아니라 내용의 무게가 평행할 때 완성됩니다.
  • 기법 — 데이터 모델에서 형제가 같은 필드 집합을 채우도록 강제하고(빈 슬롯은 플레이스홀더로 자리를 지킴), 카피는 같은 문형으로 평행하게 작성합니다.

온-스케일 치수#

  • 규칙 — 높이·여백·간격은 --wds-space-*(4px 스케일) 토큰에서 고릅니다. 임의 px(104px·176px 같은)는 같은 종류의 표면끼리 리듬을 깹니다.
  • 기법 — 같은 측정 표면(예: 스펙 바)은 하나의 높이 토큰을 공유합니다 — 그리드 스펙 바와 분할 스펙 바가 같은 행 높이(80px)를 쓰듯. 한쪽만 104px이면 나란히 봤을 때 어긋납니다.

컨테이너 채움 (shrink-wrap 금지)#

  • 규칙 — flex/grid 자식이 가운데 정렬(justify-content: center) 컨테이너 안에서 의도한 폭으로 렌더되려면 width: 100%(또는 align-self: stretch)가 필요합니다. 없으면 콘텐츠 폭으로 쪼그라들어(shrink-wrap) 작게 중앙에 박힙니다.
  • 기법 — 데모 캔버스처럼 자식을 가운데 정렬하는 부모에 폭이 콘텐츠 의존인 컴포넌트(Split·Carousel 등)를 넣을 땐 폭 100% 래퍼로 감쌉니다 — 실제로 두 컴포넌트 데모가 이 누락으로 깨진 적이 있습니다.

표현 일관성#

  • 규칙 — 같은 개념을 두 번 표현하면(측정 목업 + 라이브 데모) 색·치수·마커 언어를 통일합니다. 한쪽은 primary 틴트, 한쪽은 다른 회색이면 같은 것으로 안 읽힙니다.
  • 기법 — 역할별 색은 목업·라이브가 같은 토큰을 씁니다 — 예: 비주얼·콘텐츠=primary-subtle·폼·액션=surface-muted를 측정 스펙과 라이브 데모 양쪽 모두.

인접 컨트롤 크롬#

  • 규칙 — 나란히 놓인 컨트롤(필드·버튼·셀렉트)은 같은 크롬(테두리·표면·높이·반경 토큰)을 공유합니다. 채워진 필드 옆의 보조 버튼이 테두리·표면 없는 맨 글리프면 짝이 안 맞아 빈약·미완성으로 읽힙니다.
  • 근거 — 짝 컨트롤이 다른 무게(채운 면 vs 투명 글리프)로 보이면 의도된 그룹이 아니라 어긋난 요소로 읽힙니다.
  • 기법 — 보조 IconButton에 옆 필드와 같은 border·background: surface·border-radius: control을 부여하거나 같은 채움 variant를 씁니다 — 채워진 필드 옆 ghost 단독은 금지합니다.

캡션·문단 정렬#

  • 규칙 — 다줄 캡션·설명문은 의도된 정렬을 갖습니다 — 본문성 텍스트는 좌측 정렬(가운데 정렬 금지), 문단 사이는 토큰 간격으로 분리합니다.
  • 근거 — 가운데 정렬한 다줄 텍스트는 줄 길이가 들쭉날쭉(고아 단어)해 “정렬 안 됨”으로 읽힙니다.
  • 기법text-align: left + text-wrap: pretty(고아 줄 회피), 문단 분리는 --wds-space-*에서 — 2px 같은 비-토큰 간격을 쓰지 않습니다.

컨트롤 경계 수용#

  • 규칙 — 인터랙티브 컨트롤(캐러셀 화살표·슬라이더 핸들 등)은 섹션 콘텐츠 박스 안에 머뭅니다. 섹션 가장자리에 닿거나 넘으면 깨진 것으로 읽힙니다.
  • 근거padding-inline: calc(50% - X) 같은 % 중앙정렬 패딩은 containing block 기준이라, flex 형제(화살표)가 폭을 뺏는 좁은 컨테이너에서 트랙의 최소폭이 가용폭을 초과해 컨트롤을 바깥으로 밀어냅니다.
  • 기법 — 거터 컨트롤을 position: absolute 오버레이로 두어 트랙이 풀폭이 되게 하면 50%가 정확히 해석됩니다 — 또는 % 패딩을 형제 폭만큼 보정합니다. 좁은 컨테이너에서 컨트롤 가장자리가 섹션 안인지 프리뷰로 실측합니다.

인터랙션 일관성#

  • 규칙 — 같은 동작(복사·확장·선택 등)은 시스템 전역에서 같은 패턴·프리미티브로 구현합니다 — 표면마다 다른 방식(한쪽 hover 아이콘, 한쪽 클릭+툴팁)을 두지 않습니다.
  • 근거 — 같은 의미의 동작이 표면마다 다르게 작동하면 학습 비용이 늘고 “한 시스템”으로 안 읽힙니다 — 표현 일관성의 인터랙션 판본입니다.
  • 기법 — 복사는 공유 CopyTile(또는 useCopyToClipboard + copyTip, 타일 클릭 → 복사 + “복사됨” 툴팁)을 씁니다 — 새 표면이 ad-hoc 복사 UI(hover 아이콘 등)를 만들지 않게 합니다.

데모 스테이지 통일#

  • 규칙 — 데모는 공유 스테이지(Demo/DemoPane/HeroSpecimen)에만 무대(테두리·라운드·패딩·정렬)를 의존합니다. 개별 데모의 .module.css가 무대 높이·패딩·정렬을 다시 정의하지 않습니다 — 그 순간 데모마다 값이 갈려 통일성이 무너지고, 다음 고도화에서 손수 맞춘 값이 날아갑니다(리셋 위험).
  • 근거 — 같은 자리에 놓인 데모 표면이 한쪽은 상단 패딩 32, 옆은 12, 또 다른 곳은 자체 min-height로 제각각이면 “정리 안 됨”으로 읽힙니다. 무대는 한 곳(공유 스테이지)에서만 바뀌어야 일관됩니다.
  • 기법
    • 무대 자체(테두리·라운드·패딩·캡션 여백)는 공유 스테이지 CSS가 단일 출처로 소유합니다 — 데모는 콘텐츠만 책임집니다.
    • 콘텐츠 채움 — split pane·에디터처럼 무대를 채워야 하는 콘텐츠는 콘텐츠가 패널을 채우게 합니다(컴포넌트가 패널 자식을 stretch). 콘텐츠가 콘텐츠-높이로 떠 있고 구분선·경계만 풀 높이로 뻗으면(끝선 어긋남) 규칙 동일 높이·컨테이너 채움 위반입니다 — 구분선과 패널 콘텐츠의 위·아래 끝선이 px로 맞아야 합니다.
  • 검수 — 데모 무대의 패딩·높이·정렬이 공유 스테이지에서 오는지(개별 .module.css 재선언 0), split pane류는 구분선과 콘텐츠 끝선이 px 동일인지 프리뷰로 실측합니다.
동등 배치 통일성

적용: 동급 요소는 같은 높이 + 타이틀/내용 상단 정렬 + 여백 유지 — grid-auto-rows:1fr·subgrid·캡션 min-height·fill prop 스코프. 지양: 짧은 쪽을 콘텐츠로 줄여 크기 불일치, 타이틀 시작선 불일치, 재보정 필요한 매직넘버 min-height.

동일 높이

적용: 행 안의 형제는 Grid/Flex 기본 stretch로 같은 높이(.stage 기준), 내부 박스도 flex: 1로 동일 크기. 지양: align-items: start로 바닥선을 끊거나 내부 박스를 콘텐츠에 맞춰 줄이는 방식.

앵커 정렬

적용: 카드를 flex 컬럼으로 만들고 가변 본문에 flex: 1을 주어 푸터·CTA가 카드 간 같은 선에 핀되게 함. 지양: 메타 박스 전체에만 flex: 1을 주어 설명 길이차로 앵커가 카드 중간에 떠다니는 방식.

내부 리듬 일관성

적용: 형제가 같은 섹션 순서·같은 gap·같은 패딩을 단일 출처로 공유. 지양: 카드별 인라인 gap/padding 오버라이드.

콘텐츠 패리티

적용: 형제가 같은 필드 집합·평행한 카피·비교 가능한 밀도를 가짐. 지양: 한 카드는 가득 차고 옆 카드는 거의 비어 짝이 깨지는 상태.

온-스케일 치수

적용: height·여백을 --wds-space-*에서 고르고 같은 종류 표면은 같은 높이 토큰을 공유. 지양: 임의 px(104·176)로 행 리듬을 깨는 방식.

컨테이너 채움

적용: center 컨테이너의 자식은 width:100%/stretch를 기본으로 함. 지양: shrink-wrap으로 중앙에 작게 박히는 상태.

표현 일관성

적용: 목업·라이브가 같은 색·치수·마커 토큰을 공유. 지양: 같은 것을 다른 색/치수로 표현하는 방식.

인접 컨트롤 크롬

적용: 나란한 컨트롤이 같은 테두리·표면·높이·반경 토큰을 공유. 지양: 채운 필드 옆에 ghost 맨 글리프를 두어 짝이 빈약해 보이는 상태.

캡션·문단 정렬

적용: 다줄 캡션 좌측 정렬 + text-wrap:pretty, 문단 토큰 간격. 지양: text-align:center로 줄 길이가 들쭉날쭉해지는 상태.

컨트롤 경계 수용

적용: 캐러셀 화살표 등은 섹션 박스 안에 두고, 오버레이 또는 % 보정으로 수용. 지양: calc(50%-X) 패딩이 좁은 폭에서 컨트롤을 섹션 밖으로 밀어내는 방식.

인터랙션 일관성

적용: 복사 등은 공유 프리미티브(CopyTile 클릭→복사+툴팁)를 사용. 지양: 표면마다 hover 아이콘, 클릭 방식, 툴팁 방식을 제각각 두는 방식.

데모 스테이지 통일

적용: 무대(테두리·패딩·정렬·캡션)는 공유 스테이지가 단일 출처이고, split pane은 콘텐츠가 패널을 채워 구분선과 끝선이 일치. 지양: 데모별 .module.css가 무대 높이·패딩·정렬을 재선언하거나 콘텐츠가 떠 구분선만 풀 높이로 overhang되는 상태.

이 규칙의 기준 적용은 머티리얼 테마 갤러리 카드입니다 — 두 카드의 설명 길이가 달라도 명세·노트가 같은 선에 핀됩니다.

레이어 위계 (z-index)#

떠 있는 표면의 쌓임 순서는 토큰으로 고정합니다 — 표면이 어느 레이어를 쓰는지가 계약입니다.

1600
--wds-z-skip-link본문 건너뛰기 링크 — 접근성 최상위
1500
--wds-z-tooltipTooltip
1400
--wds-z-toastToast
1300
--wds-z-modalModal · Drawer · BottomSheet · 셸 검색
1200
--wds-z-overlay스크림 · 셸 드로어 내비
1100
--wds-z-sticky셸 헤더
1000
--wds-z-dropdownSelect · MultiSelect · Autocomplete · DropdownMenu · Popover · 날짜/시간 피커

컴포넌트 내부 로컬 스태킹(자체 컨텍스트 안 1–3)은 토큰 비대상 — 1000 미만의 임의 전역 z-index는 금지합니다.

레이어 스택 — 위일수록 높은 z, 실제 사용 표면 매핑
레이어z사용 표면
skip-link1600본문 건너뛰기 링크 (접근성 최상위)
tooltip1500Tooltip
toast1400Toast
modal1300Modal · Drawer · BottomSheet · 셸 검색
overlay1200스크림 · 셸 드로어 내비
sticky1100셸 헤더
dropdown1000Select · MultiSelect · Autocomplete · DropdownMenu · Popover · 날짜/시간 피커

컴포넌트 내부 로컬 스태킹(자체 스태킹 컨텍스트 안의 1–3, 예: DataGrid 스티키 셀, RangeSlider 썸)은 토큰 비대상입니다 — 단, 1000 미만의 임의 전역 z-index는 금지합니다.

토큰설명