Flexbox로 한 줄은 잘 정렬했는데, 행과 열을 동시에 제어하려면 어떻게 해야 할까?

Grid 레이아웃 — 2차원 배치의 모든 것

Flexbox는 한 방향(주축) 정렬에 특화되어 있어요. 하지만 대시보드, 카드 목록, 매거진 레이아웃처럼 행과 열을 동시에 다루어야 할 때는 CSS Grid가 훨씬 직관적입니다. 이 글에서는 Grid의 기본 용어부터 실전 패턴까지 한 번에 정리해 보겠습니다.


1. Grid란

CSS Grid는 2차원(행 + 열) 레이아웃 시스템 입니다. 부모 요소(컨테이너)에 display: grid를 선언하면, 자식 요소(아이템)들이 행과 열로 이루어진 격자 위에 배치됩니다.

CSS
.container {
  display: grid; /* 격자 레이아웃 활성화 */
}

Flexbox가 "한 줄 안에서의 정렬"이라면, Grid는 "전체 격자판 위에서의 배치"라고 생각하면 됩니다.


2. 기본 용어

Grid를 다루려면 6가지 핵심 용어를 알아야 합니다.

용어설명
Grid Containerdisplay: grid가 선언된 부모 요소
Grid Item컨테이너의 직계 자식 요소
Grid Line트랙을 나누는 수직/수평 선 (1번부터 시작)
Grid Track인접한 두 라인 사이의 공간 — 하나의 행 또는 열
Grid Cell하나의 행 트랙과 열 트랙이 교차하는 최소 단위
Grid Area하나 이상의 셀로 이루어진 직사각형 영역

공부하다 보면 "라인 번호"가 가장 헷갈리는 부분인데, ** 컬럼 3개를 만들면 라인은 4개 **(양쪽 끝 + 사이)라는 점만 기억하면 됩니다.


3. 컨테이너 속성

grid-template-columns / rows

행과 열의 크기를 명시적으로 정의합니다.

CSS
.container {
  display: grid;
  grid-template-columns: 200px 1fr 2fr; /* 3개 컬럼 */
  grid-template-rows: 100px auto;       /* 2개 행 */
}

fr 단위

fr(fraction)은 남은 공간을 비율로 나누는 단위 입니다.

CSS
/* 1:2:1 비율로 3개 컬럼 — 가운데가 양 옆의 2배 */
grid-template-columns: 1fr 2fr 1fr;

fr은 고정 크기(px, rem 등)를 먼저 할당한 뒤 남은 공간 에 대해 비율을 계산합니다. 200px 1fr 1fr이면 200px을 빼고 나머지를 반반 나눕니다.

repeat()

반복되는 트랙 정의를 간결하게 작성합니다.

CSS
/* 동일한 너비의 4개 컬럼 */
grid-template-columns: repeat(4, 1fr);

/* 패턴 반복: 100px, 1fr을 3번 반복 → 6개 컬럼 */
grid-template-columns: repeat(3, 100px 1fr);

auto-fill vs auto-fit

둘 다 repeat() 안에서 사용하며, 컨테이너 너비에 따라 트랙 수를 자동 계산합니다.

CSS
/* auto-fill: 빈 트랙도 공간을 차지 */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

/* auto-fit: 빈 트랙을 0으로 축소 → 아이템이 늘어남 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  • auto-fill — 아이템이 적을 때 빈 트랙이 남아 있어 아이템 크기가 유지됩니다
  • auto-fit — 빈 트랙을 없애서 아이템이 남은 공간까지 차지합니다

아이템 수가 충분하면 둘의 차이가 없어요. 아이템이 적을 때만 동작이 달라지므로, 반응형 카드 그리드에서는 보통 auto-fill이 더 예측 가능합니다.

gap

행과 열 사이의 간격을 설정합니다.

CSS
.container {
  gap: 16px;          /* 행·열 동일 간격 */
  gap: 20px 16px;     /* 행 간격 20px, 열 간격 16px */
}

grid-template-areas

영역에 이름을 붙여 레이아웃을 시각적으로 설계합니다. 자세한 내용은 6장에서 다룹니다.


4. 아이템 속성

grid-column / grid-row

아이템이 차지할 영역을 라인 번호 로 지정합니다.

CSS
.item {
  grid-column: 1 / 3; /* 1번 라인 ~ 3번 라인 (2개 컬럼) */
  grid-row: 1 / 2;    /* 1번 라인 ~ 2번 라인 (1개 행) */
}

span 키워드

라인 번호 대신 "몇 칸 차지"로 지정할 수 있습니다.

CSS
.item {
  grid-column: span 2; /* 현재 위치에서 2개 컬럼 차지 */
  grid-row: span 3;    /* 3개 행 차지 */
}

grid-area

grid-row-start / grid-column-start / grid-row-end / grid-column-end를 한 줄로 축약합니다. grid-template-areas와 함께 쓸 때는 영역 이름을 지정합니다.

