안녕하세요! 프론트엔드 개발 강사입니다. 이번에 질문 주신 내용은 CSS 레이아웃을 이해하는 데 있어 가장 중요한 핵심 원리 중 하나인 '일반 흐름(Normal Flow)'과 '흐름에서 벗어남(Out of Flow)'에 대한 문서네요!
우리가 HTML 태그를 쭉 적어 내려가면, 브라우저 화면에도 그 순서대로 위에서 아래로 예쁘게 쌓이잖아요? 이걸 바로 '일반 흐름에 있다(In flow)'고 부릅니다. 그런데 가끔 요소를 화면에 둥둥 띄워서 겹치게 하거나(absolute), 스크롤을 내려도 메뉴가 화면 맨 위에 착 붙어있게(fixed) 만들고 싶을 때가 있죠? 이때 요소를 '흐름에서 빼내는(Out of flow)' 마법을 부리게 됩니다.
딱딱한 영문 문서의 내용을 실무에서 제가 직접 겪었던 팁들을 곁들여서 이해하기 쉽고 명쾌한 구어체로 싹 번역해 드릴게요! 같이 차근차근 살펴볼까요? 😊
이전 가이드에서는 일반 흐름(normal flow) 내에서의 블록(block) 및 인라인(inline) 레이아웃에 대해 설명했습니다. 흐름 안에 있는(in flow) 모든 요소들은 이 일반적인 방식을 따라 화면에 차곡차곡 배치됩니다.
다음 예제에는 제목(<h1>), 단락(<p>), 리스트(<ul>), 그리고 내부에 <strong> 요소를 품고 있는 마지막 단락이 차례대로 포함되어 있습니다.
제목(<h1>)과 단락(<p>) 태그들은 블록(block) 레벨 요소이고, <strong> 태그는 인라인(inline) 요소입니다. 또한, 항목들을 가로 한 줄로 배치하기 위해 플렉스박스(flexbox)로 표시된 리스트(<ul>) 역시 블록과 인라인 레이아웃의 규칙에 참여하고 있습니다. (플렉스 컨테이너인 <ul> 자체의 외부 display 타입이 기본적으로 block이기 때문에 다른 블록 요소들과 마찬가지로 위아래로 쌓입니다.)
💡 강사의 부연 설명: "In Flow"의 핵심
여기서 중요한 건, 이 모든 요소들이 HTML 코드에 적힌 순서 그대로 화면에 위에서부터 아래로 자리를 잡았다는 점입니다. 그 어떤 요소도 남의 자리를 뺏거나 다른 요소 위로 겹쳐지지 않았죠. 이게 바로 모든 요소가 평화롭게 질서를 지키고 있는 'In Flow(흐름 안에 있음)' 상태입니다!
(MDN Playground에서 실행해보기 (Play))
<div class="box">
<h1>A heading</h1>
<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.
</p>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
<p>
Their names were <strong>Stephen and Joseph Montgolfier</strong>, they were
papermakers by trade, and were noted as possessing thoughtful minds and a
deep interest in all scientific knowledge and new discovery.
</p>
</div>
body {
font: 1.2em sans-serif;
}
.box > * {
border: 1px solid green;
}
ul {
display: flex;
justify-content: space-around;
list-style: none;
margin: 0;
}
위의 모든 요소는 "흐름 안에(in flow)" 있는 것으로 간주됩니다. 즉, 여러분이 작성한 HTML 소스 코드의 순서와 똑같은 순서로 페이지 화면에 나타납니다.
웹페이지의 모든 요소는 기본적으로 흐름 안에(in-flow) 있지만, 다음 세 가지 경우는 예외적으로 흐름에서 빠져나옵니다(out-of-flow).
float: left 또는 float: right)position: absolute가 적용된 항목들 (이와 똑같은 방식으로 행동하는 position: fixed 포함)<html>)흐름에서 빠져나온(Out-of-flow) 항목들은 자신만의 새로운 블록 서식 컨텍스트 (Block Formatting Context, BFC)를 생성합니다. 따라서 이 요소 내부의 모든 것들은 페이지의 나머지 부분과는 완전히 분리된, 자기들만의 독자적인 '미니 레이아웃' 세상이라고 볼 수 있습니다. 그렇기 때문에 우리 문서의 모든 것을 감싸고 있는 최상위 부모인 <html> 요소(루트 요소) 역시, 문서를 위한 최초의 블록 서식 컨텍스트를 생성하는 존재로서 흐름 밖에(out of flow) 있다고 보는 것이 맞습니다.
👨🏫 강사의 실무 팁! "흐름에서 빠져나오면 무슨 일이 생길까요?"
요소를 흐름에서 빼낸다는 건, 그 요소가 "유령"이 된다는 뜻이에요! 원래 자기 자리를 차지하고 있었는데 갑자기 공중으로 붕 떠버리니, 뒤에 줄 서 있던 다른 요소들이 "어? 빈자리네?" 하고 그 자리를 훅 치고 들어와 버립니다. 여기서 레이아웃 붕괴가 엄청나게 자주 일어나니 꼭 주의하셔야 해요!
이 예제에는 부모 <div>가 있고, 그 안에 작은 <div> 하나와 두 개의 <p>(단락)가 있습니다. 단락들에는 배경색이 칠해져 있고, 작은 <div>에는 float: left가 적용되어 있습니다. 이렇게 하면 이 <div>는 이제 일반 흐름에서 빠져나온(out of flow) 상태가 됩니다.
요소가 float(플롯) 되면, 브라우저는 먼저 이 요소가 일반 흐름에 있었을 때 놓여야 할 원래 자리를 계산해서 그 높이(y축)에 요소를 둡니다. 그러고 나서 요소를 일반 흐름에서 쏙 빼낸 뒤에, 왼쪽(left)으로 갈 수 있는 한 최대한 밀어붙여서(float) 배치합니다.
(MDN Playground에서 실행해보기 (Play))
<div class="box">
<div class="float">I am a floated box!</div>
<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>
body {
font: 1.2em sans-serif;
}
p {
background-color: #cccccc;
}
.float {
float: left;
font-weight: bold;
width: 200px;
border: 2px dotted black;
padding: 10px;
}
예제 결과를 보시면, floated 된 <div> 바로 뒤에 있는 <p>의 회색 배경색이 floated <div> 아래쪽으로 쓱 파고들어 가는 것을 볼 수 있죠?
<p> 요소 자체의 박스는 여전히 일반 흐름(normal flow)의 규칙을 따라 화면 전체 너비를 꽉 채우고 있기 때문입니다. 단지 그 안에 있는 텍스트(라인 박스)들만 floated 된 요소와 겹치지 않게 짧아져서 마치 텍스트가 박스를 감싸고 흐르는(wrapping) 것처럼 보일 뿐입니다.
⚠️ 강사의 중요 팁! "Float 해제하기 (Clearfix)"
Float 된 요소 주위로 공간을 만들고 싶다면, 뒤따라오는<p>태그에 마진을 주면 안 됩니다. 왜냐하면 Float 된 녀석은 유령처럼 떠있기 때문에 뒤에 있는<p>가 그 녀석의 존재를 모르거든요. 이럴 때는 뒤따라오는 요소에clear: both를 주거나, 아니면 애초에 Float 보다는 현대적인 Flexbox나 Grid를 사용하는 것을 적극 권장합니다!
요소에 position: absolute 또는 position: fixed를 부여하면 요소가 문서의 일반 흐름에서 완전히 제거되며, 그 요소가 원래 차지하고 있어야 할 공간조차 흔적도 없이 싹 사라집니다. 다음 예제에는 세 개의 <p> 요소가 있는데, 두 번째 단락에 position: absolute를 주고 상단에서 30px(top: 30px), 오른쪽에서 30px(right: 30px) 떨어지도록 오프셋(offset) 값을 주었습니다. 이제 이 두 번째 단락은 문서의 흐름에서 완전히 빠져나왔습니다.
(MDN Playground에서 실행해보기 (Play))
<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.
</p>
<p class="abspos">
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>
body {
font: 1.2em sans-serif;
}
.box {
width: 70%;
}
p {
border: 2px solid green;
}
.abspos {
position: absolute;
background-color: green;
color: white;
top: 30px;
right: 30px;
width: 400px;
}
결과를 보면, 두 번째 단락이 공중으로 붕 뜨면서 세 번째 단락이 첫 번째 단락 바로 밑으로 찰싹 달라붙은 걸 볼 수 있습니다!
position: fixed를 사용하는 것 역시 요소를 흐름에서 제거하지만, 차이점이 있다면 오프셋(top, bottom 등)의 기준점이 부모 요소(containing block)가 아니라 브라우저 화면(viewport)이 된다는 것입니다. (그래서 스크롤을 내려도 화면에 계속 고정되어 보이죠.)
위치 지정(positioning)을 이용해 요소를 흐름 밖으로 빼낼 때는, 콘텐츠끼리 겹치는(overlap) 문제를 개발자가 직접 세심하게 관리해 주어야 합니다. '흐름 밖(Out of flow)'이라는 말은 본질적으로 페이지의 다른 일반 요소들이 그 요소가 존재하는지조차 모르게 되어버렸다는 뜻이니까요. 그래서 유령처럼 붕 떠 있는 요소가 다른 중요한 텍스트를 덮어버리지 않도록 항상 조심해야 합니다.
만약 요소에 position: relative(상대 위치 지정)를 부여하면, 그 요소는 여전히 일반 흐름(in flow) 안에 머물러 있습니다. 하지만 오프셋 값(top, left 등)을 사용해서 원래 있던 자리에서 요소를 밀어내어(push) 다른 곳으로 살짝 이동시킬 수 있게 되죠.
중요한 점은 아래 예제에서 볼 수 있듯이, 이 요소가 이동하더라도 원래 일반 흐름에서 차지하고 있던 그 텅 빈 공간(space)은 여전히 예약된 상태로 남아있게 된다는 것입니다.
💡 강사의 실무 팁! "Relative는 왜 쓸까요?"
relative를 써서 요소를 직접 이동시키는 경우는 실무에서 흔치 않아요. 원래 자리가 텅 비어버리면 레이아웃이 미워지니까요. 그 대신,relative는position: absolute를 적용한 자식 요소가 부모 박스를 벗어나지 못하도록 가둬두는 "감옥(기준점)" 역할로 99% 사용됩니다!
(MDN Playground에서 실행해보기 (Play))
<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.
</p>
<p class="relative">
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>
body {
font: 1.2em sans-serif;
}
.box {
width: 70%;
}
p {
border: 2px solid green;
}
.relative {
position: relative;
background-color: green;
color: white;
bottom: 50px;
left: 50px;
width: 400px;
}
두 번째 문단이 위로(bottom: 50px), 오른쪽으로(left: 50px) 이동해서 첫 번째 문단을 덮어버렸지만, 세 번째 문단은 두 번째 문단이 원래 있던 그 빈자리를 고스란히 놔둔 채 그 아래에 얌전히 자리 잡은 것을 볼 수 있습니다.
요소를 원래 일반 흐름에서 배치되어야 할 위치로부터 제거하거나 이동시키는 작업을 할 때는, 요소들끼리 보기 흉하게 겹치는 것을 막기 위해 해당 요소뿐만 아니라 주변 콘텐츠들까지 잘 관리해 주어야 합니다. clear 속성으로 float를 해제하든, position: absolute 요소가 다른 글자를 가리지 않게 margin이나 padding으로 공간을 띄워주든 말이죠. 이러한 이유로 요소를 흐름에서 빼내는(out-of-flow) 방법들은 그것이 주변 레이아웃에 미치는 영향을 완벽히 이해한 상태에서 사용해야 합니다.
이번 가이드에서는 아주 특별한 위치 지정을 위해 요소를 문서의 흐름 밖으로(out of flow) 꺼내는 방법에 대해 설명했습니다. 다음 가이드인 서식 컨텍스트 소개(Introduction to formatting contexts)에서는 이와 밀접하게 관련된 개념인 블록 서식 컨텍스트(Block Formatting Context, BFC)를 생성하는 방법에 대해 자세히 알아볼 것입니다.
이 페이지가 도움이 되셨나요? [네 (Yes)] / [아니요 (No)]
기여하는 방법 알아보기 (Learn how to contribute)
이 페이지는 2025년 11월 7일에 MDN 기여자들 (MDN contributors)에 의해 마지막으로 수정되었습니다.