그리드의 열(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 기초와 레이아웃의 모든 내용을 마쳤습니다. 여러분은 이제 HTML로 콘텐츠를 만들고, CSS로 스타일을 입히며, Flexbox와 Grid를 사용하여 복잡하고 반응형인 웹 레이아웃을 설계할 수 있는 기본기를 완벽하게 다지게 되었습니다.