4/30(목) HTML, CSS 기초

허경수·5일 전

프론트엔드

목록 보기
22/29

🎓 CSS Flexbox 실전 레이아웃 — Header, Nav, Main, Aside, Footer 만들기

지난 포스팅에서 배운 Flexbox 개념을 활용해서 실무에서 자주 쓰이는 전체 페이지 레이아웃을 만들어봅니다.
flex-grow, flex-basis, flex-shrink를 실제로 적용하면서 각 속성의 역할을 체득해봅시다!


01. 완성 레이아웃 구조 🗺️

┌─────────────────────────────────┐
│            header            │  ← 고정 높이
├──────┬──────────────────┬───────┤
│      │                │       │
│ nav  │      main      │ aside │  ← 남은 공간 전부
│150px │  (flex-grow:1) │ 120px │
│      │                │       │
├──────┴──────────────────┴───────┤
│            footer            │  ← 고정 높이
└─────────────────────────────────┘

핵심 아이디어: container를 세로 Flex로, content를 가로 Flex로 만들어 중첩 Flexbox 구조를 완성합니다.


02. 전체 코드 📋

HTML

<div class="container">
    <header>
        <h1>레이아웃 배우기</h1>
    </header>
    <section class="content">
        <nav>
            <ul>
                <li><a href="#">메뉴 아이템 1</a></li>
                <li><a href="#">메뉴 아이템 2</a></li>
                <li><a href="#">메뉴 아이템 3</a></li>
                <li><a href="#">메뉴 아이템 4</a></li>
            </ul>
        </nav>
        <main>
            (1절) 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세
        </main>
        <aside>
            추가적인 내용
        </aside>
    </section>
    <footer>
        <a href="#">SBS 아카데미</a>
    </footer>
</div>

CSS

/* 기본 초기화 */
body, h1 {
    margin: 0;
}

/* 전체 컨테이너 — 세로 Flex */
.container {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
    background-color: darkcyan;
}

/* 헤더 — 고정 높이 */
.container > header {
    flex-grow: 0;
    background-color: red;
}

/* 콘텐츠 영역 — 가로 Flex + 남은 공간 전부 */
.container > .content {
    display: flex;
    flex-direction: row;
    flex-grow: 1;
}

/* 왼쪽 사이드 메뉴 — 고정 너비 */
.container > .content > nav {
    flex-basis: 150px;
    flex-shrink: 0;
    background-color: gold;
}

/* 메인 콘텐츠 — 나머지 공간 전부 */
.container > .content > main {
    flex-grow: 1;
    flex-shrink: 1;
    background-color: pink;
}

/* 오른쪽 부가 정보 — 고정 너비 */
.container > .content > aside {
    flex-basis: 120px;
    flex-shrink: 0;
    background-color: purple;
}

/* 푸터 — 고정 높이 + 가운데 정렬 */
.container > footer {
    flex-grow: 0;
    background-color: green;
    display: flex;
    justify-content: center;
}

03. HTML 구조 📝

<div class="container">
    <header>
        <h1>레이아웃 배우기</h1>
    </header>

    <section class="content">
        <nav>
            <ul>
                <li><a href="#">메뉴 아이템 1</a></li>
                <li><a href="#">메뉴 아이템 2</a></li>
                <li><a href="#">메뉴 아이템 3</a></li>
                <li><a href="#">메뉴 아이템 4</a></li>
            </ul>
        </nav>

        <main>
            (1절) 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세
        </main>

        <aside>
            추가적인 내용
        </aside>
    </section>

    <footer>
        <a href="#">SBS 아카데미</a>
    </footer>
</div>

🔍 구조 한눈에 보기

.container          ← 전체 페이지 감싸기 (세로 Flex)
  ├── header        ← 상단 헤더
  ├── .content      ← 중간 콘텐츠 영역 (가로 Flex)
  │     ├── nav     ← 왼쪽 사이드 메뉴
  │     ├── main    ← 메인 콘텐츠
  │     └── aside   ← 오른쪽 부가 정보
  └── footer        ← 하단 푸터

04. CSS 단계별 분석 🎨

STEP 1 — 기본 초기화

body, h1 {
    margin: 0; /* 브라우저 기본 여백 제거 */
}

브라우저마다 body, h1 등에 기본 margin이 있습니다.
레이아웃 작업 전에 먼저 초기화하지 않으면 의도치 않은 여백이 생깁니다.


STEP 2 — container: 세로 방향 Flex 설정

