AD JB Toolbox 01

CSS 강좌 / Grid로 행과 열 만들기

CSS Grid는 부모 안에 행과 열을 만들고 자식 요소를 격자에 배치하는 레이아웃입니다. display: grid로 컨테이너를 만들고 grid-template-columns와 grid-template-rows로 열과 행을 지정하며, 지정한 행이 부족하면 자동 행이 생성됩니다.

Grid의 컨테이너·격자선·트랙·셀 구분하기

Grid 컨테이너는 display: grid를 적용한 부모이고, Grid 아이템은 그 부모의 직접 자식입니다. 첫 자식 안에 있는 자식까지 바깥 격자의 독립 아이템이 되는 것은 아닙니다. CSS에서 격자를 그려도 HTML 요소가 새로 생기지 않으며 각 자식이 격자의 어느 영역에 놓일지 계산하는 방식이 바뀝니다.

2열 2행 Grid에서 격자선 번호, 한 열의 트랙, 하나의 셀과 두 셀을 연결한 영역을 구분한 도해

용어 뜻 2열 2행의 예
격자선(line) 행과 열을 구분하는 경계선 세로선 3개, 가로선 3개
트랙(track) 인접한 두 격자선 사이의 한 행 또는 한 열 첫 열, 둘째 행
셀(cell) 한 행과 한 열이 만나는 최소 영역 왼쪽 위의 한 칸
영역(area) 하나 이상의 셀로 만든 직사각형 두 열에 걸친 제목 영역

선 번호와 열 번호는 다릅니다. 두 열의 바깥 경계까지 세면 세로선은 1·2·3입니다. 아이템을 1번 선부터 3번 선까지 놓으면 두 열을 차지합니다. gap은 트랙 사이의 간격이며 아이템의 padding이나 테두리와는 별도로 계산됩니다. 개발자 도구의 Elements에서 grid 표시를 켜면 선 번호와 실제 영역을 확인하기 쉽습니다. MDN의 Grid 기본 개념에 용어와 기본 동작이 정리되어 있습니다.

px·%·fr로 열 너비 지정하기

.grid {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 16px;
}

이 부분 코드는 전체 예제의 .grid 규칙 안에서 열 선언을 바꾸어 비교할 수 있습니다. 첫 열은 160px, 둘째 열은 남는 공간을 사용합니다. fr은 분수 단위(fraction)로, 다른 트랙과 gap 등을 고려한 뒤 남는 공간을 비율로 나눕니다. 첫 열을 내용과 관계없이 고정하면 좁은 화면에서 본문이 너무 좁아질 수 있으므로 실제 콘텐츠와 함께 판단하세요.

너비 640px인 컨테이너에서 gap이 16px이고 두 열이 1fr·2fr이면 분배할 공간은 624px입니다. 최소 크기 제약이 개입하지 않는 조건에서 첫 열은 208px, 둘째 열은 416px입니다. 전체 예제는 minmax(0, 1fr) minmax(0, 2fr)를 사용해 트랙의 최소 너비가 콘텐츠 때문에 크게 고정되지 않도록 합니다.

50% 50%와 gap: 16px을 함께 쓰면 열만으로 이미 컨테이너 너비를 채운 뒤 gap이 더해져 넘칠 수 있습니다. 동일한 유동 열에는 fr이 간편합니다. 그렇다고 모든 열을 같은 비율로 만들 필요는 없습니다. 목록의 이름 열은 작고 설명 열은 넓어야 할 수 있으며, 고정 열과 유동 열의 조합도 사용할 수 있습니다.

명시적 행과 자동으로 생기는 행 이해하기

grid-template-rows: 80px는 첫 행 하나를 명시적으로 정의합니다. 뒤의 아이템을 놓을 행이 부족하면 암시적 행(implicit row)이 생기며, 그 크기는 grid-auto-rows로 조절할 수 있습니다. 열을 두 개 만들었다고 행이 두 개로 제한되는 것은 아닙니다.

행 크기 동작 주의할 상황
auto 내용과 컨테이너의 공간·정렬 조건에 따라 크기를 정함 고정 높이 컨테이너에서는 남는 공간이 반영될 수 있음
100px 행 높이를 고정 내용이 길면 아이템이나 글자가 넘칠 수 있음
minmax(100px, auto) 최소 100px을 확보하고 필요하면 커짐 내용이 늘어날 수 있는 카드에 유용

고정 행은 이미지 슬롯처럼 크기 조건이 명확한 곳에서 사용할 수 있지만, 설명 문단이 들어가는 카드에서는 글자 크기 확대나 번역으로 줄 수가 늘어날 수 있습니다. minmax의 최대값 auto는 모든 행의 높이를 똑같이 만들라는 의미가 아닙니다. 각 행의 콘텐츠와 레이아웃 조건에 따라 필요한 높이가 달라집니다. MDN의 grid-auto-rows 설명에서 명시적 행 밖의 크기 규칙을 확인할 수 있습니다.

