안녕하세요! 프론트엔드 개발자를 향해 달려가고 계신 여러분, 오늘도 진심으로 환영합니다. 저는 여러분의 CSS 스킬업을 도와드릴 강사입니다.
오늘 우리가 함께 정복할 주제는 바로 '다단 레이아웃 (Multiple-column layout)'입니다. 흔히 신문이나 잡지를 보면 글이 여러 단(컬럼)으로 나뉘어 있는 것을 볼 수 있죠? 웹에서도 그런 멋진 텍스트 배치를 아주 간단하게 구현할 수 있게 해주는 마법 같은 CSS 기능이랍니다.
공식 문서가 영어로 되어 있어서 조금 딱딱하게 느껴지셨을 텐데, 제가 하나도 빠짐없이 친절하게 번역해 드리면서 실무에서 자주 쓰이는 '진짜 꿀팁'들까지 팍팍 얹어드릴게요. 자, 그럼 시작해 볼까요?
다단 레이아웃(Multiple-column layout) 명세는 신문에서 흔히 볼 수 있는 것처럼 콘텐츠를 여러 단(column)으로 나누어 배치할 수 있는 방법을 제공합니다. 이 글에서는 이 기능을 어떻게 사용하는지 자세히 설명해 드립니다.
| 선행 조건 (Prerequisites): | HTML 기초 (HTML로 콘텐츠 구조화하기 공부하기), 그리고 CSS 작동 원리에 대한 이해 (CSS 스타일링 기초 공부하기). |
| 학습 목표 (Objective): | 신문에서 볼 수 있는 것과 같은 다단 레이아웃을 웹 페이지에 만드는 방법을 배웁니다. |
다단 레이아웃 — 현업에서는 줄여서 멀티콜(multicol)이라고도 많이 부릅니다 — 을 어떻게 사용하는지 알아봅시다. 멀티콜 시작 파일(multicol starting point file)을 다운로드한 다음, 적절한 위치에 CSS를 추가하면서 따라 해보실 수 있습니다. 이 섹션의 맨 아래에서 최종 코드가 어떻게 보여야 하는지 예제를 확인할 수 있습니다.
우리의 시작 파일에는 아주 단순한 HTML이 들어있습니다. container라는 클래스를 가진 래퍼(wrapper) <div>가 있고, 그 안에는 하나의 제목(heading)과 몇 개의 단락(paragraphs)이 들어있죠.
container 클래스를 가진 <div>가 바로 우리의 멀티콜 컨테이너가 될 것입니다. 다단 레이아웃을 활성화하려면 두 가지 속성 중 하나를 사용해야 합니다: 바로 column-count 또는 column-width입니다.
먼저 column-count 속성은 숫자 값을 받아서 정확히 그 숫자만큼의 단(컬럼)을 만들어냅니다. 여러분의 스타일시트에 아래 CSS를 추가하고 페이지를 새로고침 해보세요. 짠! 텍스트가 3단으로 나뉘는 것을 볼 수 있습니다.
.container {
column-count: 3;
}
이렇게 만들어진 단들은 유연한(flexible) 너비를 가집니다. 즉, 브라우저가 화면 크기에 맞춰 각 단에 얼마만큼의 공간을 할당할지 스스로 계산해 냅니다.
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font:
0.9em/1.2 "Helvetica",
"Arial",
sans-serif;
}
<div class="container">
<h1>Simple multicol example</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at
ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer
ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur
vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus.
Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus
sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus.
Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis,
eget fermentum sapien.
</p>
<p>
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies
lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>
</div>
MDN Playground에서 직접 예제 코드 만져보기
이번에는 CSS를 수정해서 column-width를 사용해 볼까요?
.container {
column-width: 200px;
}
이제 브라우저는 여러분이 지정한 200px이라는 너비를 바탕으로, 화면에 들어갈 수 있는 최대한 많은 개수의 단을 알아서 만들어 냅니다. 그리고 남는 여분의 공간은 기존 단들에게 골고루 나누어주죠. 이는 다시 말해, 컨테이너의 너비가 200px로 딱 나누어떨어지지 않는 이상 여러분이 지정한 너비(200px)와 완벽히 똑같은 너비를 가진 단이 만들어지지는 않는다는 뜻입니다. (지정한 너비는 일종의 '최소 너비'처럼 작동합니다.)
💡 강사님의 실무 팁!
실무에서 반응형 웹(Responsive Web)을 만들 때column-width는 정말 꿀 같은 속성입니다! 미디어 쿼리(Media Query)를 복잡하게 쓰지 않아도, 브라우저 창을 줄이면 알아서 3단 -> 2단 -> 1단으로 스르륵 변하거든요. 텍스트가 많은 블로그나 아티클 페이지를 만들 때 꼭 써먹어 보세요.
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font:
0.9em/1.2 "Helvetica",
"Arial",
sans-serif;
}
<div class="container">
<h1>Simple multicol example</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at
ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer
ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur
vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus.
Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus
sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus.
Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis,
eget fermentum sapien.
</p>
<p>
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies
lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>
</div>
MDN Playground에서 직접 예제 코드 만져보기
명심해야 할 점이 있습니다. 멀티콜(multicol)에 의해 쪼개진 각각의 단(column)들은 개별적으로 스타일링할 수 없습니다. 즉, 첫 번째 단만 두 번째 단보다 더 넓게 만든다거나, 특정 단 하나에만 다른 배경색이나 글자색을 주는 방법은 없습니다. (단은 실제 DOM 요소가 아니기 때문이죠!)
대신, 단들이 어떻게 보일지 변경할 수 있는 두 가지 기회가 있습니다:
column-gap 속성을 사용해 단과 단 사이의 간격(여백) 크기를 변경할 수 있습니다.column-rule 속성을 사용해 단과 단 사이에 구분선(규칙선)을 추가할 수 있습니다.위의 예제에 이어서, column-gap 속성을 추가해 단 사이의 간격을 조절해 보세요. 어떤 길이 단위(px, em, rem 등)든 자유롭게 사용할 수 있습니다.
그런 다음 column-rule을 이용해 단 사이에 선을 그어보세요. 이전 레슨에서 배운 border(테두리) 속성과 매우 비슷하게 작동합니다. 사실 column-rule은 column-rule-color, column-rule-style, 그리고 column-rule-width를 한 번에 쓰는 축약형(shorthand) 속성이며, border와 똑같은 값들을 허용합니다.
.container {
column-width: 250px;
column-gap: 20px;
column-rule: 4px dotted rgb(79 185 227);
}
한번 다양한 스타일과 색상을 넣어가며 자유롭게 테스트해 보세요!
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font:
0.9em/1.2 "Helvetica",
"Arial",
sans-serif;
}
<div class="container">
<h1>Simple multicol example</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at
ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer
ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur
vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus.
Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus
sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus.
Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis,
eget fermentum sapien.
</p>
<p>
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies
lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>
</div>
MDN Playground에서 직접 예제 코드 만져보기
여기서 한 가지 알아두셔야 할 점은, 이 구분선(rule) 자체가 어떤 너비 공간을 차지하지는 않는다는 것입니다. 이 선은 여러분이 column-gap으로 만든 여백의 정중앙에 겹쳐서 그려질 뿐입니다. 만약 선 양옆으로 더 많은 공간을 확보하고 싶다면, column-gap의 크기를 더 늘려주어야 합니다.
다단 레이아웃 내부에 있는 특정 요소를 모든 단을 가로지르도록(span across) 뻗게 만들 수도 있습니다. 이렇게 하면 확장된 요소가 나타나는 지점에서 콘텐츠가 뚝 끊기고(breaks), 해당 요소 아래에서부터 새로운 단들이 다시 시작됩니다. 어떤 요소를 모든 단에 걸쳐 확장되게 하려면, column-span 속성에 all이라는 값을 지정해 주면 됩니다.
참고:
일부 단에만 걸치도록 확장하는 것은 불가능합니다. 이 속성이 가질 수 있는 값은 오직none(기본값) 또는all뿐입니다.
💡 강사님의 실무 팁!
기사를 읽다 보면 중간에 아주 큰 글씨로 강조된 핵심 문장이나, 넓게 뻗은 소제목(Subheading)을 보신 적 있죠?column-span: all;은 바로 그럴 때 씁니다. 신문이나 매거진 스타일의 레이아웃을 짤 때 정말 스타일리시하게 활용할 수 있어요!
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font:
0.9em/1.2 "Helvetica",
"Arial",
sans-serif;
}
.container {
column-count: 3;
column-gap: 20px;
column-rule: 4px dotted rgb(79 185 227);
}
h2 {
column-span: all;
background-color: rgb(79 185 227);
color: white;
padding: 0.5em;
}
<div class="container">
<h1>Simple multicol example</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at
ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer
ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
<h2>Spanning subhead</h2>
<p>
Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae
convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis.
Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue
ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id
ornare felis, eget fermentum sapien.
</p>
<p>
Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies
lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>
</div>
MDN Playground에서 직접 예제 코드 만져보기
다단 레이아웃 내의 콘텐츠는 단편화(fragmented, 쪼개짐)됩니다. 본질적으로 이 동작은 웹 페이지를 인쇄할 때처럼 '페이지가 나뉘는 미디어(paged media)'에서 콘텐츠가 동작하는 방식과 완벽하게 동일합니다. 콘텐츠를 멀티콜 컨테이너로 바꾸면, 콘텐츠는 여러 단으로 조각조각 쪼개집니다. 이렇게 여러 단으로 흐르기 위해서는 콘텐츠가 반드시 끊어져야(break)만 하죠.
그런데 가끔, 이 '끊어짐' 현상이 글을 읽기 몹시 불편하게 만드는 곳에서 발생하기도 합니다. 아래 예제를 보시죠. 멀티콜을 사용해서 일련의 박스 카드들을 배치했습니다. 각 카드 안에는 제목과 텍스트가 들어있죠. 그런데 단이 나뉘는 지점이 하필이면 카드의 제목과 텍스트 사이를 가로지르게 되면, 제목과 텍스트가 완전히 딴 동네로 분리되어 버리는 참사가 발생합니다!
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font:
0.9em/1.2 "Helvetica",
"Arial",
sans-serif;
}
<div class="container">
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
</div>
.container {
column-width: 250px;
column-gap: 20px;
}
.card {
background-color: rgb(207 232 220);
border: 2px solid rgb(79 185 227);
padding: 10px;
margin-bottom: 1em;
}
MDN Playground에서 직접 예제 코드 만져보기
이런 불상사를 막기 위해 우리는 CSS 단편화(CSS Fragmentation) 명세에서 제공하는 속성들을 사용할 수 있습니다. 이 명세는 다단 레이아웃이나 인쇄 환경에서 콘텐츠가 끊어지는 방식을 제어할 수 있는 아주 유용한 속성들을 제공합니다.
예를 들어, .card 클래스 규칙에 break-inside 속성을 추가하고 값을 avoid로 설정해 보세요. .card는 제목과 텍스트를 함께 감싸고 있는 컨테이너이므로, 이 안에서는 내용이 둘로 쪼개지는(fragmented) 것을 막아달라고 브라우저에 요청하는 것입니다.
.card {
break-inside: avoid;
background-color: rgb(207 232 220);
border: 2px solid rgb(79 185 227);
padding: 10px;
margin-bottom: 1em;
}
이 속성을 추가하면, 이제 박스들이 하나의 덩어리로 온전히 유지됩니다. 더 이상 이리저리 찢어져서 다음 단으로 넘어가는 일은 발생하지 않게 되죠!
💡 강사님의 특급 실무 팁!
여러분, 혹시 핀터레스트(Pinterest) 같은 지그재그 벽돌형 레이아웃(Masonry Layout)을 만들어 본 적 있으신가요? 보통 자바스크립트나 무거운 외부 라이브러리를 써야 한다고 생각하지만, 방금 배운column-count와break-inside: avoid;단 두 줄이면 CSS만으로 완벽한 Masonry 레이아웃을 구현할 수 있습니다! 실무에서 정말 자주 쓰이는 마법 같은 트릭이니 꼭 기억해 두세요!
body {
width: 90%;
max-width: 900px;
margin: 2em auto;
font:
0.9em/1.2 "Helvetica",
"Arial",
sans-serif;
}
<div class="container">
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
<div class="card">
<h2>I am the heading</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc,
at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula.
</p>
</div>
</div>
.container {
column-width: 250px;
column-gap: 20px;
}
MDN Playground에서 직접 예제 코드 만져보기
수고 많으셨습니다! 이제 여러분은 여러분이 구축하고자 하는 디자인에 맞는 레이아웃 도구를 선택할 때, 또 하나의 든든한 무기인 다단 레이아웃(multiple-column layout)의 기본적인 기능들을 자유자재로 다루실 수 있게 되었습니다.
기여하는 방법 알아보기 (Learn how to contribute)
이 페이지의 마지막 수정일은 Nov 7, 2025 이며, MDN 기여자들(MDN contributors)에 의해 작성되었습니다.
멀티콜은 텍스트가 중심이 되는 서비스에서 정말 빛을 발하는 레이아웃 기법입니다. 궁금한 점이 있다면 언제든 편하게 물어보세요! 다음 강의에서 뵙겠습니다.