什么是栅格
现在很多的 UI 组件库都提供了栅格系统,在响应式方面非常的方面,今天我们来谈的是 CSS 原生的栅格系统。
栅格系统是一个二维系统,他可以同时处理行和列
栅格系统很强大,但是兼容性并不是特别好(我感觉其实已经可以了),截至目前(2022.6.30)grid 的兼容性如下
绘制栅格
使用 display: grid; 声明一个 grid 容器。
绘制行列需要使用grid-template-rows
声明行的高度,grid-template-columns
声明列的宽度
<style> .grid { width: 200px; height: 200px; border: 1px solid silver; display: grid; grid-template-rows: 100px 100px; grid-template-columns: 100px 100px; } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } </style> <div class="grid"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> </div> 复制代码
上面的示例中声明了一个 2*2 的 grid,并且固定量宽度和高度
除了使用固定宽高,还可以使用百分比
<style> .grid { width: 200px; height: 200px; border: 1px solid silver; display: grid; grid-template-rows: 30% 70%; grid-template-columns: 50% 50%; } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } </style> <!-- <div class="triangle"></div> --> <!-- <div id="circle-rect"></div> --> <div class="grid"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> </div> 复制代码
百分比的计算是相对于 grid 容器来计算的,上面的代码表示第一行高度为 30%,第二行高度为 70%,每一列的宽度都为 50%
如果行列的百分比加起来不足 100%就会有空余区域,如果大于 100%就会超出容器范围
可以使用 repeat 函数来帮我们进行重复操作
.grid { width: 200px; height: 200px; border: 1px solid silver; display: grid; grid-template-rows: repeat(2, 50%); /*等价于 50% 50%*/ grid-template-columns: repeat(4, 25%);/*等价于 25% 25% 25% 25%*/ } 复制代码
在使用 repeat 来进行重复操作时,可以传入多个数值,比如repeat(2, 100px 50px),等价于 100px 50px 100px 50px,是将第二个参数整体重复多次
除了 repeat 固定数值,还可以让 grid 自动填充
.grid { width: 200px; height: 200px; border: 1px solid silver; display: grid; grid-template-rows: repeat(auto-fill, 100px); grid-template-columns: repeat(auto-fill, 100px); } 复制代码
上面这段代码会让 div 按照每份 100px 的宽高进行自动分配,比如容器宽度不确定时,可以使用自动分配
和自动分配比较接近的是按比例划分,类似于 flex 布局中使用 flex 声明比例
.grid { width: 60%; height: 200px; border: 1px solid silver; display: grid; grid-template-rows: 1fr 2fr; grid-template-columns: 2fr 3fr; } 复制代码
第一行高度为 1/3 第二行高度为 2/3,第一列宽度为 2/5 第二列宽度为 3/5
可以使用 minmax 控制尺寸的响应式波动
.grid { width: 60%; height: 50px; border: 1px solid silver; display: grid; grid-template-rows: repeat(2, minmax(30px, 50px)); grid-template-columns: 2fr 3fr; } 复制代码
列按照比例等比划分,公有两行,每一行最小 30px, 最大 50px,如果容器范围小于所有行的最小范围,内容就会溢出
间距控制
间距控制可以使用 margin,完全没问题,但是不够优雅,我们可以使用栅格提供的间距控制属性row-gap或、column-gap或者直接使用 gap
.grid { width: 60%; height: 100px; border: 1px solid silver; display: grid; grid-template-rows: repeat(2, minmax(30px, 50px)); grid-template-columns: 2fr 3fr; gap: 20px 10px; /* 等价于 row-gap: 20px; column-gap: 10px; */ } 复制代码
使用 gap 时如果只设置一个数值,则行间距和列间距同时应用这个数值
栅格线定位
栅格线可以使用命名与编号找到,方便控制指定栅格,或将内容添加到指定栅格中。
栅格命名有两种方式,主动命名和自动命名。
自动命名就是按照栅格线从一开始向正方向计数
<style> .grid { width: 200px; height: 200px; border: 1px solid silver; display: grid; grid-template-rows: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr); } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } .grid div:first-child { grid-row-start: 1; grid-column-start: 1; grid-row-end: 2; grid-column-end: 4; } </style> <div class="grid"> <div>1</div> </div> 复制代码
控制 div 在第一条横线起始,第二条横线结束,也就是第一列;第一条竖线起始,第四条竖线结束,也就是第一、二、三列。
主动命名就是在声明 grid 行列的时候手动为栅格线命名
<style> .grid { width: 300px; height: 300px; border: 1px solid silver; display: grid; grid-template-rows: [r1-start] 100px [r1-end r2-start] 100px [r2-end r3-start] 100px [r4-end]; grid-template-columns: [c1-start] 100px [c1-end c2-start] 100px [c2-end c3-start] 100px [c4-end]; } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } .grid div:first-child { grid-row-start: r1-start; grid-column-start: c2-start; grid-row-end: r2-end; grid-column-end: c2-end; } </style> <div class="grid"> <div>1</div> </div> 复制代码
通过主动命名来实现栅格内容的填充
在手动命名栅格线的时候也可配合重复来简化操作
<style> .grid { width: 300px; height: 300px; border: 1px solid silver; display: grid; grid-template-rows: repeat(3, [r-start] 1fr [r-end]); grid-template-columns: repeat(3, [c-start] 1fr [c-end]); } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } .grid div:first-child { grid-row-start: r-start 1; grid-column-start: c-start 2; grid-row-end: r-end 2; grid-column-end: c-end 1; } </style> <div class="grid"> <div>1</div> </div> 复制代码
通过重复栅格+命名的方式我们实现了和上一个例子相同的效果
可能会有人觉得这样多此一举,这样和自动命名编号没有区别。但是,注意如果重复栅格一组只有一个格效果和自动命名是一样的,但是如果重复栅格是多组的那么效果就不一样了
上面命名的示例都是通过栅格线定位的,还可以通过偏移量来定位
.grid div:first-child { grid-row-start: r-start 2; grid-column-start: c-start 2; grid-row-end: span 2; grid-column-end: span 1; } 复制代码
通过 span 来表示使用偏移量来定位
行列定位可以使用组合模式
.grid div:first-child { grid-row: r-start 2 / r-end 3; grid-column: c-start 2 / span 1; /* grid-row: 2 / 4; grid-column: 2 / span 1; */ } 复制代码
组合模式可以将多种方式混合使用,自动命名定位、手动命名定位、偏移量定位,/
前面是start, 后面是 end
区域定位
除了使用栅格线定位还可以使用区域定位
.grid div:first-child { grid-area: 2 / 2 / 4 / 3; } 复制代码
我们使用区域定位实现了和上面示例相同的效果
区域布局同样可以使用命名栅格线来定位,同时可以混合使用
.grid div:first-child { grid-area: r-start 2 / c-start 2 / span 2 / 3; } 复制代码
可以对每一个区域进行命名,使用grid-template-areas按照每行为一组进行命名
<style> .grid { width: 300px; height: 300px; border: 1px solid silver; display: grid; grid-template-rows: 60px 1fr 60px; grid-template-columns: 60px 1fr; grid-template-areas: 'header header''nav main''footer footer'; } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } .grid div:first-child { grid-area: header; } .grid div:nth-child(2) { grid-area: main; } </style> <div class="grid"> <div>1</div> <div>2</div> </div> 复制代码
有相同命名的区域会被合并为一个区域
css 会自动将我们的命名区域的起始行和起始列命名为 【命名-start】结束列命名为【命名-end】,例如上面的 header 的grid-area 的形式为 grid-area: header-start / header-start/ header-end/ header-end。
区域和行列声明可以使用简写模式
grid-template: '栅格名称 栅格名称 栅格名称 栅格名称' 行高 '栅格名称 栅格名称 栅格名称 栅格名称' 行高 '栅格名称 栅格名称 栅格名称 栅格名称' 行高/列宽 列宽 列宽 列宽;
如果某个区域不需要命名可以使用.
作为占位符,例如
.grid { grid-template-rows: 60px 1fr 60px; grid-template-columns: 60px 1fr; grid-template-areas: 'header .''nav main''. footer'; } 复制代码
栅格流动
如果要去除栅格之的空格可以使用grid-auto-flow来控制栅格的流动,栅格布局默认 row 流动
选项 | 说明 |
column | 按列排序 |
row | 按行排列 |
dense | 元素使用前面空余栅格 |
比如
<style> .grid { width: 300px; height: 300px; border: 1px solid silver; display: grid; grid-template-rows: repeat(3, 100px); grid-template-columns: repeat(3, 100px); } .grid div { background-color: pink; background-clip: content-box; padding: 10px; border: 1px solid pink; box-sizing: border-box; } .grid div:first-child { grid-column: 1/span 2; } .grid div:nth-child(2) { grid-column: 2 / span 1; } </style> <div class="grid"> <div>1</div> <div>2</div> <div>3</div> </div> 复制代码
这个布局下的排列方式如下
将排列方式更换为 column 之后
设置为 row dense 之后
对齐方式
对齐方式是我们经常需要用到的属性,在很多时候我们都需要使用对齐来调整样式
选项 | 说明 | 对象 |
justify-content | 所有栅格在容器中的水平对齐方式,容器有额外空间时 | 栅格容器 |
align-content | 所有栅格在容器中的垂直对齐方式,容器有额外空间时 | 栅格容器 |
align-items | 栅格内所有元素的垂直排列方式 | 栅格容器 |
justify-items | 栅格内所有元素的横向排列方式 | 栅格容器 |
align-self | 元素在栅格中垂直对齐方式 | 栅格元素 |
justify-self | 元素在栅格中水平对齐方式 | 栅格元素 |
justify-content 属性的值如下
值 | 说明 |
start | 容器左边 |
end | 容器右边 |
center | 容器中间 |
stretch | 撑满容器 |
space-between | 第一个栅格靠左边,最后一个栅格靠右边,余下元素平均分配空间 |
space-around | 每个元素两侧的间隔相等。所以,栅格之间的间隔比栅格与容器边距的间隔大一倍 |
space-evenly | 栅格间距离完全平均分配 |
align-content 属性的值如下
值 | 说明 |
start | 容器顶边 |
end | 容器底边 |
center | 容器垂直中间 |
stretch | 撑满容器 |
space-between | 第一个栅格靠左边,最后一个栅格靠右边,余下元素平均分配空间 |
space-around | 每个元素两侧的间隔相等。所以,栅格之间的间隔比栅格与容器边距的间隔大一倍 |
space-evenly | 栅格间距离完全平均分配 |
justify-items 用于控制元素的水平对齐方式,可用的属性值如下
值 | 说明 |
start | 元素对齐栅格的左边 |
end | 元素对齐栅格的右边 |
center | 元素对齐栅格的中间 |
stretch | 水平撑满栅格 |
align-items 用于控制元素的垂直对齐方式,可用的属性值如下
值 | 说明 |
start | 元素对齐栅格的顶边 |
end | 元素对齐栅格的底边 |
center | 元素对齐栅格的垂直中间 |
stretch | 垂直撑满栅格 |
justify-self 与 align-self 控制单个栅格内元素的对齐方式,属性值与 justify-items 和 align-items 是一致的。
place-content 用于控制栅格的对齐方式,语法如下:
place-content: <align-content> <justify-content>
place-items 控制所有元素的对齐方式,语法如下:
place-items: <align-items> <justify-items>
place-self 控制单个元素的对齐方式,语法如下:
place-self: <align-self> <justify-self>