격자선과 span으로 아이템 배치하기

.feature {
  grid-column: 1 / -1;
}
/* 같은 2열 명시적 격자에서 두 열에 걸치는 다른 표현 */
/* .feature { grid-column: span 2; } */

1 / -1은 명시적 격자의 첫 선부터 마지막 선까지라는 뜻입니다. 2열에서도 1열로 바뀐 화면에서도 전체 너비를 차지하는 제목이나 강조 영역에 적합합니다. 음수 선 번호는 명시적 격자의 끝을 기준으로 세며 자동 생성된 모든 트랙의 끝을 뜻하지는 않습니다.

span 2는 두 트랙을 차지하라는 뜻이며, 정확한 시작 선을 지정하지 않으면 자동 배치가 위치를 정합니다. 모바일에서 열이 하나뿐인데 span 2를 그대로 유지하면 의도치 않은 추가 열을 만들 수 있습니다. 전체 너비를 유지할 목적이면 1 / -1을 사용하거나 모바일에서 span 값을 다시 지정하세요. 배치 지정을 최소화하면 남은 아이템은 기본적으로 HTML 순서에 따라 빈 셀로 들어갑니다.

전체 예제로 열·행·전체 너비 영역 확인하기

아래 코드를 grid-basics.html로 저장해 엽니다. A·B는 첫 고정 행, C는 전체 열을 차지하는 자동 행, D·E는 그다음 자동 행에 놓입니다. 480px 이하에서는 열이 하나로 바뀌며 C는 계속 전체 너비를 차지합니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>grid-basics.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
 grid-template-rows: 80px; grid-auto-rows: minmax(100px, auto); gap: 16px;
 width: min(100%, 640px); }
 .grid > div { min-width: 0; padding: 12px; background: #dceefa; overflow-wrap: anywhere; }
 .feature { grid-column: 1 / -1; }
 @media (max-width: 480px) { .grid { grid-template-columns: minmax(0, 1fr); } }
  </style>
</head>
<body>
<h1>열 비율과 행 높이</h1>
<div class="grid"><div>A: 첫 행</div><div>B: 첫 행</div><div class="feature">C: 두 열을 차지하는 영역입니다. 내용이 늘어나면 이 자동 행의 높이도 늘어납니다.</div><div>D: 다음 행</div><div>E: 설명이 긴 카드입니다. 콘텐츠의 길이에 따라 필요한 높이가 달라집니다. 고정된 높이에 모든 내용을 억지로 맞추는 대신 최소 높이 이후에는 내용을 수용하도록 설정합니다.</div></div>
</body>
</html>
  1. 넓은 화면에서 .grid 너비가 640px인지 확인하고 개발자 도구의 Grid 표시를 켭니다. 열은 208px·416px, 사이 간격은 16px입니다. 열 비율을 1fr·1fr로 바꾸면 각각 312px이 됩니다. 비교 후 1fr·2fr로 복원합니다.
  2. 첫 행의 높이는 80px입니다. A 안에 문장을 여러 줄 추가하면 행 높이 자체는 그대로이고 내용이 넘칠 수 있습니다. 텍스트를 원래대로 돌린 뒤 grid-template-rows를 minmax(80px, auto)로 바꾸면 내용에 따라 커질 수 있습니다.
  3. C의 내용을 충분히 늘립니다. grid-auto-rows가 minmax(100px, auto)이므로 행이 100px보다 커질 수 있습니다. grid-auto-rows만 100px로 바꾸어 고정 행의 차이를 관찰한 뒤 원래 값으로 되돌립니다.
  4. C의 grid-column 선언만 제거하면 C가 한 셀에 들어가고 뒤 아이템의 위치도 바뀝니다. 다시 1 / -1을 복원합니다. 화면을 480px 아래로 좁혀 전체 너비 지정이 1열에서도 유지되는지 확인합니다.

긴 콘텐츠와 모바일 넘침 확인하기

Grid의 1fr 트랙은 기본적인 자동 최소 크기 때문에 긴 문자열에 끌려 넓어질 수 있습니다. minmax(0, 1fr)는 트랙의 최소 크기를 0으로 두는 방법이고, 문자열의 실제 줄바꿈은 별도 규칙이 필요합니다. 아이템 자체에도 상황에 따라 min-width: 0을 적용합니다. 다음 코드는 grid-long-text.html로 저장합니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>grid-long-text.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px;
 width: min(100%, 600px); }
 .grid > div { padding: 12px; background: #e8f5de; overflow-wrap: anywhere; }
  </style>
</head>
<body>
<h1>Grid의 최소 크기와 긴 문자열</h1><div class="grid"><div>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</div><div>보통 길이의 설명</div></div>
</body>
</html>
  1. overflow-wrap만 normal로 바꾸어 트랙 너비는 유지되어도 글자가 밖으로 넘칠 수 있음을 확인합니다.
  2. 그 상태에서 두 열을 1fr 1fr로 바꾸면 긴 문자열의 최소 크기가 열 배분에 미치는 영향을 볼 수 있습니다. 비교 후 minmax(0, 1fr) 두 개와 anywhere를 복원합니다.

반응형 전환점은 기기 이름보다 실제 내용이 읽히는 너비를 기준으로 선택하세요. 이 예제의 480px은 학습을 위한 선택이며 모든 Grid의 기준이 아닙니다. 화면을 좁히고 글자를 확대해 고정 행, 긴 문자열, span이 만든 추가 열을 함께 확인하면 넘침의 원인을 구분할 수 있습니다.

같은 카테고리의 다른 글
CSS / Tutorial / 표 꾸미기 / 테두리

CSS / Tutorial / 표 꾸미기 / 테두리

테두리는 border 속성으로 만듭니다. table, th, td 요소에 적용할 수 있습니다. tr 요소에는 적용되지 않습니다.

CSS 강좌 / 미디어 쿼리와 콘텐츠 기준 분기점 만들기

CSS 강좌 / 미디어 쿼리와 콘텐츠 기준 분기점 만들기

카드의 최소 폭과 여백을 기준으로 미디어 쿼리 분기점을 정합니다. 1·2·3열 전체 예제와 경계값 비교로 조건이 적용되는 과정을 확인합니다.

CSS / Tutorial / position의 값이 fixed일 때 가운데 정렬하는 방법

CSS / Tutorial / position의 값이 fixed일 때 가운데 정렬하는 방법

position의 fixed를 이용하여 요소의 위치를 고정시킬 수 있습니다. 예를 들어 상단에 고정되는 메뉴바를 만들 때 사용합니다. 그런데, fixed를 하면 요소가 한쪽으로 치우칩니다. 만약 가운데에 위치시키고 싶다면 어떻게 할까요? transform 속성으로 해결할 수 있습니다.

CSS 강좌 / 배경색과 배경 이미지 설정하기

CSS 강좌 / 배경색과 배경 이미지 설정하기

실습용 이미지를 내려받아 배경색과 배경 이미지 경로를 설정합니다. cover·contain의 잘림과 빈 공간, 반복과 위치를 비교하고 배경이 안 보일 때의 확인 순서를 설명합니다.

CSS / Tutorial / 표 꾸미기 / 정렬

CSS / Tutorial / 표 꾸미기 / 정렬

표와 관련된 정렬에는 표 정렬, 셀 안의 내용 가로 정렬, 셀 안의 내용 세로 정렬이 있습니다. 기본 모양은 다음과 같습니다. 표(table) : 왼쪽 정렬 제목 셀(th) 안의 내용 가로 정렬 : 가운데 정렬 내용 셀(td) 안의 내용 세로 정렬 : 왼쪽 정렬 셀 안의 내용 세로 정렬 : 가운데 정렬

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

요소·클래스·ID·속성 선택자를 같은 HTML에 적용해 대상과 결과를 비교합니다. 복합 클래스, 공백으로 구분한 속성값, 필수 입력칸을 포함한 전체 예제와 선택자 수정 실습을 제공합니다.

CSS Tutorial / !important

CSS Tutorial / !important

CSS에서 !important는 특정 스타일 규칙이 다른 모든 스타일 규칙보다 우선 적용되도록 강제하는 데 사용됩니다. 이 키워드는 일반적인 스타일 우선 순위를 무시하고, 해당 스타일이 다른 어떤 스타일보다도 높은 우선순위를 가지도록 합니다.

CSS 강좌 / 넘치는 콘텐츠와 긴 문자열 처리하기

CSS 강좌 / 넘치는 콘텐츠와 긴 문자열 처리하기

같은 내용에 visible·hidden·auto·scroll을 적용해 넘침 처리를 비교합니다. 긴 URL 줄바꿈과 실제 말줄임표 예제를 실행하고, 원문 보존과 키보드 스크롤을 함께 확인합니다.

CSS 강좌 / 색상 값과 px·em·rem·% 단위 이해하기

CSS 강좌 / 색상 값과 px·em·rem·% 단위 이해하기

색상 표기와 px·em·rem·%의 계산 기준을 비교합니다. 중첩된 글자 크기와 여백이 있는 상자 예제로 실제 크기를 계산하고 개발자 도구에서 확인할 수 있습니다.

CSS 강좌 / 테두리, 둥근 모서리, 그림자 만들기

CSS 강좌 / 테두리, 둥근 모서리, 그림자 만들기

테두리와 윤곽선의 차이, 둥근 모서리, 그림자의 이동·흐림·퍼짐을 설명합니다. 원·타원과 부모 영역에서 그림자가 잘리는 상황을 실제 예제로 비교합니다.