Grid 布局概念
CSS Gird 已经被 W3C 纳入到 css3 的一个布局模块中, 被称为 CSS Grid Layout Module, 一般习惯称为网格布局
网格布局可以将应用程序分割成不同的空间, 定义它们的大小位置和层级
简单来说, 网格布局就像表格一样可以让元素按列和行对齐排列, 不同的是, 网格布局没有内容结构, 比如一个网格布局的子元素可以定位自己的位置, 可以是实现类似定位的效果
兼容性
可以看到几大浏览器都已经支持了 Grid 布局, 接下来我们来一步步的来玩转 Grid 布局
grid vs flex
我们知道 flex 和 grid 都是 css3 新的布局方式, 如果浏览器都支持两种布局, 你会选择那种呢? 当我们了解两者以后就能做出正确的选择了
flex 布局是一维布局, grid 布局是二维布局
网格容器和网格项
我们知道给一个元素设置了 display:flex 就指定了 flex 弹性布局, 实现 grid 布局一样简单, 给元素设置 display:grid 就可以了
- <style>
- .container{
- display: grid;
- }
- </style>
- <div class="container">
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- </div>
container 就是一个网格容器, 里面的 item 就是网格项
网格术语
网格线 grid lines
网格线组成了网格, 是网格水平和垂直的分界线
网格轨道 grid track
就是两条网格线之间的空间, 可以理解成表格里面的行或者列, 网格里面为 grid-row 和 grid-column, 网格轨道可以设置大小, 来控制高度或者宽度
上图 grid-column2 和 grid-column3 之间的区域就是一个网格轨道
网格单元格 grid cell
就是四条网格线之间的空间, 是最小的单位
网格区域
也是四条网格线组成的空间, 可能包含一个或者多个单元格
实现一个 grid 布局
了解网格个相关概念, 接下来我们来创建一个简单的 grid 布局
上面我们说网格轨道的时候说了可以给网格轨道设置大小, 可以控制高度或者宽度
- html
- <div class="grid">
- <div class="item-1">1</div>
- <div class="item-2">2</div>
- <div class="item-3">3</div>
- <div class="item-4">4</div>
- <div class="item-5">5</div>
- <div class="item-6">6</div>
- </div>
- css
- $bgcloors: #b03532 #33a8a5 #30997a #6a478f #da6f2b #3d8bb1;
- .grid{
- display: grid;
- grid-template-columns: 300px 200px 150px;
- grid-template-rows: 150px 100px;
- div{
- color: #fff;
- font-size: 30px;
- padding: 20px;
- }
- @for $i from 1 through length($bgcloors){
- .item-#{$i}{
- background: nth($bgcloors, $i)
- }
- }
- }
我们来分析下上面的 css
1 给 grid 元素设置了 display: grid 来声明使用 grid 布局 2 使用
grid-template-columns
来设置列宽, 分别为 300px 200px 150px 3 使用 grid-template-rows 来设置行高, 分别为 150px 100px
以上代码我们是实现了一个两行三列的 grid 布局, 此时浏览器显示如下
我们可以看到网格线的样子
进阶
- fr
- grid-template-columns
和 grid-template-rows 不只是可以设置具体的数值, 还可以设置百分比 rem 一类的, 还可以设置一个新单位 fr, 它是来干什么的呢? 我们先看
我们先把上面 demo 里面的 css 文件改下
- $bgcloors: #b03532 #33a8a5 #30997a #6a478f #da6f2b #3d8bb1;
- .grid{
- display: grid;
- grid-template-columns: 1fr 2fr 1fr;
- grid-template-rows: repeat(2,1fr);
- div{
- color: #fff;
- font-size: 30px;
- padding: 20px;
- }
- @for $i from 1 through length($bgcloors){
- .item-#{$i}{
- background: nth($bgcloors, $i)
- }
- }
- }
以上实现了弹性布局, fr 用来实现弹性布局, 我们这里使用里 repeat(2, 1fr), 表示重复两次, 都是 1fr
grid-gap
grid-gap 用来这是网格项间隙
css 修改如下
- $bgcloors: #b03532 #33a8a5 #30997a #6a478f #da6f2b #3d8bb1;
- .grid{
- display: grid;
- grid-template-columns: 1fr 2fr 1fr;
- grid-template-rows: repeat(2,1fr);
- grid-gap: 40px;
- div{
- color: #fff;
- font-size: 30px;
- padding: 20px;
- }
- @for $i from 1 through length($bgcloors){
- .item-#{$i}{
- background: nth($bgcloors, $i)
- }
- }
- }
展示如下
网格布局属性 grid-placement-properties
恭喜你, 从一开始一步步的实现了一个网格布局, 可以发现所有的样式都写在网格容器里面的, 当我们实现一些复杂布局的时候, 就显得有点力不从心了, 接下来我们来介绍下写在网格项中的属性
网格布局属性主要用来放置容器内的网格项目, 就是单一项目的位置网格布局属性主要有以下四个属性:
grid-column-start 设置垂直方向的开始位置网格线
grid-column-end 设置垂直方向的结束位置网格线
grid-row-start 设置水平方向的开始位置网格线
grid-row-end 设置水平方向的结束位置网格线
以上的简写方式
- grid-column: grid-column-start / grid-column-end
- grid-row: grid-row-start / grid-row-end
终极简写
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-colun-end
是不是有点蒙, 我们可以大概看下, 先来看 deme
还是熟悉的 html 布局
- <div class="grid">
- <div class="item-1">1</div>
- <div class="item-2">2</div>
- <div class="item-3">3</div>
- <div class="item-4">4</div>
- <div class="item-5">5</div>
- <div class="item-6">6</div>
- </div>
- css
- $bgcloors: #b03532 #33a8a5 #30997a #6a478f #da6f2b #3d8bb1;
- .grid{
- display: grid;
- grid-template-columns: 300px 200px 150px;
- grid-template-rows: 150px 100px;
- div{
- color: #fff;
- font-size: 30px;
- padding: 20px;
- }
- @for $i from 1 through length($bgcloors){
- .item-#{$i}{
- background: nth($bgcloors, $i)
- }
- }
- .item-2{ // 看这里看这里
- grid-column-start: 2;
- grid-column-end: 4;
- grid-row-start: 1;
- grid-row-end: 2;
- }
- .item-6{ // 你要先看上面再看这里
- grid-area: 3 / 1 / 4 / 4;
- }
- }
先来看看我们的成果
显示网格线的图片
参考上图, 我们来分析下 css 1grid 元素声明 grid 布局,
grid-template-columns
和 grid-template-rows 来创建一个两行三列的网格, 但是渲染的结果却是三行三列, 为什么? 我们先接着往下分析 2css 文件中单独设置 item-2 网格项的位置,
grid-column-start:2
垂直线开始位置为 2 grid-column-end:4 垂直线结束位置为 4 grid-row-start:1 水平线开始位置为 1 grid-row-end:2 水平线结束位置为 2 3 通过单独设置 item-2 的位置, 把本身要在第一行的 item-3 给挤下来了, 然后 345 按照 300 200 150 排列 4 这时候两件三列排列完了, 但是还有个元素, 此时剩下的元素就会独自占一行的位置, 它的大小一样会按照网格容器定义的行高列宽来渲染 5 最后我们给 item-6 来设置了终极简写方式, 终极简写: 行开始 / 列开始 / 行结束 / 列结束, 然后我们把位置对应上
grid-area:3 / 1 / 4 / 4
通过设置网格项样式属性, 我们可以就实现很多复杂的布局结构了
几种布局
最后我们结合上面所学到的实现几个常见布局
1 左右固定, 中间自适应
设置网格容器的
grid-template-columns: 100px 1fr 100px
或者
grid-template-columns: 100px auto 100px
就可以实现, 再简单不过了
- html
- <div class="container">
- <div class="left">left</div>
- <div class="middle">middle</div>
- <div class="right">right</div>
- </div>
- css
- .container{
- display: grid;
- grid-template-columns: 100px 1fr 100px;
- height: 200px;
- }
- .container div{
- text-align: center;
- }
- .left{
- background: greenyellow;
- }
- .middle{
- background: lightblue;
- }
- .right{
- background: greenyellow;
- }
2 九宫格 使用 grid-gap 设置网格项间距 使用 fr 来平分
- html
- <div class="container">
- <div class="item">1</div>
- <div class="item">2</div>
- <div class="item">3</div>
- <div class="item">4</div>
- <div class="item">5</div>
- <div class="item">6</div>
- <div class="item">7</div>
- <div class="item">8</div>
- <div class="item">9</div>
- </div>
- css
- .container{
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- grid-template-rows: repeat(3, 1fr);
- height: 400px;
- width: 400px;
- grid-gap: 8px;
- }
- .item{
- background: lightskyblue;
- }
显示如下
3 圣杯双飞翼 使用 grid-area 设置 header 元素和 footer 元素位置, 结合
grid-template-columns
和 grid-template-rows 实现布局 html
- <div class="container">
- <div class="header">header</div>
- <div class="left">left</div>
- <div class="body">body</div>
- <div class="right">right</div>
- <div class="footer">footer</div>
- </div>
- css
- .container{
- display: grid;
- grid-template-columns: 100px 1fr 100px;
- grid-template-rows: 50px 300px 50px;
- }
- .header{
- grid-area: 1 / 1 / 2 / 4;
- }
- .footer{
- grid-area: 3 / 1 / 4 / 4;
- }
- .header{
- background: lightsalmon;
- }
- .left{
- background: lightseagreen;
- }
- .body{
- background: lightslategray;
- }
- .right{
- background: lightyellow;
- }
- .footer{
- background: yellowgreen;
- }
来源: https://juejin.im/post/5a7f1c3b5188257a79249e8e