CSS Flexbox로 만드는 Holy Grail 레이아웃과 flex 기타 속성 정리

포스트 썸네일 이미지

지난 포스트에서 Flexbox의 기본 개념을 익혔다면, 이제 그걸 활용해 실제 웹사이트의 뼈대를 만들어 볼 차례다.

웹 디자인의 '성배'라 불리는 Holy Grail 레이아웃을 Flexbox로 직접 구현해 보며, 실무에서 요긴하게 쓰이는 기타 속성들까지 함께 정리해 보겠다.




이전 포스트




생활코딩 CSS 수업 영상: flex (holy grail layout)


Holy Grail 레이아웃이란 웹사이트의 가장 전형적인 5개 구역을 배치한 형태를 말한다.


  • Header: 상단 제목 / 메뉴
  • Nav: 좌측 네비게이션
  • Main: 중앙의 핵심 컨텐츠
  • Aside: 우측 광고나 부가 정보
  • Footer: 하단 정보


웹 디자인에서 이 Holy Grail 레이아웃은 수십 년간 개발자들이 꿈꿔온 가장 이상적인 레이아웃이었다.

과거에는 구현하기가 매우 까다로워 '성배'라는 이름이 붙었지만, 이제는 Flexbox 덕분에 아주 쉽게 구현할 수 있게 되었다.




