안녕하세요! 프론트엔드 개발 강사입니다. 이번에 가져오신 내용은 CSS 레이아웃의 가장 기본 중의 기본이자 핵심인 블록(Block)과 인라인(Inline) 레이아웃에 대한 문서군요!
"왜 이 태그는 줄바꿈이 되고 저 태그는 옆으로 붙지?", "왜 span 태그에는 위아래 마진이 안 먹히지?" 웹 개발을 처음 시작할 때 누구나 한 번쯤 겪는 이 답답함이 바로 이 개념을 완벽히 이해하지 못해서 생기는 거랍니다. 영문 문서라 조금 딱딱하셨을 텐데, 제가 실무 팁을 곁들여서 아주 쉽고 명쾌하게 구어체로 전부 번역해 드릴게요. 같이 차근차근 읽어볼까요? 😊
이번 가이드에서는 블록(Block) 요소와 인라인(Inline) 요소가 일반 흐름(Normal flow) 안에 있을 때 어떻게 행동하는지 그 기본 원리를 알아볼 거예요.
💡 강사의 부연 설명: "일반 흐름(Normal flow)이 뭔가요?"
쉽게 말해서position: absolute나float같은 속성으로 요소를 공중에 띄우거나 위치를 강제로 바꾸지 않고, 브라우저가 HTML 코드를 읽어 내려가는 순서대로 위에서 아래로, 좌에서 우로 차곡차곡 자연스럽게 쌓이는 상태를 말합니다. 가장 기본적이고 평화로운(?) 상태죠.
일반 흐름(Normal Flow)은 CSS 2.1 사양서(CSS 2.1 specification)에 정의되어 있습니다. 사양서에 따르면, 일반 흐름 속에 있는 어떤 박스(요소)든 반드시 특정한 서식 컨텍스트(formatting context)의 일부가 됩니다. 이 박스들은 블록(block)이 되거나 인라인(inline)이 될 수는 있지만, 동시에 두 가지가 될 수는 없습니다. 우리는 블록 레벨 박스가 블록 서식 컨텍스트(block formatting context)에 참여하고, 인라인 레벨 박스가 인라인 서식 컨텍스트(inline formatting context)에 참여한다고 표현합니다.
블록 또는 인라인 서식 컨텍스트를 가진 요소들의 행동 양식 역시 이 사양서에 정의되어 있습니다. 블록 서식 컨텍스트를 가진 요소들에 대해 사양서는 이렇게 말합니다:
"블록 서식 컨텍스트에서, 박스들은 컨테이닝 블록(부모 요소)의 맨 위에서부터 시작하여 차례대로 하나씩 세로로 배치됩니다. 두 형제 박스 사이의 수직(위아래) 거리는 'margin' 속성에 의해 결정됩니다. 또한 블록 서식 컨텍스트 안에서 서로 인접한 블록 레벨 박스들 사이의 수직 마진은 서로 병합(collapse)됩니다.
블록 서식 컨텍스트에서 각 박스의 왼쪽 바깥쪽 가장자리(outer edge)는 컨테이닝 블록의 왼쪽 가장자리와 맞닿습니다 (오른쪽에서 왼쪽으로 읽는 언어 설정에서는 오른쪽 가장자리가 맞닿습니다)." - 9.4.1
인라인 서식 컨텍스트를 가진 요소들에 대해서는 이렇게 말합니다:
"인라인 서식 컨텍스트에서, 박스들은 컨테이닝 블록의 맨 위에서부터 시작하여 차례대로 하나씩 가로로 배치됩니다. 이 박스들 사이의 수평(좌우) 마진, 테두리(border), 패딩(padding)은 모두 정상적으로 적용됩니다. 박스들은 수직 방향으로 여러 가지 방식으로 정렬될 수 있습니다. 위나 아래 끝선을 맞추거나, 박스 내부 텍스트의 베이스라인(baseline, 글자의 아랫부분 기준선)을 맞출 수도 있습니다. 한 줄을 이루는 박스들을 모두 포함하는 가상의 직사각형 영역을 라인 박스(line box)라고 부릅니다." - 9.4.2
참고로 CSS 2.1 사양서는 문서를 '가로 방향, 위에서 아래로' 읽는 가로 쓰기 모드(horizontal writing mode)를 기준으로 설명하고 있습니다. (예를 들어 '블록 박스 사이의 수직 거리'를 설명하는 것처럼요). 세로 쓰기 모드(vertical writing mode)에서 작업할 때도 블록과 인라인 요소의 기본 원리는 똑같이 적용됩니다. 이에 대한 자세한 내용은 흐름 레이아웃과 쓰기 모드(Flow layout and writing modes) 가이드에서 다룹니다.
영어처럼 가로로 글을 쓰는 쓰기 모드(horizontal writing mode)에서 블록 요소들은 하나 아래에 또 하나가 놓이는 식으로 세로로(vertically) 배치됩니다.

