# Spacing 4px 배수 한 축으로 요소 사이의 거리를 결정하는 간격 스케일입니다. > 원본: `03_ASSET_GUIDE/foundations/spacing.js` · 값: `03_ASSET_GUIDE/styles/tokens.css` (`--- Spacing: x-scale ---` 절) > status `stable` · specSource `measured` | 단계 | 역할 | 예시 | |---|---|---| | **Primitive** | 4px 배수 인덱스 스케일 `--atom-x{n}` (`n × 4 = px`) | `--atom-x6` = `24px` | | **Semantic** | 없음 — 값과 관계 거리 규칙(아래 2절)으로 대신합니다 | 라벨↔입력 `x2`, 필드↔필드 `x5` | > **원칙:** 간격은 항상 토큰으로 씁니다. 4px 배수라도 `margin: 20px` 처럼 직접 쓰지 않습니다. > 이름에 인덱스를 그대로 쓰므로 이름에서 값을 바로 알 수 있습니다. 11단계를 형용사로 구분하기 어려워 `small` · `large` 같은 이름은 쓰지 않습니다. --- ## 1. Primitive tokens 라이트/다크에서 값이 같습니다. | Token | Value | 주 사용처 | 저장소 내 사용 횟수 | |---|---|---|---| | `--atom-x1` | 4px | 아이콘과 라벨 사이, 카드 제목과 설명 사이 | 4 | | `--atom-x2` | 8px | 한 덩어리로 읽혀야 하는 요소 사이 | 26 | | `--atom-x3` | 12px | 컴포넌트 내부 여백 | 31 | | `--atom-x4` | 16px | 기본 여백, 본문 좌우 | 29 | | `--atom-x5` | 20px | 카드 내부 패딩 | 16 | | `--atom-x6` | 24px | 서로 다른 그룹 사이 | 13 | | `--atom-x7` | 28px | h4 섹션 위 | 1 | | `--atom-x8` | 32px | 스테이지 세로 패딩, 히어로 위 | 6 | | `--atom-x10` | 40px | 본문 상하 패딩, h3 섹션 위 | 9 | | `--atom-x12` | 48px | h2 섹션 위, 푸터 위 | 4 | | `--atom-x14` | 56px | 넓은 화면의 페이지 헤더 아래 | 1 | ### 결번 (x9 · x11 · x13) `--atom-x9`(36px) · `--atom-x11`(44px) · `--atom-x13`(52px) 은 **정의되어 있지 않습니다.** 아직 필요한 곳이 없어서 만들지 않았습니다. 인덱스 방식이라 결번이 있어도 이름이 어긋나지 않습니다. `x9` 가 필요하면 그 자리에 추가합니다. > [!NOTE] > 32px(`x8`) 위로는 간격이 8px 씩 건너뜁니다. 큰 간격에서 4px 차이는 눈에 띄지 않으므로, > 값이 커질수록 단계를 성기게 두는 편이 선택을 쉽게 만듭니다. ### 레이아웃 고정값 고정 치수는 간격 스케일과 별개로 전용 토큰을 씁니다. 4px 배수를 따르지만 간격이 아니라 요소의 크기이므로 스케일에 넣지 않았습니다. | Token | Value | 대상 | |---|---|---| | `--atom-control-h` | `48px` | 컨트롤 기본 높이 (Input · Textarea · Select · Multi Select · Date Input · Time Input · Input Button) | | `--atom-control-h-small` | `40px` | 컨트롤 `small` 높이 | | `--atom-control-h-large` | `56px` | 컨트롤 `large` 높이 | | `--atom-header-h` | `76px` | 사이트 헤더 높이 | | `--atom-sidebar-w` | `240px` | 사이드바 폭 | | `--atom-toc-w` | `200px` | 목차 폭 | | `--atom-sidebar-item-h` | `36px` → `38px` → `40px` | 사이드바 항목 높이 (1120px · 1280px 에서 단계 증가) | 컨트롤 높이 48 / 40 / 56 은 `x12` / `x10` / `x14` 와 값이 같지만 간격이 아닙니다. 간격 스케일을 옮겨도 컨트롤이 움직이면 안 됩니다 (`tokens.css` `--- Control surface ---` 절). Button 은 자체 높이를 갖고, 조합에 들어갈 때 `field.css` 가 행 높이에 맞춰 늘립니다. `header-h` · `sidebar-w` · `toc-w` · `sidebar-item-h` 는 문서 사이트 셸용입니다. --- ## 2. Semantic tokens ATOM 은 간격에 역할 토큰을 두지 않습니다. 대신 **값이 관계 거리를 나타낸다**는 규칙을 씁니다. ### 값과 관계 거리 값이 클수록 **요소 사이의 관계가 먼 것**을 나타냅니다. | 거리 | 토큰 | 뜻 | |---|---|---| | 4 – 8px | `x1` · `x2` | 한 덩어리. 아이콘과 라벨처럼 떼면 의미가 깨지는 관계 | | 12 – 20px | `x3` · `x4` · `x5` | 같은 그룹 안의 형제 | | 24 – 32px | `x6` · `x8` | 다른 그룹 | | 40px 이상 | `x10` · `x12` · `x14` | 다른 섹션 | ### 규칙 1. **그룹 사이는 그룹 안보다 넓게** — 라벨과 입력 사이 `x2`, 필드와 필드 사이 `x5` 처럼 안쪽을 좁게 둡니다. 2. **여백은 컨테이너가 만듭니다** — 간격은 감싸는 쪽에서 `gap` 이나 `padding` 으로 만듭니다. 3. **좌우 여백만 화면 폭에 따라 바뀝니다** — 본문 좌우 여백은 좁은 화면에서 `x4`(16px), 넓은 화면에서 `x8`(32px) (`layout.css` 의 `.atom-layout__main`). 세로 간격은 바꾸지 않습니다. 예외는 페이지 헤더 아래 여백(`x10` → `x14`)뿐이고, 헤더 글자 크기가 `2rem` → `3.75rem` 로 함께 커지기 때문입니다. --- ## 3. Design tokens (JSON) [W3C Design Tokens (DTCG)](https://tr.designtokens.org/format/) 형식입니다. 경로는 `--atom-x{n}` → `space.x{n}` 입니다. ```json { "space": { "$type": "dimension", "x1": { "$value": "4px" }, "x2": { "$value": "8px" }, "x3": { "$value": "12px" }, "x4": { "$value": "16px" }, "x5": { "$value": "20px" }, "x6": { "$value": "24px" }, "x7": { "$value": "28px" }, "x8": { "$value": "32px" }, "x10": { "$value": "40px" }, "x12": { "$value": "48px" }, "x14": { "$value": "56px" } }, "control": { "$type": "dimension", "h": { "$value": "48px" }, "h-small": { "$value": "40px" }, "h-large": { "$value": "56px" } }, "layout": { "$type": "dimension", "header-h": { "$value": "76px" }, "sidebar-w": { "$value": "240px" }, "toc-w": { "$value": "200px" }, "sidebar-item-h": { "$value": "36px", "$extensions": { "atom": { "min-width-1120": "38px", "min-width-1280": "40px" } } } } } ``` --- ## 4. CSS 적용 ```css /* 컨테이너가 간격을 만든다 */ .atom-field-group { display: flex; flex-direction: column; gap: var(--atom-x5); } /* 그룹 안은 그룹 사이보다 좁게 */ .atom-field { display: flex; flex-direction: column; gap: var(--atom-x2); } ``` --- ## 5. 사용 가이드 ### 간격은 항상 토큰으로 4px 배수라도 `margin: 20px` 처럼 직접 쓰지 않습니다. 직접 쓴 값은 밀도를 조정할 때 일괄 변경되지 않습니다. - ✅ **Do** `gap: var(--atom-x3)` 처럼 토큰으로 씁니다. - ❌ **Don't** `gap: 12px` 처럼 값을 직접 쓰지 않습니다. ### 스케일에 없는 값은 쓰지 않습니다 18px 이 필요해 보이면 대개 16px 이나 20px 로 충분합니다. 꼭 필요하면 토큰을 추가하고, 한 곳에서만 쓸 값을 직접 넣지 않습니다. 예외는 **광학 보정**입니다. 아이콘의 시각 중심이 기하 중심과 어긋나는 경우처럼 스케일과 무관한 1–2px 조정은 스케일 밖의 값을 써도 됩니다. 다만 왜 그런지 주석을 남깁니다. - ✅ **Do** 스케일에서 가장 가까운 두 값 중 하나를 고릅니다. - ⚠️ **Caution** 광학 보정은 예외로 두되, 이유를 주석으로 남깁니다. - ❌ **Don't** 한 곳에서만 쓸 중간값을 만들지 않습니다. ### 그룹 사이는 그룹 안보다 넓게 간격은 **요소의 묶음**을 나타냅니다. 그룹 안 간격이 그룹 사이 간격보다 넓으면 묶음이 잘못 읽힙니다. - ✅ **Do** 라벨과 입력 사이 `x2`, 필드와 필드 사이 `x5` 처럼 안쪽을 좁게 둡니다. - ❌ **Don't** 필드 안팎을 같은 간격으로 두지 않습니다. ### 여백은 컨테이너가 만듭니다 자식 요소에 `margin` 을 붙여 간격을 만들면 그 요소를 다른 곳에 옮길 때마다 간격이 따라옵니다. - ✅ **Do** 컨테이너에 `display: flex; gap: var(--atom-x2)` 를 씁니다. - ❌ **Don't** 자식마다 `margin-right` 를 붙이고 마지막만 예외 처리하지 않습니다. ### 접근성 - **터치 영역** — 간격이 아니라 요소 자체의 크기로 확보합니다. 최소 44×44px 를 권장하며, `--atom-x11`(44px) 이 없으므로 현재는 컴포넌트별 `min-height` 로 처리합니다(예: `--atom-control-h-small`(40px)을 쓰는 `small` 컨트롤은 이 기준에 못 미칩니다). - **인접한 액션** — 서로 다른 결과를 내는 버튼이 나란히 있을 때는 최소 `x2`(8px) 를 둡니다. 간격이 좁으면 잘못 누르기 쉽습니다. - **확대** — 간격은 px 고정이라 브라우저 글자 확대에 반응하지 않습니다. 200% 확대에서 내용이 겹치지 않는지는 컴포넌트마다 확인해야 합니다.