이번 편의 결과물: portfolio/css/ 전체의 물리 속성(margin-left, padding-right, border-bottom 등)이 논리 속성(margin-inline-start, padding-inline-end, border-block-end 등)으로 바뀐다. · 다루는 개념: inline/block 축, 논리 속성-물리 속성 매핑, 축약형(margin-inline, padding-block)
이 편에서 만드는 파일
web-practice/
└── portfolio/
└── css/
└── styles.css ~ (물리 속성 → 논리 속성 전면 치환)새 파일은 없습니다. 08편까지 만든 @layer 5개(reset, tokens, base, components, utilities)와 @scope, 서브그리드 규칙은 그대로 두고 속성 이름만 바꿉니다.
개념 정리
지금까지 쓴 margin-left, padding-top, border-right 같은 속성은 화면의 물리적 방향(위·아래·왼쪽·오른쪽)을 기준으로 합니다. 한국어·영어처럼 가로쓰기·왼쪽에서 오른쪽으로 읽는 언어에서는 문제가 없지만, 아랍어(오른쪽에서 왼쪽)나 세로쓰기 언어에서는 “왼쪽 여백”이 실제로는 “문장이 시작하는 쪽 여백”이어야 의미가 통합니다.
논리 속성(logical properties)은 물리적 방향 대신 글의 흐름 축을 기준으로 삼습니다.
- inline 축: 한 줄의 글자가 흘러가는 방향(가로쓰기 기준 가로)
- block 축: 줄이 쌓이는 방향(가로쓰기 기준 세로)
writing-mode나 direction이 바뀌면 inline/block 축의 실제 화면 방향도 함께 바뀝니다. 이 사이트는 계속 가로쓰기·왼쪽에서 오른쪽으로 읽는 한국어를 쓰지만, 논리 속성으로 옮겨 두면 나중에 다국어 지원을 붙일 때 CSS를 다시 쓸 필요가 없습니다.
물리 속성 → 논리 속성 매핑
| 물리 속성 | 논리 속성 | 축 |
|---|---|---|
margin-left / margin-right | margin-inline-start / margin-inline-end | inline |
margin-top / margin-bottom | margin-block-start / margin-block-end | block |
padding-left + padding-right | padding-inline (축약형) | inline |
padding-top + padding-bottom | padding-block (축약형) | block |
border-bottom | border-block-end | block |
width / height | inline-size / block-size | inline / block |
left / right(포지셔닝) | inset-inline-start / inset-inline-end | inline |
text-align: left | text-align: start | inline |
margin-inline처럼 시작·끝 값이 같으면 축약형 하나로 씁니다. 값이 다르면 margin-inline: var(--space-4) var(--space-8);처럼 시작 값, 끝 값 순서로 씁니다.
흔한 오해
가로쓰기 한국어 사이트라 “굳이 바꿀 필요가 있나”라는 의문이 자연스럽습니다. 두 가지 실무 이유가 있습니다. 첫째, 다국어 지원을 나중에 추가해도 레이아웃 속성을 다시 쓰지 않아도 됩니다. 둘째, 컨테이너 쿼리·서브그리드 등 최근 레이아웃 사양은 논리 속성을 기본 단위로 문서화하므로, 나머지 코드와 용어를 맞추는 편이 유지보수에 유리합니다.
실습
1. 파일 열기
portfolio/css/styles.css를 엽니다. base 레이어부터 시작해서 components, utilities 순서로 물리 속성을 찾습니다.
2. 코드 작성
base 레이어의 기본 여백부터 바꿉니다.
/* portfolio/css/styles.css */
@layer base {
body {
margin-block: 0;
padding-inline: 0;
color: var(--color-text);
background-color: var(--color-bg);
}
.container {
inline-size: min(100% - var(--space-8), var(--container-max));
margin-inline: auto;
}
}components 레이어의 헤더·히어로·카드를 바꿉니다.
/* portfolio/css/styles.css */
@layer components {
.site-header {
block-size: var(--header-height);
border-block-end: 1px solid var(--color-border);
padding-inline: var(--space-6);
}
#mobile-menu {
/* inset: var(--header-height) var(--space-4) auto var(--space-4); 였던 물리 속성을 논리 속성으로 */
inset-block-start: var(--header-height);
inset-inline: var(--space-4);
}
.hero {
padding-block: var(--space-16);
text-align: center;
}
.hero h1 {
font-size: var(--text-3xl);
}
.about img {
inline-size: 12rem;
}
.project-card h2 {
padding-inline: var(--space-4);
margin-block-start: var(--space-4);
}
.project-card p {
padding-inline: var(--space-4);
}
.project-card .tags {
padding-inline: var(--space-4);
}
.field input,
.field select,
.field textarea {
inline-size: 100%;
padding-block: var(--space-3);
padding-inline: var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius);
}
.field input:invalid:not(:placeholder-shown) {
border-color: var(--color-accent);
}
}utilities 레이어의 여백 유틸리티도 축 이름으로 다시 짓습니다.
/* portfolio/css/styles.css */
@layer utilities {
.mt-8 {
margin-block-start: var(--space-8);
}
.px-4 {
padding-inline: var(--space-4);
}
}3. 실행
브라우저에서 portfolio/index.html, projects.html, contact.html을 각각 새로고침합니다. 별도 명령은 없습니다.
4. 확인
- 개발자 도구
Elements탭에서.project-card를 선택하면computed패널에margin-inline-start,padding-inline같은 논리 속성 이름이 그대로 보입니다. - 화면에 보이는 여백·정렬은 08편과 완전히 같습니다. 논리 속성 치환은 값을 바꾸는 작업이 아니라 이름을 바꾸는 작업이므로 레이아웃 차이가 없어야 정상입니다.
- 개발자 도구 콘솔에서
document.documentElement.dir = 'rtl'을 입력해 봅니다. 헤더 로고와 내비, 카드 여백이 좌우로 뒤집혀 따라옵니다. 물리 속성이었다면 이 상태에서 여백이 반대쪽에 남아 어색해집니다.
직접 해보기
.faq details의padding-block은 그대로 두고,.project-card button[data-open-project]의margin-top: auto를margin-block-start: auto로 바꿔 보세요..site-header의border-bottom이 이미border-block-end로 바뀌었는지 확인하고,.site-nav의gap처럼 애초에 물리 속성이 필요 없는 속성(간격을gap으로 주는 경우)은 왜 바꿀 필요가 없는지 설명해 보세요.
답 보기
.project-card button[data-open-project] {
margin: var(--space-4);
margin-block-start: auto;
}gap은 처음부터 방향이 아니라 아이템 사이의 간격만 지정하는 속성이라 좌우·상하 구분이 없다. 그래서 flex/grid의 gap은 물리 속성 → 논리 속성 치환 대상이 아니다.
자주 하는 실수
| 증상 | 원인 | 고치는 법 |
|---|---|---|
width를 inline-size로 바꿨더니 flex-basis와 충돌한다 | Flex 컨테이너 안에서 inline-size와 flex-basis가 동시에 크기를 결정하려 한다 | Flex 아이템은 기존처럼 flex 축약형을 쓰고, inline-size는 최댓값 제한(max-inline-size) 용도로만 쓴다 |
text-align: start가 오래된 브라우저에서 left처럼 안 보인다 | 걱정할 필요 없음 — start는 2015년 이후 모든 주요 브라우저가 지원한다 | 별도 폴백 불필요 |
padding-inline: 1rem 2rem을 padding-inline-start/-end 두 줄로 나눠 써서 코드가 길어졌다 | 축약형 문법을 모르고 물리 속성 두 줄 습관을 그대로 옮겼다 | 시작·끝 값이 다르면 padding-inline: 시작값 끝값; 한 줄로 축약한다 |
inset-inline-start를 안 써서 position: absolute 요소가 RTL에서 안 뒤집힌다 | left/right 포지셔닝 값을 논리 속성으로 안 바꿈 | left → inset-inline-start, right → inset-inline-end로 바꾼다 |