그리드의 열(Column) 트랙의 크기와 개수를 정의합니다. 공백으로 구분하여 각 열의 너비를 지정합니다.
단위: px, %, em, rem, vw, vh 등 다양한 CSS 단위 사용 가능.
fr (Fraction): 사용 가능한 공간에 대한 비율을 나타내는 단위. 남은 공간을 유연하게 나눌 때 매우 유용합니다. (예: 1fr 2fr 1fr은 남은 공간을 1:2:1 비율로 나눔)
repeat() 함수: 동일한 크기의 트랙을 반복할 때 사용합니다. repeat(반복 횟수, 트랙 크기). (예: repeat(3, 1fr)은 1fr 1fr 1fr과 동일)
minmax() 함수: 트랙의 최소 및 최대 크기를 지정합니다. minmax(최소 크기, 최대 크기). (예: minmax(100px, 1fr)은 최소 100px, 최대 남은 공간을 차지)
auto: 콘텐츠의 크기에 맞춰 자동으로 조절되거나, 남은 공간을 균등하게 분배합니다.
.container { display: grid; /* 3개의 열: 첫 번째 200px, 두 번째 남은 공간의 2배, 세 번째 남은 공간의 1배 */ grid-template-columns: 200px 2fr 1fr; /* 4개의 동일한 열 (각각 남은 공간의 1/4) */ grid-template-columns: repeat(4, 1fr); /* 최소 150px, 최대 남은 공간을 차지하는 열들을 자동으로 생성 */ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); /* 반응형 그리드에 자주 사용 */}
.item-a { grid-column: 1 / 3; /* 첫 번째 세로 라인에서 시작하여 세 번째 세로 라인에서 끝남 (2칸 차지) */ grid-row: 1 / 2; /* 첫 번째 가로 라인에서 시작하여 두 번째 가로 라인에서 끝남 (1칸 차지) */}.item-b { grid-column: span 2; /* 두 칸 너비를 차지 */ grid-row: span 3; /* 세 칸 높이를 차지 */}
그리드 컨테이너에서 grid-template-areas로 정의된 영역 이름을 사용하여 아이템을 배치합니다. 훨씬 직관적이고 가독성이 높은 방법입니다.
컨테이너에 영역 정의:
.container { display: grid; grid-template-columns: 1fr 2fr 1fr; grid-template-rows: auto 1fr auto; grid-template-areas: "header header header" /* 첫 번째 행: 모두 header 영역 */ "nav main aside" /* 두 번째 행: nav, main, aside */ "footer footer footer"; /* 세 번째 행: 모두 footer 영역 */}
/* 기본 스타일 및 박스 사이징 */* { box-sizing: border-box; margin: 0; padding: 0;}body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f0f2f5; color: #333; line-height: 1.6;}/* Grid 컨테이너 설정 */.grid-container { display: grid; /* Grid 활성화 */ gap: 20px; /* 그리드 셀 사이의 간격 */ min-height: 100vh; /* 최소 높이를 뷰포트 높이로 설정 */ max-width: 1200px; /* 최대 너비 제한 */ margin: 0 auto; /* 중앙 정렬 */ /* 그리드 영역 이름 정의 및 배치 */ grid-template-areas: "header header header" "navbar main sidebar" "footer footer footer"; /* 각 열의 너비 정의 */ grid-template-columns: 200px 1fr 250px; /* nav 200px, main 가변, sidebar 250px */ /* 각 행의 높이 정의 */ grid-template-rows: auto 1fr auto; /* header, footer는 콘텐츠만큼, main은 남은 공간 모두 */}/* 그리드 아이템 기본 스타일 */.grid-container > * { background-color: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);}/* Grid 아이템을 정의된 영역에 배치 */.header { grid-area: header; background-color: #2c3e50; color: white; text-align: center; padding: 30px;}.header h1 { font-size: 2.8em; margin-bottom: 10px;}.navbar { grid-area: navbar; background-color: #34495e; color: white;}.navbar ul { list-style: none; padding: 0;}.navbar li { margin-bottom: 10px;}.navbar a { display: block; /* 링크 영역 확장 */ color: white; text-decoration: none; padding: 10px; border-radius: 5px; transition: background-color 0.3s ease;}.navbar a:hover { background-color: #4a6581;}.main-content { grid-area: main;}.main-content h2 { color: #2980b9; margin-bottom: 15px; border-bottom: 2px solid #2980b9; padding-bottom: 5px;}.main-content h3 { color: #4a6581; margin-top: 25px; margin-bottom: 10px;}.main-content ul { list-style-type: disc; margin-left: 20px;}.main-content li { margin-bottom: 5px;}/* 이미지 갤러리 (Grid in Grid - Flexbox와 함께 사용) */.image-gallery { display: grid; /* 갤러리 내부를 다시 그리드로 */ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); /* 최소 180px, 가변 열 */ gap: 15px; margin: 20px 0; padding: 15px; background-color: #f9f9f9; border-radius: 5px;}.image-gallery img { width: 100%; height: 150px; object-fit: cover; /* 비율 유지하며 채우기 */ border-radius: 5px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);}.sidebar { grid-area: sidebar; background-color: #ecf0f1;}.sidebar h3 { color: #2c3e50; margin-bottom: 15px;}.sidebar button { background-color: #28a745; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-top: 15px; transition: background-color 0.3s ease;}.sidebar button:hover { background-color: #218838;}.footer { grid-area: footer; background-color: #34495e; color: white; text-align: center; padding: 20px; font-size: 0.9em;}/* 반응형 디자인: 화면 너비 768px 이하 */@media (max-width: 768px) { .grid-container { /* 모바일에서는 모든 영역을 하나의 열에 세로로 쌓음 */ grid-template-areas: "header" "navbar" "main" "sidebar" "footer"; grid-template-columns: 1fr; /* 하나의 열만 사용 */ grid-template-rows: auto auto 1fr auto auto; /* 각 영역 높이 조정 */ gap: 15px; /* 간격도 조금 줄임 */ } .header, .navbar, .main-content, .sidebar, .footer { padding: 15px; /* 패딩도 줄임 */ } .navbar ul { display: flex; /* 네비게이션 메뉴를 플렉스박스로 가로 정렬 */ flex-wrap: wrap; /* 공간 부족 시 줄바꿈 */ justify-content: center; gap: 10px; } .navbar li { margin-bottom: 0; } .navbar a { padding: 8px 12px; font-size: 0.9em; } .image-gallery { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); /* 모바일 이미지 갤러리 조정 */ gap: 10px; }}
결과 확인
Live Server를 통해 grid_layout.html 파일을 열어보세요.
웹 페이지의 헤더, 네비게이션, 메인 콘텐츠, 사이드바, 푸터가 명확한 격자 형태로 배치된 것을 확인할 수 있습니다. grid-template-areas를 통해 코드에서 레이아웃 구조가 시각적으로 어떻게 보이는지 주목하세요.
브라우저 창의 너비를 조절해 보세요. 특히 768px 이하로 줄어들면, Grid 컨테이너의 grid-template-areas와 grid-template-columns 설정이 변경되어 모든 영역이 세로로 쌓이는 반응형 디자인이 적용되는 것을 확인할 수 있습니다. image-gallery와 같이 Grid 안에 Grid를 사용하여 복잡한 섹션을 만들 수도 있습니다.
이번 장에서는 2차원 레이아웃을 위한 강력한 CSS 모듈인 CSS Grid Layout에 대해 학습했습니다. Grid 컨테이너에 행과 열 트랙을 정의하고(grid-template-columns, grid-template-rows), 트랙 사이의 간격을 설정하며(gap), 아이템들을 라인 기반(grid-column, grid-row) 또는 영역 이름 기반(grid-area, grid-template-areas)으로 배치하는 방법을 배웠습니다. 또한, 그리드 셀 내부에서 아이템을 정렬하고(justify-items, align-items), 그리드 전체를 정렬하는(justify-content, align-content) 방법도 익혔습니다.
Flexbox가 1차원 배열에 강점을 가진다면, Grid는 행과 열을 함께 다루는 2차원 레이아웃에 적합합니다. 이 두 기술은 현대 웹 개발에서 거의 모든 레이아웃 문제를 해결할 수 있는 핵심 도구입니다.
이로써 3장 CSS 기초와 레이아웃의 모든 내용을 마쳤습니다. 3장에서는 HTML 구조에 CSS를 적용하고, Flexbox와 Grid로 반응형 레이아웃을 설계하는 기본 흐름을 정리했습니다.
아래 다이어그램은 CSS Grid로 페이지 영역을 설계하고 반응형으로 바꾸는 흐름을 정리한 것입니다.
아래 다이어그램은 CSS Grid를 선택해야 하는 상황과 핵심 속성의 역할을 정리한 것입니다.
Grid 레이아웃에서 다시 볼 기준과 확인 순서를 정리했습니다.
다음 학습으로 넘어가기 전, Grid 레이아웃에서 남은 개념 경계와 실습 확인 포인트를 점검합니다.