6. 레이아웃
개요
본 학습 문서는 모던 웹 인터페이스의 구조를 설계하는 핵심 기술인 CSS 레이아웃과 다양한 디바이스 환경에 대응하는 반응형 웹 디자인 기법을 다룹니다. 전통적이지만 텍스트 흐름 제어에 여전히 필수적인 float 속성부터, 요소의 위치를 정밀하게 제어하는 position, 그리고 현대 웹 레이아웃의 표준인 flex와 grid 시스템의 상세 활용법을 집중적으로 학습합니다. 또한 미디어 쿼리(MediaQuery)를 활용한 반응형 전략, calc() 함수를 이용한 유연한 수치 계산, 그리고 고정 비율 미디어를 처리하는 가변 미디어 기법 등 최신 퍼블리싱 트렌드에 부합하는 실전 기술들을 예제와 함께 제공합니다.
01. float
설명
요소를 일반적인 문서 흐름에서 제외하여 부모 요소의 왼쪽이나 오른쪽 가장자리에 배치한다. 현대 웹에서는 레이아웃 보다는 주로 이미지 주변으로 텍스트가 자연스럽게 흐르도록 설정할 때 실무에서 활용된다.
| 값 | 설명 |
|---|---|
left | 요소를 왼쪽으로 부유시킴 |
right | 요소를 오른쪽으로 부유시킴 |
none | 기본값. 부유시키지 않음 |
float된 요소는 부모 요소가 높이를 인식하지 못하므로, 반드시clear속성이나::after가상 요소를 이용한 Clearfix 기법으로 해제해야 한다. 자세한 내용은 🔗MDN 참고.
1-1. float 활용 예제
시작 float-text-flow.html
<div class="container">
<img src="img/lotus.png" alt="연꽃">
<p>인도가 원산지인 연꽃은 연못 위에 둥둥 떠 있는 수생식물이라는 이미지만 떠올리기 쉽지만, 실은 논이나 늪지의 진흙 속에서도 자라고 관상용뿐만 아니라 식용, 약용으로 쓰이기도 합니다.</p>
</div>
완료 float-text-flow.html
<div class="container">
<img src="img/lotus.png" style="float: right; width: 150px; margin-left: 20px;" alt="연꽃">
<p>인도가 원산지인 연꽃은 연못 위에 둥둥 떠 있는 수생식물이라는 이미지만 떠올리기 쉽지만, 실은 논이나 늪지의 진흙 속에서도 자라고 관상용뿐만 아니라 식용, 약용으로 쓰이기도 합니다.</p>
</div>
1-2. Clearfix (실무 해제 기법)
clearfix.css
/* 부모 요소에 적용하여 자식의 float을 해제함 */
.clearfix::after {
content: "";
display: block;
clear: both;
}
02. position
설명
요소를 문서의 좌표 시스템 상에서 배치하는 방법을 정의한다. 레이어 겹침(layering)이나 화면 상단 고정 메뉴, 팝업 등을 구현할 때 필수적인 속성이다.
| 값 | 설명 |
|---|---|
static | 기본값. 문서 흐름에 따라 순차적 배치 |
relative | 원래 위치를 기준으로 상대적 이동 |
absolute | 상위 요소(non-static)를 기준으로 절대적 배치 |
fixed | 뷰포트(화면)를 기준으로 고정 배치 |
sticky | 지정한 임계값까지는 흐름을 따르다 그 후 고정됨 |
z-index는static을 제외한position값이 설정된 요소들 사이에서만 깊이 순서를 조절할 수 있다. 자세한 내용은 🔗MDN 참고.
2-1. absolute & relative
시작 ex-position.html
<div class="parent">
<div class="child"></div>
</div>
<style>
.parent { width: 300px; height: 300px; background: #eee; }
.child { width: 100px; height: 100px; background: red; }
</style>
완료 ex-position.html
<div class="parent" style="position: relative;">
<div class="child" style="position: absolute; bottom: 0; right: 0;"></div>
</div>
<style>
.parent { width: 300px; height: 300px; background: #eee; }
.child { width: 100px; height: 100px; background: red; }
</style>
2-2. sticky 예제
ex2-72-5.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>sticky position</title>
<style>
.container { background-color: orangered; width: 700px; height: 600px; }
.box { width: 350px; height: 100px; font-size: 25px; color: #fff; }
.box-1 { background-color: green; position: sticky; top: 0; }
</style>
</head>
<body>
<div class="container">
<div class="box box-1">Box 1 (Sticky)</div>
</div>
</body>
</html>
03. flex
설명
부모 요소를 컨테이너로 삼아 자식 아이템들을 1차원(행 또는 열) 방향으로 효율적으로 정렬하는 현대적인 레이아웃 시스템이다. 공간 배분과 정렬을 자동화하여 복잡한 계산 없이 유연한 레이아웃을 구성할 수 있다.
| 주요 속성 | 설명 |
|---|---|
display: flex | 컨테이너를 Flex Box로 선언 |
justify-content | 주축 방향 아이템 정렬 |
align-items | 교차축 방향 아이템 정렬 |
Flex 아이템에는
float이 적용되지 않으며,margin: auto를 통해 정렬과 여백 처리를 쉽게 구현할 수 있다. 자세한 내용은 🔗MDN 참고.
3-1. flex 정렬
시작 01-flex.html
<div class="flex-container">
<div class="item">1</div><div class="item">2</div><div class="item">3</div>
</div>
<style>
.item { width: 100px; height: 100px; background: tomato; margin: 10px; }
</style>
완료 01-flex.html
<div class="flex-container" style="display: flex; justify-content: space-around;">
<div class="item">1</div><div class="item">2</div><div class="item">3</div>
</div>
<style>
.item { width: 100px; height: 100px; background: tomato; margin: 10px; color: white; text-align: center; line-height: 100px; }
</style>
04. grid
설명
행(Row)과 열(Column)을 모두 활용하는 2차원 레이아웃 시스템이다. 복잡한 골격 설계나 격자 구조의 인터페이스를 구현할 때 가장 강력하고 효율적인 도구이다.
| 용어 | 설명 |
|---|---|
Grid Container | display: grid가 적용된 부모 요소 |
Gap | 그리드 아이템 사이의 간격 |
grid-template-areas를 사용하면 레이아웃의 구조를 설계도처럼 시각적으로 정의할 수 있어 유지보수가 매우 편리하다. 자세한 내용은 🔗MDN 참고.
4-1. grid 기본 레이아웃
시작 01-grid.html
<div class="grid-container">
<div class="header">Header</div>
<div class="main">Main</div>
<div class="aside">Aside</div>
<div class="footer">Footer</div>
</div>
완료 01-grid.html
<div class="grid-layout">
<header>Header</header>
<nav>Nav</nav>
<main>Main</main>
<footer>Footer</footer>
</div>
<style>
.grid-layout {
display: grid;
grid-template-areas:
"header header header"
"nav main main"
"footer footer footer";
gap: 10px;
}
header { grid-area: header; background: #f99; padding: 20px; }
nav { grid-area: nav; background: #9f9; padding: 20px; }
main { grid-area: main; background: #99f; padding: 20px; }
footer { grid-area: footer; background: #ff9; padding: 20px; }
</style>
05. calc
설명
CSS 속성값에 사칙연산(+, -, *, /) 표현식을 사용하여 수치를 동적으로 계산한다. 백분율(%)과 픽셀(px) 등 서로 다른 단위 간의 연산이 가능하여 반응형 레이아웃 구현 시 유용하다.
| 연산자 | 사용 규칙 |
|---|---|
+, - | 반드시 연산자 앞뒤로 공백이 있어야 함 |
*, / | 곱셈·나눗셈도 가능. 한쪽은 단위 없는 숫자 |
자세한 내용은 🔗MDN 참고.
5-1. calc 로 남는 너비 채우기
시작 calc-layout.html
<div class="layout">
<aside>사이드바</aside>
<main>본문 영역</main>
</div>
완료 calc-layout.html
<div class="layout">
<aside>사이드바</aside>
<main>본문 영역</main>
</div>
<style>
.layout { display: flex; }
aside { width: 250px; background: #eee; padding: 20px; }
/* 전체 너비(100%)에서 사이드바 250px 를 뺀 나머지를 본문이 차지 */
main { width: calc(100% - 250px); background: #d8eafd; padding: 20px; }
</style>
06. MediaQuery 및 반응형 패턴
설명
뷰포트의 크기에 따라 서로 다른 스타일을 적용하는 기술과 실무에서 검증된 대표적인 레이아웃 설계 패턴들을 학습한다.
| 패턴명 | 특징 |
|---|---|
Mostly Fluid | 대화면에서 고정 너비, 소화면에서 유동적으로 변함 |
Column Drop | 화면이 좁아지면 다단 레이아웃이 아래로 쌓임 |
Layout Shifter | 해상도 중단점에 따라 요소를 재배치 |
자세한 내용은 🔗MDN 참고.
6-1. 패턴 01. Mostly Fluid
시작 01-mostly-fluid.html
<div id="wrap">
<div id="content">Content</div>
<div id="aside">Aside</div>
</div>
완료 01-mostly-fluid.html
<style>
#wrap { max-width: 960px; margin: 0 auto; width: 100%; }
#content { float: left; width: 62.5%; background: lime; padding: 20px; }
#aside { float: right; width: 35%; background: green; padding: 20px; }
@media screen and (max-width:480px) {
#content, #aside { width: 100%; float: none; }
}
</style>
<div id="wrap">
<div id="content">Content</div>
<div id="aside">Aside</div>
</div>
6-2. 패턴 02. Column Drop
시작 02-column-drop.html
<div class="cols">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
완료 02-column-drop.html
<div class="cols">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
<style>
.cols { display: flex; gap: 10px; }
.box { flex: 1; padding: 20px; background: #cde; text-align: center; }
/* 화면이 좁아지면 가로 배치를 세로로 바꿔 칸이 아래로 쌓임(drop) */
@media screen and (max-width: 600px) {
.cols { flex-direction: column; }
}
</style>
6-3. 패턴 03. Layout Shifter
시작 03-layout-shifter.html
<div class="shifter">
<nav class="nav">Nav</nav>
<main class="main">Main</main>
</div>
완료 03-layout-shifter.html
<div class="shifter">
<nav class="nav">Nav</nav>
<main class="main">Main</main>
</div>
<style>
.shifter { display: flex; gap: 10px; }
.nav { flex: 1; padding: 20px; background: #fcd; order: 1; } /* 넓은 화면: 왼쪽 */
.main { flex: 3; padding: 20px; background: #cdf; order: 2; } /* 넓은 화면: 오른쪽 */
@media screen and (max-width: 600px) {
.shifter { flex-direction: column; }
/* 좁은 화면: order 로 순서를 바꿔 본문을 네비 위로 끌어올림 */
.main { order: 1; }
.nav { order: 2; }
}
</style>
07. 가변 미디어
설명
비디오나 지도 같은 고정 비율의 콘텐츠가 부모 요소의 너비에 맞춰 비율을 유지하며 크기가 변하도록 처리하는 기법이다.
| 핵심 기술 | 역할 |
|---|---|
aspect-ratio | 가로:세로 비율을 직접 지정 (최신 브라우저, 가장 간단) |
padding-bottom | 가로 너비 기준 높이 비율(예: 16:9 = 56.25%) 확보 |
최신 브라우저에서는
aspect-ratio속성으로 비율을 훨씬 간단히 지정할 수 있다. 예전 방식인padding-bottom기법도 함께 알아두면 좋다. 자세한 내용은 🔗MDN 참고.
7-1. 16:9 반응형 영상
시작 responsive-video.html
<div class="video">
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"></iframe>
</div>
완료(최신 방식) responsive-video.html
<div class="video">
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"></iframe>
</div>
<style>
/* 비율만 지정하면 너비에 맞춰 높이가 자동으로 계산됨 */
.video { aspect-ratio: 16 / 9; }
.video iframe { width: 100%; height: 100%; border: 0; }
</style>
완료(예전 방식) responsive-video.html
<div class="video">
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"></iframe>
</div>
<style>
/* aspect-ratio 가 없던 시절: 부모 높이를 0 으로 두고
padding-bottom 56.25%(= 9 ÷ 16) 로 16:9 공간을 확보 */
.video { position: relative; width: 100%; padding-bottom: 56.25%; height: 0; }
.video iframe {
position: absolute; top: 0; left: 0;
width: 100%; height: 100%; border: 0;
}
</style>