<!DOCTYPE html>
<html>
<head>
    <style>
        .container {
            display: flex;
            flex-direction: column
        }
        header {
            border-bottom: 1px solid gray;
            padding-left: 20px;
        }
        footer {
            border-top: 1px solid gray;
            padding: 20px;
            text-align: center;
        }
        .content {
            display: flex;
        }
        .content nav {
            border-right: 1px solid gray;
        }
        .content aside {
            border-left: 1px solid gray;
        }
        nav, aside {
            flex-basis: 150px;
            flex-shrink: 0;
        }
        main {
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>생활코딩</h1>
        </header>
        <section class="content">
            <nav>
                <ul>
                    <li>html</li>
                    <li>css</li>
                    <li>javascript</li>
                </ul>
            </nav>
            <main>
                Lorem ipsum dolor sit amet consectetur, adipisicing elit. Minus ipsam reiciendis voluptates soluta delectus, quo at tenetur numquam illum possimus a quia! Aperiam perferendis error deserunt amet fuga, porro deleniti quos, optio saepe veniam ipsum suscipit voluptate expedita facilis quidem, nisi provident commodi libero aliquid assumenda repellendus. Harum temporibus distinctio, dolor neque ut laudantium reprehenderit praesentium molestiae deleniti officia vel ea provident, quaerat tempora facilis quasi non eaque aliquam optio vitae, aut consequatur rerum eius? Blanditiis necessitatibus ad tenetur deserunt, vel impedit, doloremque ab est debitis sed minima possimus et suscipit, rem ipsa odio soluta ipsum at dolores alias recusandae? Dolores iste harum fugiat magni voluptates necessitatibus molestias accusantium officia doloremque aperiam provident, laboriosam facere, vel, et hic unde perspiciatis quisquam ea minus dicta. Aut neque doloribus iusto laborum cumque. Nobis asperiores, odio rem dignissimos a deserunt unde eaque esse atque qui consectetur illum id minus est quae assumenda aut modi velit consequuntur necessitatibus dolorem error provident soluta! Molestiae unde nihil voluptate consectetur ducimus qui rem iusto deleniti excepturi. Tenetur, sapiente reiciendis, consectetur eum dolor eos quaerat mollitia esse facere aperiam quos quidem! Porro dignissimos corporis iure? Cupiditate, odio dignissimos molestias illum quos eum nihil tempore atque non doloribus exercitationem, perspiciatis assumenda esse autem expedita dolorem et architecto sint. Consequatur eos inventore natus atque debitis pariatur fuga culpa rem delectus enim incidunt quod sit, vero tempore sequi cupiditate voluptatem aliquid distinctio cumque a quasi nobis quidem? Iste quam ab adipisci perspiciatis sunt cum quia, eius repellendus in! Adipisci esse tenetur quas, labore sequi assumenda maxime, placeat, delectus reiciendis mollitia nesciunt doloribus. Cum, nam natus? Ex molestias cum aliquid sed autem non minima officiis ipsum magni corporis nam vitae quam, dignissimos veritatis ipsa velit. Natus vitae exercitationem deleniti incidunt, itaque esse, maiores expedita ex consequatur, sapiente repellat quam non reprehenderit eligendi ipsa sunt modi libero! Quasi, nobis neque distinctio harum ad veniam enim dolorem eum eligendi voluptatibus voluptas fuga veritatis tempore.
            </main>
            <aside>
                AD
            </aside>
        </section>
        <footer>
            <a href="https://opentutorials.org/course/1">홈페이지</a>
        </footer>
    </div>
</body>
</html>

위의 생활코딩 수업 영상에서 사용한 코드다.

이 코드로 어떻게 Holy Grail 레이아웃을 완성할 수 있는지 분석해 보겠다.





1단계: 수직 쌓기 (전체 구조)

.container {
    display: flex;
    flex-direction: column;
}
  • 역할: 전체 페이지를 큰 바구니(.container)에 담고, 위에서 아래로(column) 쌓는다.
  • 결과: Header - Content(중앙 영역) - Footer가 순서대로 세로로 배치된다.



2단계: 수평 펼치기 (중앙 핵심)

.content {
    display: flex;
}
  • 역할: 중앙 영역인 .content 섹션에 다시 한번 display: flex;를 준다. (기본값이 row이므로 가로로 배치된다.)
  • 결과: Nav - Main - Aside가 나란히 옆으로 서게 된다. 이때 Flexbox의 특징 덕분에 세 요소의 높이가 자동으로 가장 긴 요소에 맞춰 똑같아진다.



3단계: 크기 고정과 유연성 조절

nav, aside {
    flex-basis: 150px;
    flex-shrink: 0;
}
  • flex-basis: 150px;: 좌우 사이드바의 기본 너비를 150px로 고정한다.
  • flex-shrink: 0;: 화면이 좁아지더라도 이 사이드바들은 절대 줄어들지 말고 150px을 유지하라는 뜻이다. 덕분에 메뉴와 광고창이 찌그러지지 않는다.
  • main은 특별한 설정이 없어도 남는 공간을 모두 차지하며 브라우저 너비에 따라 유연하게 늘어난다.




이렇게 Flexbox를 이용해서 부모 컨테이너는 column으로 세로 뼈대를 잡고, 중앙 컨텐츠는 다시 row로 가로 배치를 하여 사이드바 너비만 고정(flex-shrink: 0)하면 쉽게 Holy Grail 레이아웃을 완성할 수 있다.





생활코딩 CSS 수업 영상: flex (기타 속성들)


드디어 flex 관련 마지막 수업 영상이다.




수업 영상에서 나오는 생활코딩의 flex 관련 웹페이지의 링크다.




1. 부모(컨테이너)에 적용하는 속성들

  • flex-direction: 아이템이 쌓이는 방향(가로 세로)과 정방향/역방향 여부를 결정한다.
  • flex-wrap: 자식들이 한 줄에 다 안 들어갈 때, 다음 줄로 넘길지 아니면 삐져나가게 둘지 정한다.
  • align-items: 수직축(기본 세로)을 기준으로 자식들이 한 줄 안에서 어떻게 정렬될지 결정한다.
  • justify-content: 메인축(기본 가로)을 기준으로 자식들 사이의 간격과 정렬(좌, 우, 중앙 등)을 조절한다.
  • align-content: flex-wrap으로 줄바꿈이 생겨 여러 줄이 되었을 때, 그 줄들 사이의 간격을 조절한다.



2. 자식(아이템)에 적용하는 속성들

flex-growflex-shrink는 이전 포스트에서 이미 다뤘지만, 다시 한번 정리한다.


  • align-self: 부모가 정한 align-items 규칙을 무시하고, 해당 아이템만 따로 수직 정렬하고 싶을 때 쓴다.
  • flex-grow: 형제 요소들 사이에서 남는 빈 공간을 어떤 비율로 나누어 가져서 커질지 결정한다.
  • flex-shrink: 공간이 부족할 때 어떤 비율로 자신을 깎아서 줄어들지 결정한다.
  • flex: flex-grow, flex-shrink, flex-basis를 한 줄에 선언하는 축약형 속성이다.
  • order: HTML 코드 순서와 상관없이 화면에 보여지는 시각적 배치 순서를 숫자로 지정한다.





<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .container {
            display: flex;
            flex-direction: column;
            width: 800px;
            border:1px solid gray;
        }
        header {
            border-bottom: 1px solid gray;
            padding-left: 20px;
        }
        footer {
            border-top: 1px solid gray;
            padding: 20px;
            text-align: center;
        }
        .content {
            display: flex;
        }
        .content nav {
            border-right: 1px solid gray;
        }
        .content aside {
            border-left: 1px solid gray;
        }
        nav, aside {
            flex-basis: 150px;
            flex-shrink: 0;
        }
        main {
            padding: 10px;
        }
        nav {
            order: -1;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>생활코딩</h1>
        </header>
        <section class="content">
            <main>
                Lorem ipsum dolor sit amet consectetur, adipisicing elit. Minus ipsam reiciendis voluptates soluta delectus, quo at tenetur numquam illum possimus a quia! Aperiam perferendis error deserunt amet fuga, porro deleniti quos, optio saepe veniam ipsum suscipit voluptate expedita facilis quidem, nisi provident commodi libero aliquid assumenda repellendus. Harum temporibus distinctio, dolor neque ut laudantium reprehenderit praesentium molestiae deleniti officia vel ea provident, quaerat tempora facilis quasi non eaque aliquam optio vitae, aut consequatur rerum eius? Blanditiis necessitatibus ad tenetur deserunt, vel impedit, doloremque ab est debitis sed minima possimus et suscipit, rem ipsa odio soluta ipsum at dolores alias recusandae? Dolores iste harum fugiat magni voluptates necessitatibus molestias accusantium officia doloremque aperiam provident, laboriosam facere, vel, et hic unde perspiciatis quisquam ea minus dicta. Aut neque doloribus iusto laborum cumque. Nobis asperiores, odio rem dignissimos a deserunt unde eaque esse atque qui consectetur illum id minus est quae assumenda aut modi velit consequuntur necessitatibus dolorem error provident soluta! Molestiae unde nihil voluptate consectetur ducimus qui rem iusto deleniti excepturi. Tenetur, sapiente reiciendis, consectetur eum dolor eos quaerat mollitia esse facere aperiam quos quidem! Porro dignissimos corporis iure? Cupiditate, odio dignissimos molestias illum quos eum nihil tempore atque non doloribus exercitationem, perspiciatis assumenda esse autem expedita dolorem et architecto sint. Consequatur eos inventore natus atque debitis pariatur fuga culpa rem delectus enim incidunt quod sit, vero tempore sequi cupiditate voluptatem aliquid distinctio cumque a quasi nobis quidem? Iste quam ab adipisci perspiciatis sunt cum quia, eius repellendus in! Adipisci esse tenetur quas, labore sequi assumenda maxime, placeat, delectus reiciendis mollitia nesciunt doloribus. Cum, nam natus? Ex molestias cum aliquid sed autem non minima officiis ipsum magni corporis nam vitae quam, dignissimos veritatis ipsa velit. Natus vitae exercitationem deleniti incidunt, itaque esse, maiores expedita ex consequatur, sapiente repellat quam non reprehenderit eligendi ipsa sunt modi libero! Quasi, nobis neque distinctio harum ad veniam enim dolorem eum eligendi voluptatibus voluptas fuga veritatis tempore.
            </main>
            <nav>
                <ul>
                    <li>html</li>
                    <li>css</li>
                    <li>javascript</li>
                </ul>
            </nav>
            <aside>
                AD
            </aside>
        </section>
        <footer>
            <a href="https://opentutorials.org/course/1">홈페이지</a>
        </footer>
    </div>
</body>
</html>

코드가 조금 수정됐다.


body{ }를 추가하고 그 안에 display: flex;align-items: center;justify-content: center;를 넣어서 body의 모든 콘텐츠가 가운데로 정렬되게 했다.


.container{ } 에는 width: 800px;을 추가했다.

이전에는 박스가 화면 전체 너비를 차지했다면, 이제는 800px이라는 고정된 너비를 가지게 돼서 전체 레이아웃이 화면 중앙에 콤팩트하게 모여 보이게 된다.


<nav><main> 태그의 순서를 바꿨지만, nav { order: -1; }를 추가해서 원래대로 nav를 main보다 먼저 오게 했다.




다음 포스트

이 글이 도움이 됐거나 유익했다면 스크롤을 조금만 더 내려서 댓글을 남겨주세요. (비로그인도 가능합니다!)
응원이나 피드백이 담긴 댓글은 제가 계속 블로그를 해나갈 수 있는 원동력이 됩니다. 😊

지인에게 보여주고 싶은 글이었다면 URL을 복사해서 메신저나 소셜 미디어에 공유해 주세요.

댓글 쓰기

0 Comments

문의하기 양식