최근 본 글

    CSS Flexbox 기초 – 가로·세로 정렬 쉽게 하는 법

    CSS Flexbox 기초 – 가로·세로 정렬 쉽게 하는 법

    지난 글에서는 색상과 글꼴로 페이지의 분위기를 꾸미는 방법과 구글 폰트 적용법을 알아보았습니다. 이제 꽤 그럴듯한 페이지를 만들 수 있게 되었지만, 아직 해결하지 못한 큰 숙제가 하나 남아 있습니다. 바로 배치입니다. 메뉴를 가로로 나란히 놓거나, 카드 세 개를 같은 간격으로 배치하거나, 상자를 화면 정가운데에 놓는 일은 생각보다 까다롭습니다. 예전에는 이런 배치를 위해 복잡한 꼼수를 써야 했지만, 지금은 Flexbox 하나면 몇 줄의 코드로 해결됩니다. 오늘은 CSS 레이아웃의 핵심 도구인 Flexbox의 기본 개념과 주요 속성을 직접 눈으로 확인할 수 있는 예제와 함께 정리해 보겠습니다.

    1. Flexbox란 무엇인가요?

    Flexbox는 Flexible Box Layout의 줄임말로, 요소들을 한 방향(가로 또는 세로)으로 유연하게 배치하고 정렬하기 위한 CSS 기능입니다. 지난 박스 모델 글에서 div 같은 블록 요소는 한 줄을 모두 차지해 아래로 쌓인다고 배웠습니다. 그래서 div 세 개를 만들면 기본적으로 세로로 차곡차곡 쌓입니다. Flexbox를 사용하면 이 상자들을 옆으로 나란히 놓고, 간격을 똑같이 나누고, 높이를 맞추고, 가운데로 모으는 일을 아주 간단하게 할 수 있습니다.

    지금 우리가 보는 대부분의 웹사이트 상단 메뉴바, 카드형 목록, 버튼 묶음, 로그인 화면의 가운데 정렬 등이 Flexbox로 만들어져 있습니다. 그만큼 실무에서 가장 자주 쓰는 CSS 기능 중 하나이므로 확실하게 익혀 두는 것이 좋습니다.

    2. 컨테이너와 아이템 – 부모와 자식

    Flexbox를 이해하려면 먼저 두 가지 역할을 구분해야 합니다.

    • 플렉스 컨테이너(Flex Container) : display: flex를 적용한 부모 요소입니다.
    • 플렉스 아이템(Flex Item) : 컨테이너 바로 안에 있는 자식 요소들입니다.
    <div class="container">   ← 플렉스 컨테이너 (부모)
      <div class="item">1</div>   ← 플렉스 아이템 (자식)
      <div class="item">2</div>
      <div class="item">3</div>
    </div>
    
    .container {
      display: flex;
    }

    가장 중요한 포인트는 display: flex를 자식이 아니라 부모에게 준다는 것입니다. 부모에게 “너의 자식들을 플렉스 방식으로 배치해 줘”라고 명령하는 셈입니다. 초보자가 가장 많이 하는 실수가 아이템에 display: flex를 주는 것이니 꼭 기억해 두세요. 위 코드 한 줄만 적용해도 세로로 쌓여 있던 상자들이 가로로 나란히 정렬됩니다.

    적용 전 (기본)

    1
    2
    3

    display: flex 적용 후

    1
    2
    3

    3. Flexbox의 핵심 – 주축과 교차축

    Flexbox의 모든 정렬 속성은 두 개의 축을 기준으로 작동합니다. 이 개념만 이해하면 Flexbox의 절반은 이해한 것입니다.

    • 주축(Main Axis) : 아이템이 나열되는 방향입니다. 기본값은 가로(왼쪽 → 오른쪽)입니다.
    • 교차축(Cross Axis) : 주축과 수직으로 교차하는 방향입니다. 주축이 가로면 교차축은 세로입니다.
    1
    2
    3
    → 주축 (justify-content가 담당)
    ↓ 교차축 (align-items가 담당)

    그리고 Flexbox의 두 핵심 정렬 속성이 각각 하나의 축을 담당합니다. justify-content는 주축 방향 정렬을, align-items는 교차축 방향 정렬을 맡습니다. 이 짝을 기억해 두면 “가로 정렬은 뭘로 하더라?” 하고 헷갈릴 일이 없습니다.

    4. flex-direction – 배치 방향 정하기

    flex-direction은 주축의 방향, 즉 아이템이 나열되는 방향을 정합니다.

    값 배치 방향
    row (기본값)가로, 왼쪽 → 오른쪽
    row-reverse가로, 오른쪽 → 왼쪽
    column세로, 위 → 아래
    column-reverse세로, 아래 → 위

    여기서 중요한 점은 flex-direction: column으로 바꾸면 주축이 세로, 교차축이 가로로 바뀐다는 것입니다. 따라서 justify-content가 세로 정렬을, align-items가 가로 정렬을 담당하게 됩니다. 처음에는 헷갈릴 수 있지만 “justify는 항상 나열 방향, align은 그 반대 방향”이라고 기억하면 됩니다.

    5. justify-content – 주축 방향 정렬

    justify-content는 아이템들을 주축(기본: 가로) 방향으로 어떻게 배치할지, 남는 공간을 어떻게 나눌지 정합니다. 각 값의 결과를 직접 확인해 보세요.

    flex-start (기본값) – 시작점에 모으기

    1
    2
    3

    center – 가운데에 모으기

    1
    2
    3

    flex-end – 끝점에 모으기

    1
    2
    3

    space-between – 양 끝에 붙이고 사이를 균등하게

    1
    2
    3

    space-around – 각 아이템 양옆에 같은 여백

    1
    2
    3

    space-evenly – 모든 간격을 완전히 동일하게

    1
    2
    3

    실무에서 가장 많이 쓰는 값은 space-between입니다. 웹사이트 상단에서 로고는 왼쪽 끝, 메뉴는 오른쪽 끝에 배치하는 레이아웃이 바로 이 값 하나로 만들어집니다. space-around와 space-evenly는 비슷해 보이지만, space-around는 양 끝 여백이 아이템 사이 여백의 절반이고 space-evenly는 모든 여백이 같다는 차이가 있습니다.

    6. align-items – 교차축 방향 정렬

    align-items는 아이템들을 교차축(기본: 세로) 방향으로 정렬합니다. 차이를 보려면 컨테이너에 높이가 있어야 하므로, 아래 예시는 컨테이너 높이를 90px로 지정했습니다.

    stretch (기본값)

    1
    2

    flex-start

    1
    2

    center

    1
    2

    flex-end

    1
    2

    기본값인 stretch는 아이템을 컨테이너 높이에 맞게 쭉 늘립니다. 그래서 내용 길이가 다른 카드들을 Flexbox로 나란히 놓으면 자동으로 높이가 똑같이 맞춰집니다. 예전에는 이것조차 어려운 작업이었는데, Flexbox에서는 아무것도 하지 않아도 기본으로 됩니다. 아이콘과 글자를 한 줄에 놓을 때 세로 위치를 맞추려면 center를 쓰면 됩니다.

    7. 화면 정가운데 정렬 – Flexbox의 필살기

    웹 개발에서 오랫동안 “가장 어려운 일”로 농담처럼 불리던 것이 상자를 가로·세로 모두 정가운데에 놓는 것이었습니다. Flexbox로는 단 세 줄이면 됩니다.

    .container {
      display: flex;
      justify-content: center;  /* 가로 가운데 */
      align-items: center;      /* 세로 가운데 */
      height: 300px;
    }
    정가운데!

    이 세 줄은 Flexbox에서 가장 유명한 공식이니 꼭 외워 두세요. 폼 편에서 만든 로그인 화면을 브라우저 창 정가운데에 놓고 싶다면, body에 이 세 줄과 min-height: 100vh;(화면 전체 높이)를 주면 됩니다.

    8. flex-wrap과 gap – 줄바꿈과 간격

    ① flex-wrap – 줄바꿈 허용
    Flexbox는 기본적으로 아이템을 한 줄에 억지로 모두 넣으려고 합니다. 그래서 아이템이 많으면 하나하나가 찌그러지듯 좁아집니다. flex-wrap: wrap을 주면 공간이 부족할 때 아이템이 자연스럽게 다음 줄로 넘어갑니다. 상품 목록이나 갤러리처럼 개수가 많은 카드를 배치할 때 필수입니다.

    ② gap – 아이템 사이 간격
    아이템 사이에 간격을 줄 때 예전에는 각 아이템에 margin을 주고, 마지막 아이템의 margin을 따로 없애는 번거로운 작업을 했습니다. 이제는 컨테이너에 gap 속성 하나만 주면 아이템 사이에만 깔끔하게 간격이 생깁니다.

    .gallery {
      display: flex;
      flex-wrap: wrap;   /* 넘치면 다음 줄로 */
      gap: 16px;         /* 아이템 사이 16px */
    }
    1
    2
    3
    4
    5
    6
    7
    8

    위 예시는 브라우저 창 너비를 줄이거나 스마트폰으로 보면 한 줄에 들어가는 개수가 자동으로 바뀌는 것을 확인할 수 있습니다.

    9. 아이템에 주는 속성 – flex와 order

    지금까지는 컨테이너(부모)에 주는 속성이었습니다. 아이템(자식) 각각에 주는 속성도 있는데, 그중 가장 많이 쓰는 것은 flex입니다.

    ① flex – 남는 공간 나눠 갖기
    flex: 1을 주면 아이템들이 컨테이너의 남는 공간을 비율대로 나눠 가집니다. 세 아이템 모두 flex: 1이면 1:1:1로 똑같이 나누고, 가운데만 flex: 2로 주면 1:2:1 비율이 됩니다.

    모두 flex: 1

    1
    1
    1

    가운데만 flex: 2

    1
    2
    1

    시맨틱 태그 편의 실습에서 main에 flex: 3, aside에 flex: 1을 줘서 본문과 사이드바를 3:1 비율로 나눈 것이 바로 이 방법입니다. 검색창처럼 버튼은 고정 크기로 두고 입력창만 남는 공간을 모두 채우게 하고 싶을 때도 입력창에만 flex: 1을 주면 됩니다.

    ② order – 보이는 순서 바꾸기
    order는 HTML 코드 순서를 바꾸지 않고 화면에 보이는 순서만 바꿉니다. 기본값은 0이며, 숫자가 작을수록 앞에 옵니다. 다만 화면 낭독기는 HTML 순서대로 읽기 때문에, 내용의 논리적 순서가 바뀌는 곳에는 사용하지 않는 것이 좋습니다.

    ③ align-self – 특정 아이템만 따로 정렬
    align-items가 모든 아이템의 교차축 정렬을 정한다면, align-self는 특정 아이템 하나만 다르게 정렬할 때 사용합니다.

    10. 속성 정리표 – 부모용과 자식용

    적용 대상 속성 역할
    컨테이너
    (부모)
    display: flex플렉스 박스 시작
    flex-direction배치 방향(주축)
    justify-content주축 방향 정렬
    align-items교차축 방향 정렬
    flex-wrap줄바꿈 허용
    gap아이템 사이 간격
    아이템
    (자식)
    flex남는 공간 차지 비율
    order보이는 순서
    align-self개별 교차축 정렬

    표 편에서 배운 rowspan으로 정리해 보았습니다. 속성이 많아 보이지만, 실무에서 매일 쓰는 것은 display, justify-content, align-items, gap, flex 다섯 가지 정도입니다.

    11. 실습: 메뉴바와 카드 목록 만들기

    이제 Flexbox로 실제 웹사이트에서 흔히 보는 상단 메뉴바와 카드 목록을 만들어 보겠습니다. 아래 코드를 flex.html로 저장해 브라우저에서 열어보세요.

    <!DOCTYPE html>
    <html lang="ko">
    <head>
      <meta charset="UTF-8">
      <title>Flexbox 실습</title>
      <style>
        * { box-sizing: border-box; }
        body {
          margin: 0;
          font-family: sans-serif;
          background: #f5f7fb;
        }
    
        /* 메뉴바: 로고는 왼쪽, 메뉴는 오른쪽 */
        .navbar {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: 16px 32px;
          background: #264de4;
        }
        .logo {
          color: white;
          font-size: 20px;
          font-weight: bold;
        }
        .menu {
          display: flex;
          gap: 24px;
        }
        .menu a {
          color: white;
          text-decoration: none;
        }
    
        /* 카드 목록: 같은 너비, 넘치면 줄바꿈 */
        .cards {
          display: flex;
          flex-wrap: wrap;
          gap: 20px;
          max-width: 900px;
          margin: 40px auto;
          padding: 0 16px;
        }
        .card {
          flex: 1;
          min-width: 220px;
          background: white;
          border-radius: 10px;
          padding: 24px;
          display: flex;
          flex-direction: column;
        }
        .card h3 { margin: 0 0 8px; }
        .card p  { flex: 1; color: #666; }
        .card a {
          align-self: flex-start;
          padding: 8px 16px;
          background: #264de4;
          color: white;
          border-radius: 6px;
          text-decoration: none;
        }
      </style>
    </head>
    <body>
      <nav class="navbar">
        <div class="logo">코딩 공부</div>
        <div class="menu">
          <a href="#">HTML</a>
          <a href="#">CSS</a>
          <a href="#">문의</a>
        </div>
      </nav>
    
      <div class="cards">
        <div class="card">
          <h3>HTML 기초</h3>
          <p>웹페이지의 뼈대를 만드는 방법을 배웁니다.</p>
          <a href="#">보러 가기</a>
        </div>
        <div class="card">
          <h3>CSS 기초</h3>
          <p>색상, 글꼴, 여백으로 페이지를 꾸미는 방법을 배웁니다. 설명이 조금 더 길어도 카드 높이는 똑같이 맞춰집니다.</p>
          <a href="#">보러 가기</a>
        </div>
        <div class="card">
          <h3>Flexbox</h3>
          <p>요소를 자유롭게 정렬합니다.</p>
          <a href="#">보러 가기</a>
        </div>
      </div>
    </body>
    </html>

    완성된 화면은 대략 다음과 같습니다.

    코딩 공부 HTMLCSS문의

    HTML 기초

    웹페이지의 뼈대를 만드는 방법을 배웁니다.

    보러 가기

    CSS 기초

    색상, 글꼴, 여백으로 페이지를 꾸미는 방법을 배웁니다. 설명이 조금 더 길어도 카드 높이는 똑같이 맞춰집니다.

    보러 가기

    Flexbox

    요소를 자유롭게 정렬합니다.

    보러 가기

    이 실습에는 Flexbox의 실전 활용법이 여러 겹으로 담겨 있습니다. 메뉴바는 space-between으로 로고와 메뉴를 양 끝에 배치했고, 메뉴 안에서 다시 Flexbox와 gap으로 링크 간격을 맞췄습니다. 이처럼 Flexbox 안에 Flexbox를 넣는 중첩은 아주 흔한 패턴입니다. 카드 목록은 flex: 1로 너비를 똑같이 나누고, min-width와 flex-wrap으로 화면이 좁아지면 자동으로 줄이 바뀌게 했습니다. 또 각 카드를 세로 방향 Flexbox로 만들고 설명 문단에 flex: 1을 주어, 설명 길이가 달라도 버튼이 항상 카드 맨 아래에 나란히 정렬되도록 했습니다. 실무에서 정말 자주 쓰는 기법이니 꼭 직접 실행해 보세요.

    12. Flexbox에서 자주 하는 실수

    • 자식에게 display: flex를 줌 : 정렬하고 싶은 요소들의 부모에게 줘야 합니다. 아이템들을 나란히 놓고 싶다면 그것들을 감싸는 상자에 적용하세요.
    • 세로 가운데 정렬이 안 돼요 : 컨테이너의 높이가 내용만큼밖에 없어서 움직일 공간이 없는 경우입니다. 컨테이너에 height나 min-height를 지정하세요.
    • justify-content로 세로 정렬이 돼요 : flex-direction을 column으로 바꾸면 주축이 세로가 되어 justify-content와 align-items의 역할이 서로 바뀝니다.
    • 아이템이 찌그러져요 : 기본적으로 한 줄에 다 넣으려 하기 때문입니다. flex-wrap: wrap을 추가하거나 아이템에 min-width를 지정하세요.
    • 손자 요소는 정렬이 안 돼요 : Flexbox는 바로 아래 자식에게만 적용됩니다. 더 안쪽 요소를 정렬하려면 그 부모에게 다시 display: flex를 주세요.

    마무리하며

    오늘은 CSS 레이아웃의 핵심 도구인 Flexbox를 알아보았습니다. display: flex는 부모에게 준다는 원칙, 그리고 justify-content는 주축(나열 방향), align-items는 교차축(그 반대 방향)을 담당한다는 짝만 확실히 기억하면 대부분의 배치 문제를 해결할 수 있습니다. 특히 justify-content와 align-items에 center를 주는 정가운데 정렬 공식, 로고와 메뉴를 양 끝에 놓는 space-between, 줄바꿈과 간격을 한 번에 해결하는 flex-wrap과 gap, 남는 공간을 비율로 나누는 flex: 1은 앞으로 웹페이지를 만들 때마다 사용하게 될 것입니다. 오늘 실습한 메뉴바와 카드 목록을 내 마음대로 바꿔 보면서 손에 익혀 보세요.

    다음 글에서는 지금까지 만든 페이지가 스마트폰에서도 보기 좋게 바뀌도록 하는 반응형 웹과 미디어 쿼리를 다루겠습니다. 오늘 배운 Flexbox와 함께 쓰면 PC와 모바일 모두에 대응하는 페이지를 만들 수 있습니다. 궁금한 점은 댓글로 남겨 주세요!

    댓글 0

    댓글 남기기