Normal Flow의 한계 극복부터 Position 4대 속성(static/relative/absolute/fixed), Flexbox 1차원 레이아웃(주축·교차축·flex: 1), Media Query 반응형 디자인, 그리고 실전 반응형 네비게이션 바(Navbar) 구현까지 총정리한 실전 가이드
- Normal Flow (기본 문서 흐름)와 레이아웃의 필요성
- CSS position 속성: 자유로운 위치 제어
- Flexbox (Flexible Box Layout): 1차원 정렬 시스템
- 반응형 웹 디자인 (Responsive Design) & Media Query
- 실전 종합 프로젝트: 반응형 네비게이션 바 (Responsive Navbar)
- 💡 실전 핵심 요약 치트시트
- CSS에서 아무런 위치/레이아웃 속성도 적용하지 않았을 때 브라우저가 요소를 자동으로 배치하는 기본 규칙입니다.
- 웹 문서의 가장 자연스러운 원시적 흐름(Normal Flow)입니다.
- Inline 요소: 텍스트를 쓸 때처럼 왼쪽에서 오른쪽으로 나열되며, 공간이 꽉 차면 자동으로 다음 줄로 넘어갑니다 (span, a, strong).
- Block-level 요소: 블록처럼 위에서 아래로 한 줄 전체를 독점하며 벽돌을 쌓듯 차례로 배치됩니다 (div, p, h1).
Warning
🚨 Normal Flow의 치명적 한계:
기본 흐름만으로는 현대 웹의 필수 요소인 좌우 가로 정렬, 상하좌우 완전한 정가운데 정렬, 유연한 간격(gap) 조절, 특정 위치 고정(헤더/배지) 등을 구현하기가 극도로 어렵습니다.
➔ 따라서 우리는 **position**과 **flexbox**를 통해 Normal Flow를 의도적으로 벗어나거나 제어합니다!
- 역할: 요소를 어디에(Where), 무엇을 기준(Reference)으로 배치할지 결정하는 핵심 속성.
- 오프셋 프로퍼티: 기준점으로부터 얼마나 떨어질지 거리를 지정합니다.
- top, bottom, left, right (px, rem, % 등)
- 모든 HTML 요소의 태생적 기본값.
- Normal Flow를 그대로 유지하며 일반적인 문서 흐름에 따라 배치됩니다.
- ⚠️ top, left, right, bottom 오프셋 좌표를 적어도 완전히 무시되어 적용되지 않습니다!
- 기준점: **"내가 원래 있었어야 할 본래 위치"**가 기준점(0, 0)이 됩니다.
- 특징:
- Normal Flow 유지: 요소가 시각적으로 이동하더라도, 원래 자리는 빈 공간(유령 자리)으로 그대로 보존됩니다.
- 다른 인접 요소들의 레이아웃 배치에 전혀 영향을 주지 않습니다 (margin과 다른 점!).
- 🌟 자식의 absolute를 가두는 기준 조상 역할로 가장 많이 사용됩니다.
.box {
position: relative;
top: 30px; /* 원래 위치에서 아래로 30px 이동 */
left: 30px; /* 원래 위치에서 오른쪽으로 30px 이동 */
}
- 기준점: "가장 가까운 position이 지정된 조상 요소" (즉, static이 아닌 relative, absolute, fixed를 가진 부모).
- 특징:
- Normal Flow에서 완전 제거: 붕 떠오르면서(부유) 원래 차지하던 자리가 사라집니다. 주변 요소들이 빈자리를 메우기 위해 당겨집니다.
- 기준이 될 포지셔닝 부모가 없으면 **브라우저 화면(Viewport / 초기 컨테이닝 블록)**을 기준으로 배치됩니다.
<div class="container">
<div class="box">BOX</div>
</div>
/* 1. 부모에게 기준점 부여 */
.container {
width: 200px;
height: 200px;
border: 3px solid #333;
position: relative; /* 자식의 absolute 좌표 기준점이 됨! */
}
/* 2. 자식은 부모 안에서 자유자재로 이동 */
.box {
width: 100px;
height: 100px;
background: #4caf50;
position: absolute;
top: 0px;
left: 0px; /* 부모 컨테이너의 좌상단(0, 0)에 정확히 밀착 */
}
.korean-link {
position: absolute;
top: 10px;
right: 10px; /* 부모의 오른쪽 위 모서리에 고정 */
color: darkcyan;
font-size: small;
}
- 기준점: 부모가 누구든 상관없이 무조건 **브라우저 화면 전체(Viewport)**가 기준점.
- 특징:
- Normal Flow에서 완전히 제거됨.
- 페이지를 아무리 길게 스크롤해도 화면의 지정된 그 위치에 못 박힌 듯 영구 고정됩니다.
- 주요 사용처: 상단 고정 헤더(Navigation Bar), 화면 우하단 맨 위로 가기 플로팅 버튼, 챗봇 상담 아이콘.
.fixed-header {
position: fixed;
top: 0;
left: 0;
width: 100%; /* 화면 상단 전체를 덮는 고정 바 */
}
속성값기준점 (Reference)Normal Flow 이탈 여부원래 자리 보존 여부스크롤 시 동작
| static | 일반적인 문서 흐름 | ❌ (유지) | ⭕ (보존) | 함께 스크롤됨 (위치 이동 불가) |
| relative | 자신의 본래 위치 | ❌ (유지) | ⭕ (원래 자리 비어있음) | 함께 스크롤됨 |
| absolute | 포지셔닝된 가장 가까운 조상 | ⭕ (완전 제거) | ❌ (자리 사라짐) | 함께 스크롤됨 |
| fixed | 브라우저 화면 (Viewport) | ⭕ (완전 제거) | ❌ (자리 사라짐) | 화면에 영구 고정 (스크롤 무시) |
- 목적: 복잡한 계산 없이 여러 박스를 한 방향(가로 or 세로)으로 유연하게 배치하고 정렬하기 위한 최신 CSS 레이아웃 시스템.
- 핵심 특징:
- 1차원 레이아웃: 가로(Row) 또는 세로(Column) 중 한 방향 축을 기준으로 정렬.
- 부모 중심 제어: 부모(Container)에게 속성을 주면 자식(Items)들의 배치가 일괄 통제됨.
- 직관적인 간격과 정렬: gap, justify-content, align-items로 손쉬운 여백 제어.
부모 요소에 display: flex;를 선언하는 순간, 즉시 Flex 환경이 가동됩니다:
<div class="container"> <!-- Flex Container (부모) -->
<div class="item">A</div> <!-- Flex Item (자식) -->
<div class="item">B</div> <!-- Flex Item (자식) -->
<div class="item">C</div> <!-- Flex Item (자식) -->
</div>
.container {
display: flex; /* 자식들이 기본적으로 가로(row) 방향으로 나란히 정렬됨 */
gap: 10px; /* 자식 아이템 사이의 간격을 10px로 균등 배치 */
}
Flexbox는 항상 두 개의 직교하는 축을 기준으로 요소를 정렬합니다:
[기본값: flex-direction: row 인 경우]
주축 (Main Axis: 가로) ➔ justify-content 로 정렬
────────────────────────────────────────────────────────►
│ [Item A] [Item B] [Item C]
│
│ 교차축 (Cross Axis: 세로) ➔ align-items 로 정렬
▼
- 주축 (Main Axis): 아이템들이 배치되는 기본 진행 방향 (기본값: 가로 방향 row).
- 교차축 (Cross Axis): 주축과 90도로 교차하는 수직 방향 (기본값: 세로 방향 column).
- flex-direction: row; (기본값) ➔ 왼쪽에서 오른쪽으로 가로 배치
- flex-direction: column; ➔ 위에서 아래로 세로 배치 (모바일 반응형에서 필수!)
- flex-start (기본값): 시작 지점으로 정렬
- center: 주축 기준 가운데 정렬
- flex-end: 끝 지점으로 정렬
- space-between: 양 끝을 벽에 붙이고, 아이템 사이 간격을 균등하게 배분 (네비게이션 바 필수!)
- space-around / space-evenly: 아이템 둘레/사이를 균등 분배
- stretch (기본값): 부모의 높이만큼 아이템을 늘림
- center: 교차축 기준 수직 가운데 정렬
- flex-start / flex-end: 상단 또는 하단 정렬
.item {
display: flex;
justify-content: center; /* 가로(주축) 가운데 */
align-items: center; /* 세로(교차축) 가운데 */
}
콘텐츠가 적은 페이지에서도 푸터(Footer)가 화면 중간에 뜨지 않고 항상 브라우저 맨 바닥에 달라붙게 만드는 실무 표준 기법:
body {
min-height: 100vh; /* 화면 전체 높이 보장 */
display: flex;
flex-direction: column; /* 세로 방향으로 쌓기 */
}
main {
flex: 1; /* ⭐ 메인 콘텐츠가 화면의 남은 여백을 전부 차지하여 푸터를 맨 밑으로 밀어냄! */
}
footer {
margin-bottom: 2rem;
}
- 개구리를 연잎 위에 올려놓으며 Flexbox 정렬 속성을 직관적으로 마스터하는 세계적인 학습 게임:
- 🔗 링크: https://flexboxfroggy.com/#ko
- 스마트폰, 태블릿, 데스크톱 모니터 등 사용자의 화면 크기(Viewport)와 디바이스 환경이 다양화됨에 따라, 화면에 맞춰 레이아웃과 폰트 크기가 자연스럽게 재배치되는 웹을 구축해야 합니다.
- 유연한 레이아웃: Flexbox, Grid
- 유연한 상대 크기 단위: %, vw, vh, rem
- 조건부 스타일: Media Query (@media)
Note
rem 단위란?
rem(Root em)은 최상위 <html> 태그의 기본 폰트 크기(보통 16px)를 기준으로 비례하는 상대 단위입니다.
- 1rem = 16px
- 2.4rem = 약 38.4px (대제목)
- 0.9rem = 약 14.4px (작은 본문/라벨)
모바일이나 사용자 설정에 따라 기본 글꼴이 커지면 모든 요소가 아름답게 함께 확대/축소됩니다.
- 정의: **"화면이 이 조건(크기)에 부합하면, 아래 스타일을 덮어써서 적용하라!"**는 조건부 CSS 규칙.
/* 화면 너비가 400px 이하인 작은 스마트폰 화면일 때만 실행 */
@media (max-width: 400px) {
.container {
flex-direction: column; /* 가로 나열을 세로 쌓기로 변경 */
}
.box {
background: orange; /* 배경색 변경 */
}
}
강의 슬라이드에서 완성한 PC에서는 가로 1줄, 모바일(400px 이하)에서는 세로로 깔끔하게 떨어지는 반응형 상단 메뉴바의 완성 코드입니다:
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>반응형 Navigation Bar</title>
<!-- Font Awesome CDN 및 외부 스타일시트 연결 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" />
<link rel="stylesheet" href="navbar_style.css" />
</head>
<body>
<nav class="navbar">
<!-- 1. 좌측 로고 -->
<div class="navbar__logo">
<i class="fa-brands fa-dev"></i>
<a href="#">qu3vipon</a>
</div>
<!-- 2. 중앙 메뉴 링크 -->
<ul class="navbar__menu">
<li><a href="#">About</a></li>
<li><a href="resume.html">Resume</a></li>
<li><a href="#">Gallery</a></li>
</ul>
<!-- 3. 우측 SNS 아이콘 -->
<ul class="navbar__icons">
<li><i class="fa-brands fa-github"></i></li>
<li><i class="fa-brands fa-x-twitter"></i></li>
</ul>
</nav>
</body>
</html>
/* 기본 리셋 및 폰트 */
body {
margin: 0;
font-family: "BBH Bogle", sans-serif;
}
a {
text-decoration: none;
color: black;
}
/* 네비게이션 컨테이너: flex 3등분 좌우 분배 */
.navbar {
display: flex;
justify-content: space-between; /* 로고 - 메뉴 - 아이콘을 양 끝과 중앙에 고루 배치 */
align-items: center; /* 수직 가운데 정렬 */
background-color: beige;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.navbar__logo {
font-size: 1.4rem;
}
/* 메뉴 리스트: 가로 flex 배치 */
.navbar__menu {
display: flex;
list-style: none;
padding: 0;
}
.navbar__menu li {
padding: 8px 12px;
}
.navbar__menu li:hover {
background-color: white;
border-radius: 8px;
}
/* SNS 아이콘 리스트: 가로 flex 배치 */
.navbar__icons {
display: flex;
list-style: none;
padding: 0;
}
.navbar__icons li {
padding: 8px 4px;
}
화면 너비가 좁아지면 가로 정렬을 **세로 1열(column)**로 전환하여 화면 찌그러짐을 방지합니다:
@media (max-width: 400px) {
/* 1. 전체 바를 세로로 쌓고 왼쪽 정렬 */
.navbar {
flex-direction: column;
align-items: flex-start;
padding: 16px;
}
/* 2. 메뉴 항목을 가로폭 100% 차지하게 늘리고 텍스트 중앙 정렬 */
.navbar__menu {
flex-direction: column;
width: 100%;
text-align: center;
}
/* 3. 아이콘 모음도 중앙 정렬 */
.navbar__icons {
justify-content: center;
width: 100%;
}
}
1. position 핵심 공식
- static : 기본 흐름 (top/left 무시)
- relative : 원래 내 자리 기준 (부모 기준점 잡기용)
- absolute : 가장 가까운 포지셔닝 부모 기준 (자식 부유 배치)
- fixed : 화면 창(viewport) 기준 (스크롤해도 영구 고정)
🌟 공식: 부모에 position: relative 주고 자식에 position: absolute 주기!
2. Flexbox 정렬 공식
- display: flex; (가로 정렬 가동)
- justify-content: center; (주축 가로 가운데)
- align-items: center; (교차축 세로 가운데)
- justify-content: space-between; (양 끝 벌리기)
- flex: 1; (남은 빈 공간 다 차지하기)
3. 반응형 Media Query 공식
@media (max-width: 768px) {
/* 모바일/태블릿용 스타일 작성 (flex-direction: column 등) */
}