Flexbox 레이아웃
지난 장에서 우리는 모든 HTML 요소가 박스 모델 개념을 기반으로 하며, display 속성으로 요소의 기본 배치 방식을 제어할 수 있음을 학습했습니다.
display: block, display: inline, display: inline-block은 간단한 레이아웃에는 유용하지만, 복잡한 UI 요소를 유연하게 정렬하고 배치하는 데는 한계가 있습니다.
특히 다양한 화면 크기에 맞춰 요소를 재배치해야 하는 반응형 웹 디자인에서는 그 한계가 더 분명해집니다.
여기서 등장하는 것이 바로 Flexbox(Flexible Box Layout)입니다. Flexbox는 1차원 레이아웃(한 줄 또는 한 열)을 위해 설계된 CSS3 레이아웃 모듈입니다.
부모 요소(컨테이너) 안 자식 요소(아이템)를 효율적으로 정렬/분배/배치할 수 있어, 복잡하고 유연한 레이아웃을 훨씬 쉽게 구현할 수 있습니다.
이 장에서는 Flexbox의 기본 개념과 주요 속성을 상세하게 학습하고, 실습을 통해 Flexbox의 강력함을 직접 경험해 볼 것입니다. Flexbox를 익히면 웹 레이아웃 구현 능력이 한 단계 성장합니다.
Flexbox의 기본 개념: 컨테이너와 아이템
Flexbox는 부모-자식 관계를 기반으로 작동합니다. Flexbox 레이아웃을 적용하려는 영역을 Flex 컨테이너(Flex Container)로 만들고, 그 안에 있는 직계 자식 요소들이 Flex 아이템(Flex Item)이 됩니다.
- Flex 컨테이너:
display: flex또는display: inline-flex속성이 적용된 부모 요소입니다. 컨테이너에 적용하는 속성들은 그 안에 있는 Flex 아이템들의 전체적인 배치와 정렬에 영향을 미칩니다. - Flex 아이템: Flex 컨테이너의 직계 자식 요소들입니다. 아이템에 직접 적용하는 속성들은 개별 아이템의 크기나 정렬 방식에 영향을 줍니다.
- 주축 (Main Axis): Flex 아이템들이 배열되는 주된 방향입니다. 기본값은 가로(
row)입니다. - 교차축 (Cross Axis): 주축에 수직인 방향입니다. 주축이 가로이면 교차축은 세로(
column)가 됩니다.
Flex 컨테이너 속성: 아이템 전체 정렬/배치
Flexbox 레이아웃에서는 스타일 규칙, 레이아웃 계산, 화면 반영 결과를 정리합니다.
Flex 컨테이너에 적용하는 속성들은 Flex 아이템들의 배열 방식과 공간 분배를 제어합니다.
display로 Flex 컨테이너 선언
display: flex;: 컨테이너를 블록 레벨 Flex 컨테이너로 만듭니다. 즉, 컨테이너 자체가 새로운 줄에서 시작하고 부모 너비를 차지합니다. (가장 일반적인 사용)display: inline-flex;: 컨테이너를 인라인 레벨 Flex 컨테이너로 만듭니다. 즉, 컨테이너 자체가 인라인 요소처럼 콘텐츠 흐름에 따라 옆으로 배치됩니다.
flex-direction (주축 방향 설정)
Flex 아이템들이 배열될 주축의 방향을 설정합니다.
row(기본값): 아이템들을 가로 방향으로 (왼쪽에서 오른쪽, 또는 오른쪽에서 왼쪽) 배열합니다. 주축은 가로입니다.row-reverse: 아이템들을row의 반대 방향으로 배열합니다.column: 아이템들을 세로 방향으로 (위에서 아래) 배열합니다. 주축은 세로입니다.column-reverse: 아이템들을column의 반대 방향으로 배열합니다.
.container {
display: flex;
flex-direction: column; /* 아이템들을 세로로 쌓음 */
}flex-wrap (아이템 줄바꿈 설정)
Flex 아이템들이 컨테이너를 벗어날 경우 줄바꿈(wrap)할지 여부를 설정합니다.
nowrap(기본값): 모든 아이템을 한 줄에 강제로 배치합니다. (아이템 크기가 줄어들 수 있음)wrap: 아이템들이 컨테이너를 벗어나면 다음 줄로 넘어가게 합니다.wrap-reverse:wrap의 반대 방향으로 줄바꿈합니다.
.container {
display: flex;
flex-wrap: wrap; /* 아이템이 넘치면 자동으로 줄바꿈 */
}justify-content (주축 방향 정렬)
주축 방향으로 Flex 아이템들의 정렬과 공간 분배를 설정합니다.
flex-start(기본값): 주축의 시작 지점으로 아이템들을 정렬합니다.flex-end: 주축의 끝 지점으로 아이템들을 정렬합니다.center: 주축의 중앙으로 아이템들을 정렬합니다.space-between: 아이템들 사이에 균등한 공간을 분배합니다. (시작과 끝 아이템은 컨테이너 경계에 붙음)space-around: 각 아이템 주위에 균등한 공간을 분배합니다. (시작과 끝 아이템은 컨테이너 경계에서 떨어짐)space-evenly: 모든 아이템과 컨테이너 경계 사이의 공간을 모두 균등하게 분배합니다.
.container {
display: flex;
justify-content: center; /* 아이템들을 가로 중앙 정렬 */
}align-items (교차축 방향 정렬)
교차축 방향으로 Flex 아이템들의 정렬을 설정합니다.
stretch(기본값): 아이템들이 컨테이너의 교차축 길이에 맞춰 늘어납니다. (height속성이 지정되지 않은 경우)flex-start: 교차축의 시작 지점으로 아이템들을 정렬합니다.flex-end: 교차축의 끝 지점으로 아이템들을 정렬합니다.center: 교차축의 중앙으로 아이템들을 정렬합니다.baseline: 아이템들의 텍스트 기준선(baseline)에 맞춰 정렬합니다.
.container {
display: flex;
align-items: center; /* 아이템들을 세로 중앙 정렬 */
height: 200px; /* align-items를 보려면 컨테이너에 높이 지정 필요 */
}align-content (여러 줄의 교차축 정렬)
flex-wrap: wrap이 적용되어 Flex 아이템들이 여러 줄로 나뉘었을 때, 그 여러 줄 자체를 교차축 방향으로 정렬합니다. 한 줄일 때는 효과가 없습니다.
stretch(기본값): 각 줄의 공간을 균등하게 늘려 컨테이너를 채웁니다.flex-start: 각 줄을 교차축의 시작 지점으로 정렬합니다.flex-end: 각 줄을 교차축의 끝 지점으로 정렬합니다.center: 각 줄을 교차축의 중앙으로 정렬합니다.space-between: 각 줄 사이에 균등한 공간을 분배합니다.space-around: 각 줄 주위에 균등한 공간을 분배합니다.
.container {
display: flex;
flex-wrap: wrap;
align-content: space-around; /* 여러 줄을 교차축 방향으로 분배 */
height: 400px; /* align-content를 보려면 컨테이너에 충분한 높이 필요 */
}단축 속성 flex-flow
flex-direction과 flex-wrap을 한 번에 설정하는 단축 속성입니다.
.container {
flex-flow: row wrap; /* flex-direction: row; flex-wrap: wrap; 과 동일 */
}아래 다이어그램은 축을 정한 뒤 정렬, 간격, 줄바꿈을 선택하는 순서를 한 번에 보여줍니다.
이 흐름을 기준으로 보면 justify-content, align-items, gap, wrap을 상황에 맞게 고르기 쉽습니다.
Flex 아이템 속성: 개별 아이템 제어
Flex 아이템에 적용하는 속성들은 해당 아이템의 크기 조절, 정렬, 순서 등을 개별적으로 제어합니다.
order (순서 변경)
Flex 아이템의 시각적 순서를 변경합니다. 기본값은 0이며, 숫자가 낮을수록 먼저 표시됩니다.
.item-a { order: 2; }
.item-b { order: 1; } /* item-b가 item-a보다 먼저 표시됨 */flex-grow (확대 비율)
컨테이너에 남는 공간이 있을 때, Flex 아이템이 그 공간을 얼마나 차지하여 늘어날지 비율을 설정합니다. 기본값은 0 (늘어나지 않음)입니다.
.item-1 { flex-grow: 1; } /* 남는 공간을 1의 비율로 가져감 */
.item-2 { flex-grow: 2; } /* 남는 공간을 2의 비율로 가져감 (item-1의 2배) */flex-shrink (축소 비율)
Flex 아이템들이 너무 많아 컨테이너를 벗어날 때, Flex 아이템이 얼마나 축소될지 비율을 설정합니다. 기본값은 1 (줄어듦)입니다. 0으로 설정하면 줄어들지 않습니다.
.item-1 { flex-shrink: 0; } /* 공간이 부족해도 줄어들지 않음 */
.item-2 { flex-shrink: 1; } /* 기본 비율로 줄어듦 */flex-basis (기본 크기)
Flex 아이템이 flex-grow나 flex-shrink 속성이 적용되기 전에 가질 기본 크기를 주축 방향으로 지정합니다. width 또는 height와 유사하게 작동하지만, Flexbox 컨텍스트 내에서 더 유연합니다.
auto(기본값): 콘텐츠 크기나 명시된width/height를 따릅니다.px,%,em등 다양한 단위 사용 가능.
.item-1 { flex-basis: 100px; } /* 기본 너비 100px */
.item-2 { flex-basis: 30%; } /* 기본 너비 컨테이너의 30% */단축 속성 flex
flex-grow, flex-shrink, flex-basis를 한 번에 설정하는 단축 속성입니다.
flex: [flex-grow] [flex-shrink] [flex-basis];flex: 1;는flex: 1 1 0%;와 동일합니다. (늘어나고, 줄어들고, 기본 크기는 0)flex: auto;는flex: 1 1 auto;와 동일합니다.flex: none;는flex: 0 0 auto;와 동일합니다. (늘어나지도 줄어들지도 않음)
.item {
flex: 1 1 200px; /* 늘어나는 비율 1, 줄어드는 비율 1, 기본 크기 200px */
}align-self (개별 아이템 교차축 정렬)
개별 Flex 아이템의 교차축 정렬을 설정합니다. 컨테이너의 align-items 속성보다 우선합니다.
auto(기본값): 부모의align-items설정을 따릅니다.stretch,flex-start,flex-end,center,baseline:align-items와 동일한 값.
.item-special {
align-self: flex-end; /* 해당 아이템만 교차축 끝에 정렬 */
}실습: Flexbox를 활용한 레이아웃
지금까지 배운 Flexbox 속성들을 활용하여 실제 웹 페이지의 흔한 레이아웃인 네비게이션 바와 카드 목록을 만들어 봅시다.
flexbox_layout.html 파일 작성<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flexbox 레이아웃 실습</title>
<link rel="stylesheet" href="css/flex.css">
</head>
<body>
<header class="navbar">
<div class="logo">MyBrand</div>
<nav class="nav-menu">
<a href="#" class="nav-item">홈</a>
<a href="#" class="nav-item">제품</a>
<a href="#" class="nav-item">서비스</a>
<a href="#" class="nav-item special-item">문의하기</a>
</nav>
</header>
<main class="main-content">
<h1>Flexbox로 만드는 유연한 레이아웃</h1>
<section class="card-section">
<h2>인기 상품</h2>
<div class="product-cards">
<div class="card">
<h3>제품명 1</h3>
<p>이 제품은 뛰어난 품질과 디자인을 자랑합니다.</p>
<span class="price">49,000원</span>
</div>
<div class="card">
<h3>제품명 2</h3>
<p>일상에 편리함을 더해주는 필수 아이템입니다.</p>
<span class="price">75,000원</span>
</div>
<div class="card">
<h3>제품명 3</h3>
<p>놀라운 기능과 합리적인 가격으로 만나보세요.</p>
<span class="price">120,000원</span>
</div>
<div class="card">
<h3>제품명 4</h3>
<p>새로운 경험을 선사할 프리미엄 제품.</p>
<span class="price">99,000원</span>
</div>
<div class="card wide-card">
<h3>특별 할인 제품</h3>
<p>지금 구매하시면 특별한 혜택이 기다리고 있습니다! 놓치지 마세요.</p>
<span class="price">150,000원</span>
</div>
</div>
</section>
</main>
<footer>
<p>© 2025 Flexbox 연습. 모든 권리 보유.</p>
</footer>
</body>
</html>css/flex.css 파일 작성/* 기본 스타일 및 박스 사이징 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f4f7f6;
color: #333;
line-height: 1.6;
}
/* 1. 네비게이션 바 (Flex 컨테이너) */
.navbar {
display: flex; /* Flexbox 활성화 */
justify-content: space-between; /* 로고와 메뉴를 양 끝으로 정렬 */
align-items: center; /* 수직 중앙 정렬 */
background-color: #2c3e50;
color: white;
padding: 15px 30px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
}
.navbar .logo {
font-size: 1.8em;
font-weight: bold;
color: #f1c40f; /* 로고 색상 */
}
.navbar .nav-menu {
display: flex; /* 메뉴 아이템들을 Flexbox로 정렬 */
gap: 25px; /* 메뉴 아이템들 사이 간격 */
}
.nav-item {
color: white;
text-decoration: none;
font-size: 1.1em;
padding: 5px 0;
transition: color 0.3s ease;
}
.nav-item:hover {
color: #f1c40f;
}
/* Flex 아이템 개별 정렬 예시 */
.special-item {
background-color: #e67e22; /* 주황색 버튼처럼 */
padding: 8px 15px;
border-radius: 5px;
color: white !important; /* hover 색상보다 우선 */
font-weight: bold;
transition: background-color 0.3s ease;
align-self: center; /* 해당 아이템만 수직 중앙 정렬 */
}
.special-item:hover {
background-color: #d35400;
}
/* 메인 콘텐츠 */
.main-content {
max-width: 1200px;
margin: 40px auto;
padding: 0 20px;
}
.main-content h1 {
text-align: center;
color: #3498db;
margin-bottom: 40px;
font-size: 2.5em;
}
/* 2. 상품 카드 섹션 (Flex 컨테이너) */
.card-section h2 {
text-align: center;
color: #2c3e50;
margin-bottom: 30px;
font-size: 2em;
}
.product-cards {
display: flex; /* Flexbox 활성화 */
flex-wrap: wrap; /* 공간 부족 시 줄바꿈 */
justify-content: center; /* 카드들을 가로 중앙 정렬 */
gap: 25px; /* 카드들 사이 간격 */
}
.card {
background-color: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
width: 280px; /* 각 카드의 고정 너비 */
text-align: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
transition: transform 0.2s ease-in-out;
display: flex; /* 카드 내부의 콘텐츠도 Flexbox로 배치 */
flex-direction: column; /* 카드 내부 콘텐츠를 세로로 쌓음 */
justify-content: space-between; /* 카드 콘텐츠 위아래로 분배 */
}
.card:hover {
transform: translateY(-8px);
}
.card img {
max-width: 100%;
height: 150px; /* 이미지 높이 고정 */
object-fit: cover; /* 이미지 비율 유지하며 채우기 */
border-radius: 5px;
margin-bottom: 15px;
}
.card h3 {
font-size: 1.4em;
color: #2980b9;
margin-bottom: 10px;
}
.card p {
font-size: 0.95em;
color: #555;
margin-bottom: 15px;
flex-grow: 1; /* 단락이 남는 공간을 차지하여 늘어남 */
}
.card .price {
font-size: 1.2em;
font-weight: bold;
color: #e67e22;
margin-top: 10px; /* 가격 위에 마진 */
}
/* 특정 카드에 Flex 아이템 속성 적용 */
.wide-card {
width: 600px; /* 더 넓은 카드 (두 칸 차지) */
flex-shrink: 0; /* 줄어들지 않도록 설정 */
}
/* 푸터 스타일 */
footer {
background-color: #34495e;
color: #ecf0f1;
text-align: center;
padding: 20px 0;
margin-top: 50px;
font-size: 0.9em;
}
/* 미디어 쿼리 (반응형: 화면 너비 768px 이하) */
@media (max-width: 768px) {
.navbar {
flex-direction: column; /* 네비게이션을 세로로 쌓음 */
align-items: flex-start; /* 왼쪽 정렬 */
padding: 15px 20px;
}
.navbar .nav-menu {
flex-direction: column; /* 메뉴 아이템 세로 정렬 */
gap: 10px;
width: 100%; /* 너비 전체 차지 */
margin-top: 15px;
}
.nav-item {
width: 100%;
text-align: center;
padding: 10px 0;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 5px;
}
.special-item {
align-self: stretch; /* 전체 너비로 늘어남 */
}
.product-cards {
flex-direction: column; /* 모바일에서는 카드들을 세로로 쌓음 */
align-items: center; /* 세로 중앙 정렬 (가로 방향) */
}
.card {
width: 90%; /* 모바일에서 카드 너비 조정 */
}
.wide-card {
width: 90%; /* 모바일에서 넓은 카드 너비 조정 */
}
}- Live Server를 통해
flexbox_layout.html파일을 열어보세요. - 상단 네비게이션 바의 로고와 메뉴가 양 끝으로 깔끔하게 정렬되고, 메뉴 아이템들이 가로로 정렬된 것을 확인하세요.
- 상품 카드들이 가로로 배치되고, 화면 너비가 좁아지면 자동으로 다음 줄로 넘어가는 것을 확인하세요.
gap속성으로 카드 사이의 간격이 유지되는 것도 확인하세요. - 특히 브라우저 창의 너비를 조절해 보세요. 768px 이하로 줄어들면 네비게이션 바와 상품 카드 레이아웃이 자동으로 바뀝니다. 이는 미디어 쿼리와 Flexbox를 함께 사용한 결과입니다.
이번 장에서는 현대 웹 레이아웃의 핵심 기술인 Flexbox(Flexible Box Layout)에 대해 깊이 있게 학습했습니다. Flexbox가 컨테이너와 아이템이라는 두 가지 주요 개념을 중심으로 작동하며, 주축과 교차축의 개념을 통해 아이템의 정렬과 공간 분배를 제어한다는 것을 이해했습니다.
컨테이너에 적용하는 display, flex-direction, flex-wrap, justify-content, align-items, align-content 속성들을 통해 전체적인 레이아웃 방향과 정렬 방식을 제어하는 방법을 배웠습니다. 또한, 아이템에 적용하는 order, flex-grow, flex-shrink, flex-basis, align-self 속성들을 통해 개별 아이템의 순서, 크기, 정렬을 조절하는 방법도 익혔습니다.
Flexbox는 한 방향으로 배치되는 요소를 정렬하고 간격을 조정할 때 자주 사용됩니다. 이 장에서 배운 내용을 바탕으로 복잡한 UI도 쉽게 구성할 수 있는 기반을 다지게 되었습니다.
아래 다이어그램은 Flexbox 컨테이너와 아이템 속성이 레이아웃을 조절하는 방식을 요약한 것입니다.
아래 다이어그램은 Flexbox 속성을 축, 정렬, 줄바꿈 기준으로 고르는 방법을 정리한 것입니다.
아래 다이어그램은 Flexbox의 기본 개념: 컨테이너와 아이템을 레이아웃 조건, 스타일 선언, 화면 확인 순서로 정리합니다.
Flexbox 레이아웃에서 다시 볼 기준과 확인 순서를 정리했습니다.
다음 학습으로 넘어가기 전, Flexbox 레이아웃에서 남은 개념 경계와 실습 확인 포인트를 점검합니다.