.container {
    display: flex;
    flex-direction: column;  /* 자식들을 세로로 쌓기 */
    min-height: 100dvh;      /* 최소 높이 = 화면 전체 높이 */
    background-color: darkcyan;
}
속성역할
flex-direction: columncolumnheader → content → footer 순으로 세로 배치
min-height: 100dvh100dvh콘텐츠가 적어도 화면을 꽉 채움

dvh란? Dynamic Viewport Height의 약자로, 모바일 브라우저의 주소창 높이까지 고려한 화면 높이입니다. vh보다 더 정확합니다.


.container > header {
    flex-grow: 0; /* 기본값 — 남은 공간을 차지하지 않음 */
    background-color: red;
}

.container > footer {
    flex-grow: 0; /* 기본값 — 남은 공간을 차지하지 않음 */
    background-color: green;
    display: flex;
    justify-content: center; /* 푸터 내용 가운데 정렬 */
}

flex-grow: 0기본값이라 생략해도 동일하게 동작합니다.
직접 써놓으면 "이건 의도적으로 늘어나지 않게 한 것"이라는 의도를 코드로 표현할 수 있습니다.


STEP 4 — content: 가로 방향 Flex 설정 ⭐

.container > .content {
    display: flex;
    flex-direction: row; /* 자식들을 가로로 배치 (기본값) */
    flex-grow: 1;        /* header/footer를 제외한 남은 공간 전부 차지 */
}

flex-grow: 1이 핵심입니다.
header와 footer는 flex-grow: 0(고정)이고, content만 flex-grow: 1이므로
화면 높이에서 header + footer를 뺀 나머지를 content가 전부 차지합니다.

화면 전체 높이 (100dvh)
├── header  → flex-grow: 0 (내용 높이만큼)
├── content → flex-grow: 1 (나머지 전부 ← 이게 핵심!)
└── footer  → flex-grow: 0 (내용 높이만큼)

STEP 5 — nav / aside: 고정 너비 사이드바

.container > .content > nav {
    flex-basis: 150px;  /* 기본 너비 150px */
    flex-shrink: 0;     /* 화면이 좁아져도 줄어들지 않음 */
    background-color: gold;
}

.container > .content > aside {
    flex-basis: 120px;  /* 기본 너비 120px */
    flex-shrink: 0;     /* 화면이 좁아져도 줄어들지 않음 */
    background-color: purple;
}
속성역할
flex-basisFlex 아이템의 기본 크기 설정 (너비 역할)
flex-shrink: 0공간이 부족해도 줄어들지 않음
flex-shrink: 1공간이 부족하면 비율대로 줄어듦 (기본값)

flex-shrink: 0을 빼보면 화면을 좁혔을 때 nav와 aside가 쪼그라드는 걸 확인할 수 있습니다.


STEP 6 — main: 남은 공간 전부 차지

.container > .content > main {
    flex-grow: 1;   /* nav와 aside를 제외한 나머지 공간 전부 */
    flex-shrink: 1; /* 공간 부족 시 줄어들 수 있음 (기본값) */
    background-color: pink;
}
content 가로 공간
├── nav   → flex-basis: 150px (고정)
├── main  → flex-grow: 1 (나머지 전부 ← 핵심!)
└── aside → flex-basis: 120px (고정)

05. 직접 실험해보기 🧪

각 속성을 지워보면서 변화를 눈으로 확인해보세요!

지워볼 속성기본값지우면 어떻게 되나?
headerflex-grow: 00변화 없음 (기본값이라서)
navflex-shrink: 01화면을 좁히면 nav가 쪼그라듦
asideflex-shrink: 01화면을 좁히면 aside가 쪼그라듦
mainflex-shrink: 11변화 없음 (기본값이라서)
contentflex-grow: 10content가 높이를 차지 못함

📖 핵심 학습 포인트 요약

📌 중첩 Flexboxcontainer(세로 Flex) 안에 content(가로 Flex)를 넣어 2D 레이아웃을 완성합니다.

📌 flex-grow: 1 — header/footer는 0(고정), content만 1로 설정해 남은 세로 공간을 content가 가져갑니다.

📌 flex-basis — nav와 aside의 고정 너비를 설정합니다. width와 비슷하지만 Flex 환경에 최적화된 속성입니다.

📌 flex-shrink: 0 — nav와 aside가 화면이 좁아져도 줄어들지 않게 고정합니다. 1이 기본값이라 명시적으로 0을 써야 합니다.

📌 min-height: 100dvh — 콘텐츠가 적어도 화면 전체를 채우는 레이아웃을 만들 때 사용합니다.

0개의 댓글