02 — Display
display는 한 속성처럼 보이지만 사실 두 개의 차원이다 — 외부 흐름(부모와 어떻게 어울리는가)과 내부 흐름(자식을 어떻게 배치하는가). CSS Display Module Level 3가 이를 두 단어로 쪼개 표준화했고, 모던 CSS는 이 두 축을 따로 다룬다.
Why — 왜 display 하나에 모든 게 걸려 있나
CSS의 모든 레이아웃은 display 값으로 분기한다.
- 같은 마크업이
display: block이면 세로로,flex면 가로로,grid면 2D로 쌓인다. - 같은
<span>이display: inline이면width를 못 받고,inline-block이면 받는다. - 부모가
flex인 순간 자식의margin: auto가 센터링 마법이 된다. display: contents는 박스 자체를 없애고 자식만 남긴다.display: flow-root는 새 BFC를 만들어 clearfix를 폐기시킨다.
display를 모르면 다른 어떤 CSS 속성도 어떤 컨텍스트에서 동작하는지 예측할 수 없다.
How — 외부 흐름과 내부 흐름의 두 차원
CSS Display 3 명세는 display를 <display-outside> <display-inside> 의 두 키워드로 분해한다.
display: block flow; /* = block */
display: inline flow; /* = inline */
display: block flex; /* = flex */
display: inline flex; /* = inline-flex */
display: block grid; /* = grid */
display: block flow-root; /* = flow-root */| 차원 | 의미 | 값 |
|---|---|---|
<display-outside> | 이 박스가 부모 흐름에서 어떻게 흐르는가 | block, inline, run-in |
<display-inside> | 이 박스의 자식들이 어떻게 배치되는가 | flow, flow-root, flex, grid, table, ruby |
대부분의 브라우저가 두 단어 문법도 지원하지만, 실무에서는 한 단어 별칭(flex, grid, inline-block 등)을 더 자주 쓴다. 중요한 건 두 차원이 독립이라는 개념적 모델이다.
What — 값 전체 카탈로그
1) 외부 흐름 — 부모에 어떻게 흐르나
| 값 | 줄바꿈 | width/height 받음 | 비고 |
|---|---|---|---|
block | O (앞뒤 줄바꿈) | O | <div>, <p>, <section> 기본 |
inline | X (텍스트처럼 흐름) | X | <span>, <a> 기본 |
inline-block | X | O | inline처럼 흐르되 박스 모델은 block |
none | — | — | 박스 자체가 생성되지 않음 (DOM에는 있음) |
contents | — | — | 박스 자체는 사라지고 자식이 부모로 승격 |
2) 내부 흐름 — 자식을 어떻게 배치하나
| 값 | 자식 배치 알고리즘 | 새 BFC 생성 | 비고 |
|---|---|---|---|
flow (기본) | normal flow (위→아래 또는 왼→오) | X | 기본값 |
flow-root | normal flow + 새 BFC | O | 모던 clearfix |
flex | flex layout | O | 1차원 |
grid | grid layout | O | 2차원 |
table | table layout | O | <table> 호환 |
ruby | ruby annotation | — | 동아시아 텍스트 주석 |
3) 한 단어 별칭 (실무에서 자주 쓰는 것)
display: block; /* = block flow */
display: inline-block; /* = inline flow-root */ /* ← 사실 inline-block은 내부적으로 BFC */
display: flex; /* = block flex */
display: inline-flex; /* = inline flex */
display: grid; /* = block grid */
display: inline-grid; /* = inline grid */
display: flow-root; /* = block flow-root */4) display: contents — 박스를 지운다
<ul style="display: flex; gap: 8px;">
<li style="display: contents;">
<a>Home</a>
<a>About</a>
</li>
</ul><li>는 시맨틱으로 존재하지만 박스는 없다. <a> 두 개가 <ul>의 flex 자식이 된다. 시맨틱 마크업과 시각 레이아웃을 분리하는 강력한 도구.
주의: 일부 브라우저(특히 Safari 구버전)에서 접근성 트리 처리가 불완전했다 — 2024년 이후로는 대부분 정상.
5) display: flow-root — 모던 clearfix
.parent { display: flow-root; }
/* 자식 float를 자동으로 감싼다. clearfix hack 불필요. */과거의 .clearfix::after { content: ""; display: block; clear: both; } 6줄 hack을 한 줄로 대체한다. 2018년 이후 Baseline.
What-if — 잘못 쓰면
1) <span>에 width를 주려는 시도
span { width: 200px; } /* 무시됨 */해결: display: inline-block 또는 block 또는 flex item.
2) display: none을 트랜지션으로 부드럽게 사라지게 하려는 시도
none은 박스를 제거하므로 트랜지션 대상이 아니다. 2023년 이후 transition-behavior: allow-discrete + @starting-style로 가능해졌지만 별도 패턴.
.modal {
transition: opacity 0.2s, display 0.2s allow-discrete;
}
.modal[hidden] { display: none; opacity: 0; }3) display: contents로 키보드 포커스가 깨지는 경우
구버전 Safari·Firefox에서 display: contents인 요소가 가진 시맨틱 역할(예: <button>)이 무시되는 버그가 있었다. 2023년 이후 대부분 해결되었지만 interactive 요소에는 신중히 적용.
4) display: flex를 줬는데 자식이 줄바꿈 안 함
flex는 기본 flex-wrap: nowrap. 자식이 부모를 뚫는다.
.row { display: flex; flex-wrap: wrap; gap: 16px; }5) display: inline-block의 공백 4px
<div style="display: inline-block">A</div><div style="display: inline-block">B</div>HTML 줄바꿈이 space character로 렌더링되어 박스 사이에 4px가 생긴다. 해결: 부모 font-size: 0, 또는 더 나은 답은 display: flex.
Insight — flow-root는 16년 묵은 clearfix를 폐기시킨 작은 영웅
2002년 — Big John이 “How To Clear Floats Without Structural Markup” 라는 글에서
::after { content: ""; clear: both; }패턴을 정립했다.이후 16년간 모든 CSS 프레임워크는
.clearfix유틸리티 클래스를 갖고 있었다.2018년 —
display: flow-root가 Chrome 58·Firefox 53·Safari TP에 도착했고, Edge가 따라오면서 Baseline에 들어갔다. 한 줄로 끝났다.
flow-root의 핵심은 “새 BFC를 명시적으로 만든다” 는 한 가지다. 과거에는 overflow: hidden이 부작용으로 BFC를 만들어서 clearfix로 쓰였다 — 하지만 overflow: hidden은 그림자나 툴팁이 잘리는 부작용이 있었다. flow-root는 오직 BFC만 만드는 의도가 명확한 속성이다.
CSS Display Module Level 3는 박스 모델 자체의 정의를 다시 썼다 — 박스의 외부와 내부는 독립적이다. 이게 왜 중요한가? 미래의 layout 모드가 추가될 때 (masonry, subgrid, etc.) 외부/내부 차원이 독립이면 조합만으로 확장된다. 실제로 2024년 display: masonry가 제안될 때도 <display-inside> 값으로 추가되는 방향으로 논의되고 있다.
CSS는 속성을 분해해서 진화한다 — font가 font-family + font-size + font-weight로, background가 background-image + background-position으로 분해되었듯, display도 두 차원으로 분해되어 미래를 준비한다.
요약 + Mermaid
display는 외부 흐름 × 내부 흐름의 두 차원.flow-root로 모던 BFC → clearfix 폐기.contents로 박스 제거 → 시맨틱과 시각 분리.flex/grid는 둘 다 새 BFC를 자동 생성.- inline 요소에
width/height는 무시 —inline-block필요. - flex 기본
flex-wrap: nowrap— 줄바꿈 원하면 명시.