반대로 세로 쓰기 모드(vertical writing mode)에서는 블록 요소들이 가로로 나란히 배치될 것입니다.

이 가이드에서는 영어(한국어도 마찬가지죠!)를 기준으로, 즉 가로 쓰기 모드를 기준으로 설명하겠습니다. 하지만 여기서 설명하는 모든 규칙은 문서가 세로 쓰기 모드일 때도 동일한 논리로 작동합니다.
사양서에 정의된 대로, 두 블록 박스 사이의 간격을 만들어내는 것은 바로 마진(margins)입니다. 테두리(border)를 추가한 두 개의 단락(<p>) 요소 레이아웃을 통해 이 사실을 직접 눈으로 확인할 수 있어요. 브라우저의 기본 스타일시트는 각 단락 요소의 위아래에 마진(margin)을 추가해서 단락 간의 간격을 자동으로 만들어냅니다.
(MDN Playground에서 실행해보기)
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
}
만약 이 단락(<p>) 요소들의 마진을 0으로 설정하면, 두 요소의 테두리가 딱 맞닿게 됩니다. (마진이 사라졌기 때문이죠!)
(MDN Playground에서 실행해보기)
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
margin: 0;
}
👨🏫 강사의 실무 팁! "Block 요소의 성질"
블록 요소의 가장 큰 특징은 "부모 요소의 가로 너비(100%)를 혼자 다 차지한다"는 것입니다. 그래서 블록 요소 다음에는 무조건 줄바꿈이 일어나는 거죠.<div>,<p>,<h1>~<h6>,<ul>,<li>,<section>같은 태그들이 대표적인 블록 요소랍니다.
기본적으로 블록 요소들은 인라인 방향(가로 방향)으로 가능한 모든 공간을 차지(consume)하려고 합니다. 그래서 우리의 단락(<p>) 요소들이 옆으로 쫙 퍼져서 부모 컨테이너(containing block) 안에서 최대한 크게 자리를 잡은 것입니다.
설령 우리가 블록 요소에 고정된 width(너비)를 줘서 옆에 다른 요소가 들어올 공간이 충분히 남게 하더라도, 블록 요소들은 여전히 나란히 붙지 않고 위아래로 차곡차곡 레이아웃됩니다. 각각의 블록 요소는 부모 컨테이너의 시작 지점(가로 쓰기 모드에서는 왼쪽 끝)에서부터 항상 새롭게 시작합니다.
(MDN Playground에서 실행해보기)
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
width: 40%; /* 너비를 40%로 줄여서 옆에 공간이 남아돌지만, 여전히 줄바꿈이 됩니다! */
}
사양서는 블록 요소 사이의 마진이 서로 병합(collapse)된다고 설명합니다. 이게 무슨 말이냐면, 아래쪽 마진(bottom margin)을 가진 어떤 요소 바로 밑에 위쪽 마진(top margin)을 가진 다른 요소가 이어질 때, 이 두 마진의 크기를 단순히 더하는 것이 아니라는 뜻입니다. 대신 두 마진이 하나로 합쳐지며(collapse), 결과적으로 둘 중 더 큰 마진의 크기 하나로 간격이 결정됩니다.
아래 예제에서, 단락(<p>)들은 위쪽 마진(top margin)이 20px이고 아래쪽 마진(bottom margin)이 40px입니다. 두 단락 사이의 간격은 20 + 40인 60px이 될 것 같지만, 실제로는 40px이 됩니다. 왜냐하면 두 번째 단락의 더 작은 위쪽 마진(20px)이 첫 번째 단락의 더 큰 아래쪽 마진(40px) 속으로 먹혀들어 가면서(collapse) 큰 값 하나만 남았기 때문입니다.
💡 강사의 실무 팁! "마진 병합, 당황하지 마세요"
초보 시절 레이아웃을 짤 때 제일 많이 당황하는 부분이 바로 이 마진 병합(Margin Collapse)입니다. "어? 왜 마진을 줬는데 공간이 안 늘어나지?" 싶을 땐 십중팔구 이 녀석 때문이에요. 상하 마진(Top, Bottom)에서만 발생하고 좌우 마진(Left, Right)에서는 발생하지 않는다는 점도 꼭 기억해 두세요!
(MDN Playground에서 실행해보기)
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
margin: 20px 0 40px 0; /* 상단 20px, 하단 40px */
}
마진 병합에 대해 더 깊이 알고 싶다면 마진 병합 마스터하기(Mastering Margin Collapsing) 문서를 읽어보세요.
📝 참고:
만약 마진이 병합되고 있는 건지 아닌지 확신이 서지 않는다면, 브라우저 개발자 도구(DevTools)에서 박스 모델(Box Model) 탭을 확인해 보세요. 여기에 실제 적용된 마진 크기가 숫자로 표시되기 때문에 무슨 일이 일어나고 있는지 파악하는 데 큰 도움이 됩니다.
인라인 요소(Inline elements)는 해당 쓰기 모드에서 문장(글자)이 흘러가는 방향을 따라 옆으로 하나씩 나란히 배치됩니다. 우리가 보통 인라인 요소를 다룰 때 '얘네들도 박스를 가지고 있나?'라고 잘 생각하지 않지만, CSS의 모든 것은 박스(box)로 이루어져 있으므로 인라인 요소 역시 엄연한 박스입니다. 이 인라인 박스들은 하나 옆에 또 하나가 차례대로 배열됩니다. 만약 부모 컨테이너의 가로 공간이 부족해서 박스들이 다 들어가지 못한다면, 박스는 끊어지면서(break) 새로운 줄로 넘어가게 됩니다. 이렇게 만들어진 텍스트의 각 줄을 라인 박스(line box)라고 부릅니다.
👨🏫 강사의 실무 팁! "Inline 요소의 성질"
인라인 요소는 오직 "자기가 품고 있는 내용물(글자, 이미지 등)의 크기"만큼만 공간을 차지합니다. 대표적으로<span>,<a>,<strong>,<img>같은 태그들이 있죠. 주의할 점은 순수한 인라인 요소에는width,height, 상하margin, 상하padding값들이 레이아웃을 밀어내는 데 정상적으로 작동하지 않는다는 것입니다! (좌우 여백은 적용됩니다)
다음 예제에서는 단락(<p>) 내부의 텍스트가 줄바꿈이 될 때, 그 안에 포함된 <strong> 요소 하나 때문에 총 3개의 인라인 박스가 쪼개지며 생성되는 모습을 볼 수 있습니다.
(MDN Playground에서 실행해보기)
<p>
Before that night—<strong>a memorable night</strong>, as it was to
prove—hundreds of millions of people had watched the rising smoke-wreaths of
their fires without drawing any special inspiration from the fact.
</p>
위 코드에서 <strong> 태그 앞에 있는 일반 글자들("Before that night—")과 </strong> 태그 뒤에 있는 일반 글자들을 감싸고 있는 가상의 박스를 익명 박스(anonymous boxes)라고 부릅니다. 브라우저가 화면의 모든 내용을 어떻게든 박스로 감싸기 위해 스스로 끼워 넣은 박스인데, 우리가 CSS 선택자로 직접 콕 집어서 디자인할 수는 없는 박스죠.
이러한 인라인 요소들이 이루는 한 줄, 즉 라인 박스(line box)의 수직 방향 높이(영어 환경에서는 height)는 그 줄 안에 들어있는 가장 키가 큰 박스에 의해 결정됩니다. 아래 예제를 보실까요? <strong> 요소의 글자 크기(font-size)를 300%로 키웠습니다. 이 엄청나게 커진 <strong> 요소의 내용이 줄바꿈 되어 두 줄(two lines)에 걸쳐 표시되고 있기 때문에, 이제 그 거대한 텍스트의 높이가 이 두 줄의 라인 박스 높이 전체를 결정하게(늘려버리게) 됩니다.
(MDN Playground에서 실행해보기)
<p>
Before that night—<strong>a memorable night</strong>, as it was to
prove—hundreds of millions of people had watched the rising smoke-wreaths of
their fires without drawing any special inspiration from the fact.
</p>
strong {
font-size: 300%;
}
블록 박스와 인라인 박스가 어떻게 동작하는지에 대해 더 깊이 알고 싶다면, 시각적 서식 모델(visual formatting model) 가이드를 참고해 보세요.
CSS2.1에 있던 규칙들 외에도, 새로운 CSS 버전들은 블록과 인라인 박스의 동작을 더 구체적으로 설명하고 있습니다. display 속성은 어떤 박스 자체의 행동과, 그 박스 내부에 있는 자식 박스들의 행동 방식을 정의합니다. CSS Display Model Level 3 사양서를 보면 display 속성이 박스와 그 박스가 생성하는 내부 박스들의 동작을 어떻게 바꾸는지 더 자세히 알 수 있습니다.
어떤 요소의 디스플레이(display) 타입은 크게 외부 디스플레이 타입(outer display type)과 내부 디스플레이 타입(inner display type) 두 가지를 동시에 정의합니다.
Flex(플렉스) 레이아웃을 예로 들면 이 개념을 아주 명확하게 볼 수 있습니다. 아래 예제에서 저는 <div> 하나에 display: flex를 주었습니다.
이 Flex 컨테이너는 밖에서 볼 때는 마치 블록(block) 요소처럼 행동합니다. 새로운 줄에서 시작하고 부모의 가로(inline) 공간을 모두 차지해 버리죠. 이것이 바로 외부 디스플레이 타입(outer display type)이 block이기 때문입니다.
하지만 이 컨테이너 안에 들어있는 자식 요소(Flex items)들은 더 이상 일반적인 블록/인라인 서식 컨텍스트를 따르지 않고, 플렉스 서식 컨텍스트(flex formatting context)에 참여하게 됩니다. 부모가 display: flex를 통해 내부 디스플레이 타입(inner display type)을 flex로 선언했기 때문에, 직계 자식들을 플렉스 규칙에 따라 배치(가로로 나란히 등)하는 것이죠.
(MDN Playground에서 실행해보기)
<div class="container">
<div>Flex Item</div>
<div>Flex Item</div>
<div>
<div>Children</div>
<div>are in</div>
<div>normal flow</div>
</div>
</div>
.container {
display: flex; /* 컨테이너 자체는 바깥에선 block처럼, 내부는 flex로 동작합니다. */
}
.container > * {
border: 1px solid green;
}
여러분이 CSS에서 다루는 모든 박스가 이런 식으로 작동한다고 생각하시면 됩니다.
박스 자신은 '외부 디스플레이 타입'을 가져서 옆에 있는 다른 박스들과 어떻게 어울릴지 결정합니다. 그리고 '내부 디스플레이 타입'을 가져서 자기 품 안에 있는 자식들을 어떻게 줄 세울지 결정하죠.
그리고 그 자식들 역시 또 각자 자신만의 외부/내부 디스플레이 타입을 가지게 됩니다.
위 예제에서 Flex 컨테이너의 직계 자식들은 밖에서 볼 때 '플렉스 레벨 박스(flex level boxes)'가 됩니다. 즉, 부모가 만든 플렉스 서식 컨텍스트의 통제를 받죠. 하지만 이 자식들 자체의 '내부 디스플레이 타입'은 기본값인 flow(일반 흐름)입니다. 그래서 그 자식의 자식들(손자들)은 다시 원래 방식대로 블록 또는 인라인 요소로서 위아래로 차곡차곡 쌓이게 되는 것입니다! (여러분이 다시 display를 바꿔주지 않는 이상 말이죠.)
💡 강사의 중요 팁! "디스플레이의 두 얼굴"
이 외부/내부 디스플레이 개념은 정말 중요합니다.display: flex나display: grid를 쓰더라도, 이 컨테이너 자체의 외부 타입은 여전히block입니다! 그래서 Flex 컨테이너를 두 개 만들면 둘이 나란히 붙지 않고 위아래로 떨어지는 거예요. 만약 Flex 컨테이너 자체도 인라인 요소처럼 옆으로 붙게 만들고 싶다면? 그때 쓰는 게 바로display: inline-flex랍니다! (외부는 inline, 내부는 flex)
브라우저들은 각 HTML 태그의 의미에 가장 잘 어울린다고 생각하는 방식(기본값)으로 요소들을 블록 또는 인라인으로 렌더링합니다.
예를 들어, <strong> 요소는 문장 속 특정 텍스트를 강하게 강조하기 위해 사용되며, 브라우저는 기본적으로 이를 굵은(bold) 글씨의 인라인 요소로 표시합니다. 문장 중간에 들어가는 <strong> 요소가 갑자기 줄바꿈을 일으키는 블록(block) 요소로 표시된다면 문맥상 말이 안 되겠죠.
하지만, 여러분이 만약 모든 <strong> 요소가 블록 박스처럼 행동해서 혼자 한 줄을 다 차지하게 만들고 싶다면, CSS에서 strong { display: block; } 이라고 강제 지정해 주면 됩니다!
CSS로 레이아웃(디스플레이 형태)을 마음대로 바꿀 수 있다는 사실은 아주 중요한 의미를 가집니다. 이는 여러분이 겉모습(디자인)에 얽매이지 않고, 데이터의 의미에 가장 적합한 시맨틱(semantic) HTML 태그를 자유롭게 골라 쓴 다음, CSS로 원하는 겉모습(블록/인라인)으로 포장할 수 있다는 뜻이니까요.
(MDN Playground에서 실행해보기)
<p>
Before that night—<strong>a memorable night</strong>, as it was to
prove—hundreds of millions of people had watched the rising smoke-wreaths of
their fires without drawing any special inspiration from the fact.
</p>
strong {
display: block; /* 인라인 태그인 strong을 강제로 블록으로 만들어 줄바꿈시켰습니다! */
}
이번 가이드에서는 가장 기본적인 상태인 '일반 흐름(normal flow)' 속에서 블록 요소와 인라인 요소가 각각 어떻게 화면에 그려지는지 살펴보았습니다. 우리가 CSS 스타일을 단 한 줄도 적지 않은 순수 HTML 문서조차 사람들이 읽기 편한 형태로 예쁘게 정렬되어 나오는 이유는 브라우저가 이 기본 동작 규칙을 성실히 따르고 있기 때문입니다. 이 '일반 흐름(Normal flow)'이 어떻게 작동하는지 이해하는 것은 앞으로 더 복잡한 CSS 레이아웃을 마스터하기 위해 반드시 거쳐야 하는 가장 중요한 첫걸음입니다.
이 페이지가 도움이 되셨나요? [네 (Yes)] / [아니요 (No)]
기여하는 방법 알아보기 (Learn how to contribute)
이 페이지는 2025년 12월 15일에 MDN 기여자들 (MDN contributors)에 의해 마지막으로 수정되었습니다.