03-Grid布局
📋 学习目标
掌握CSS Grid布局系统
理解网格轨道和单元格
实现复杂二维布局
响应式网格设计
🎯 Grid基础
启用Grid布局
.container {
display: grid; /* 块级grid容器 */
/* 或 */
display: inline-grid; /* 行内grid容器 */
}
基本概念
Grid Container(网格容器)
Grid Item(网格项目)
Grid Line(网格线)
Grid Track(网格轨道)- 行或列
Grid Cell(网格单元格)
Grid Area(网格区域)
📏 容器属性
grid-template-columns / rows
.container {
/* 固定宽度 */
grid-template-columns: 200px 200px 200px;
/* 百分比 */
grid-template-columns: 33.33% 33.33% 33.33%;
/* fr单位(fraction)*/
grid-template-columns: 1fr 1fr 1fr;
/* 混合单位 */
grid-template-columns: 200px 1fr 2fr;
/* 命名网格线 */
grid-template-columns: [start] 1fr [middle] 1fr [end];
/* repeat() 函数 */
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(3, 200px);
grid-template-columns: repeat(2, 1fr 2fr); /* 1fr 2fr 1fr 2fr */
/* auto-fill:自动填充 */
grid-template-columns: repeat(auto-fill, 200px);
/* auto-fit:自动适应 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
/* 行高度 */
.container {
grid-template-rows: 100px 200px 100px;
grid-template-rows: repeat(3, 1fr);
}
minmax()函数
.container {
/* 最小200px,最大1fr */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* 最小内容大小,最大无限 */
grid-template-columns: minmax(min-content, max-content);
/* 响应式列宽 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
grid-template-areas
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
/* 空白单元格用 . 表示 */
.container {
grid-template-areas:
"header header ."
"sidebar main main"
". footer footer";
}
grid-template(简写)
.container {
/* grid-template-rows / grid-template-columns */
grid-template: 100px 1fr / 200px 1fr;
/* 配合areas */
grid-template:
"header header" 100px
"sidebar main" 1fr
"footer footer" 100px
/ 200px 1fr;
}
gap(间距)
.container {
/* 行列间距 */
gap: 20px;
/* 分别设置 */
row-gap: 20px;
column-gap: 10px;
/* 简写 */
gap: 20px 10px; /* 行 列 */
}
/* 旧属性名(兼容性)*/
.container {
grid-gap: 20px;
grid-row-gap: 20px;
grid-column-gap: 10px;
}
justify-items(水平对齐)
.container {
/* 起点对齐 */
justify-items: start;
/* 终点对齐 */
justify-items: end;
/* 居中对齐 */
justify-items: center;
/* 拉伸(默认) */
justify-items: stretch;
}
align-items(垂直对齐)
.container {
align-items: start;
align-items: end;
align-items: center;
align-items: stretch; /* 默认 */
}
place-items(复合属性)
.container {
/* align-items justify-items */
place-items: center center;
place-items: start end;
}
justify-content(网格整体水平对齐)
.container {
/* 网格总宽度小于容器时 */
justify-content: start;
justify-content: end;
justify-content: center;
justify-content: stretch;
justify-content: space-around;
justify-content: space-between;
justify-content: space-evenly;
}
align-content(网格整体垂直对齐)
.container {
height: 100vh;
align-content: start;
align-content: end;
align-content: center;
align-content: stretch;
align-content: space-around;
align-content: space-between;
align-content: space-evenly;
}
place-content(复合属性)
.container {
/* align-content justify-content */
place-content: center center;
}
grid-auto-columns / rows
.container {
/* 隐式网格的列宽 */
grid-auto-columns: 100px;
grid-auto-columns: minmax(100px, auto);
/* 隐式网格的行高 */
grid-auto-rows: 100px;
grid-auto-rows: minmax(100px, auto);
}
grid-auto-flow
.container {
/* 先行后列(默认) */
grid-auto-flow: row;
/* 先列后行 */
grid-auto-flow: column;
/* 稠密填充 */
grid-auto-flow: row dense;
grid-auto-flow: column dense;
}
🎁 项目属性
grid-column / row
.item {
/* 列起始线 / 列结束线 */
grid-column-start: 1;
grid-column-end: 3;
/* 简写 */
grid-column: 1 / 3;
/* 跨越2列 */
grid-column: span 2;
/* 从第2列开始,跨越2列 */
grid-column: 2 / span 2;
}
.item {
/* 行位置 */
grid-row-start: 1;
grid-row-end: 3;
grid-row: 1 / 3;
grid-row: span 2;
}
/* 同时设置行列 */
.item {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
grid-area
/* 方式1:指定区域名称 */
.item {
grid-area: header;
}
/* 方式2:指定位置 */
.item {
/* row-start / column-start / row-end / column-end */
grid-area: 1 / 1 / 3 / 3;
}
/* 等同于 */
.item {
grid-row: 1 / 3;
grid-column: 1 / 3;
}
justify-self / align-self
.item {
/* 水平对齐 */
justify-self: start;
justify-self: end;
justify-self: center;
justify-self: stretch;
/* 垂直对齐 */
align-self: start;
align-self: end;
align-self: center;
align-self: stretch;
}
place-self
.item {
/* align-self justify-self */
place-self: center center;
}
🎨 常见布局
等宽列布局
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
圣杯布局
.container {
display: grid;
min-height: 100vh;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
gap: 20px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
瀑布流布局
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: 10px;
gap: 16px;
}
.item {
/* 通过JavaScript动态计算 */
grid-row-end: span var(--row-span);
}
响应式网格
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
}
/* 自动适应:少于3个时拉伸,超过时换行 */
12列栅格系统
.row {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 16px;
}
.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-12 { grid-column: span 12; }
卡片布局
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
padding: 20px;
}
.card {
display: grid;
grid-template-rows: auto 1fr auto;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.card-header {
padding: 16px;
background-color: #f5f5f5;
}
.card-body {
padding: 16px;
}
.card-footer {
padding: 16px;
border-top: 1px solid #ddd;
}
图片画廊
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-auto-rows: 200px;
gap: 10px;
}
.gallery-item {
overflow: hidden;
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* 特殊尺寸 */
.gallery-item--large {
grid-column: span 2;
grid-row: span 2;
}
.gallery-item--wide {
grid-column: span 2;
}
.gallery-item--tall {
grid-row: span 2;
}
🔧 实战技巧
自动响应式布局
.auto-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 16px;
}
固定侧边栏
.layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 20px;
}
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
}
}
重叠元素
.overlap-container {
display: grid;
}
.background {
grid-column: 1;
grid-row: 1;
}
.content {
grid-column: 1;
grid-row: 1;
z-index: 1;
place-self: center;
}
命名网格线
.container {
display: grid;
grid-template-columns:
[full-start] 1fr
[content-start] minmax(0, 1200px) [content-end]
1fr [full-end];
}
.full-width {
grid-column: full-start / full-end;
}
.content-width {
grid-column: content-start / content-end;
}
📚 Grid vs Flexbox
何时使用Grid
二维布局(行和列)
复杂页面布局
需要精确控制行列
重叠元素布局
何时使用Flexbox
一维布局(行或列)
组件内部布局
内容驱动的布局
简单对齐需求
结合使用
/* Grid用于页面布局 */
.page {
display: grid;
grid-template-areas:
"header"
"main"
"footer";
}
/* Flexbox用于组件内部 */
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
📚 完整示例
杂志风格布局
<div class="magazine">
<div class="item item-1">Article 1</div>
<div class="item item-2">Article 2</div>
<div class="item item-3">Article 3</div>
<div class="item item-4">Article 4</div>
<div class="item item-5">Article 5</div>
</div>
<style>
.magazine {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 200px);
gap: 10px;
}
.item-1 {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.item-2 {
grid-column: 3 / 5;
}
.item-3 {
grid-column: 3 / 5;
}
.item-4 {
grid-column: 1 / 3;
}
.item-5 {
grid-column: 3 / 5;
}
</style>
仪表板布局
<div class="dashboard">
<header class="header">Header</header>
<nav class="sidebar">Sidebar</nav>
<main class="main">Main Content</main>
<aside class="widgets">Widgets</aside>
<footer class="footer">Footer</footer>
</div>
<style>
.dashboard {
display: grid;
height: 100vh;
grid-template-columns: 250px 1fr 300px;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header header header"
"sidebar main widgets"
"footer footer footer";
gap: 10px;
padding: 10px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.widgets { grid-area: widgets; }
.footer { grid-area: footer; }
@media (max-width: 1024px) {
.dashboard {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.widgets {
display: none;
}
}
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"footer";
}
.sidebar {
display: none;
}
}
</style>
📚 实践练习
练习1:响应式网格
创建一个响应式产品网格:
大屏4列,中屏3列,平板2列,手机1列
使用auto-fit和minmax
练习2:复杂布局
实现一个新闻网站首页:
头部、侧边栏、主内容区、广告位、底部
某些文章占据2x2格子
响应式适配
练习3:图片画廊
创建一个图片画廊:
自动适应列数
支持不同尺寸的图片
悬停效果