CSS
/* 라인 번호 축약 */
.item { grid-area: 1 / 1 / 3 / 4; }

/* Named Area 이름 지정 */
.header { grid-area: header; }

justify-self / align-self

개별 아이템의 정렬을 제어합니다.

CSS
.item {
  justify-self: center; /* 가로 방향 가운데 정렬 */
  align-self: end;      /* 세로 방향 끝 정렬 */
}

5. 암시적 그리드

grid-template-*으로 정의한 것보다 아이템이 더 많으면, Grid는 자동으로 암시적(implicit) 트랙 을 생성합니다.

CSS
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);  /* 명시적: 3개 컬럼 */
  grid-auto-rows: 150px;                   /* 암시적 행 높이 */
}

grid-auto-flow

아이템이 자동 배치되는 방향을 제어합니다.

CSS
.container {
  grid-auto-flow: row;       /* 기본값: 행 방향으로 채움 */
  grid-auto-flow: column;    /* 열 방향으로 채움 */
  grid-auto-flow: row dense; /* 행 방향 + 빈 공간 채우기 */
}

dense는 빈 공간을 줄여주지만, DOM 순서와 시각적 순서가 달라질 수 있으므로 접근성에 주의 가 필요합니다. 스크린 리더는 DOM 순서로 읽기 때문이에요.


6. Named Areas로 레이아웃 설계하기

grid-template-areas를 쓰면 코드만 봐도 레이아웃이 눈에 보입니다.

CSS
.dashboard {
  display: grid;
  grid-template-columns: 240px 1fr 1fr;
  grid-template-rows: 60px 1fr 60px;
  grid-template-areas:
    "header  header  header"   /* 상단 전체 */
    "sidebar main    aside"    /* 본문 영역 */
    "footer  footer  footer";  /* 하단 전체 */
  gap: 12px;
  min-height: 100vh;
}

/* 각 아이템에 영역 이름 연결 */
.dashboard-header  { grid-area: header; }
.dashboard-sidebar { grid-area: sidebar; }
.dashboard-main    { grid-area: main; }
.dashboard-aside   { grid-area: aside; }
.dashboard-footer  { grid-area: footer; }

핵심 규칙 몇 가지를 기억해 두면 좋습니다.

  • 영역은 반드시 직사각형 이어야 합니다 (L자 형태 불가)
  • 빈 셀은 .(마침표)로 표시합니다
  • 같은 이름이 인접해야 하나의 영역으로 인식됩니다
CSS
/* 오른쪽 사이드바 없는 레이아웃 */
grid-template-areas:
  "header  header  header"
  "sidebar main    ."        /* 마침표 = 빈 영역 */
  "footer  footer  footer";

7. 실전 패턴

반응형 카드 그리드

가장 자주 쓰이는 패턴입니다. 미디어 쿼리 없이 컨테이너 너비에 따라 컬럼 수가 자동으로 조절됩니다.

CSS
.card-grid {
  display: grid;
  /* 최소 280px, 남은 공간은 균등 분배 */
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

이 한 줄이면 화면이 넓을 때는 45개, 좁을 때는 12개 컬럼으로 자동 전환됩니다. minmax()의 최소값을 조절해서 카드의 최소 너비를 결정합니다.

대시보드 레이아웃

Named Areas와 미디어 쿼리를 결합하면 반응형 대시보드를 깔끔하게 만들 수 있습니다.

CSS
.dashboard {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas:
    "header"
    "main"
    "sidebar"
    "footer";
  gap: 16px;
}

/* 태블릿 이상 */
@media (min-width: 768px) {
  .dashboard {
    grid-template-columns: 240px 1fr;
    grid-template-areas:
      "header  header"
      "sidebar main"
      "footer  footer";
  }
}

/* 데스크톱 */
@media (min-width: 1200px) {
  .dashboard {
    grid-template-columns: 240px 1fr 300px;
    grid-template-areas:
      "header  header  header"
      "sidebar main   aside"
      "footer  footer  footer";
  }
}

grid-template-areas만 바꾸면 레이아웃 구조가 완전히 달라지니까, 미디어 쿼리와 조합했을 때 코드가 정말 읽기 좋아집니다.


정리

  • **Grid는 2차원 **, Flexbox는 1차원 — 행과 열을 동시에 제어해야 하면 Grid
  • fr 단위 는 남은 공간을 비율로 나눈다
  • auto-fill vs auto-fit 은 아이템이 부족할 때만 차이가 난다
  • Named Areas 를 쓰면 레이아웃을 시각적으로 설계할 수 있다
  • 암시적 그리드 와 grid-auto-flow를 이해하면 예상 밖의 배치를 방지할 수 있다
  • repeat(auto-fill, minmax(최소값, 1fr))은 반응형 카드 그리드의 공식이다
댓글 로딩 중...