在日常项目中我们经常会遇到两栏布局、三栏布局、不定列自适应、不定项目大小、指定大小指定位置等等如下图,对于这类布局使用Grid处理起来就更容易。部分的grid属性可以通过js进行动态设置,来指定项目的大小和位置。
一、基本概念及应用场景
Grid布局适合应用到将网页划分成一个个网格,进行不同方式组合,类似下图。Grid布局是将容器划分成“行”和“列”,形成单元格,然后可以指定项目所在的单元格进行设置,因此Grid布局可以看作二维布局
点击展开html代码
<div class="grid">
<div class="item-1 center">1</div>
<div class="item-2 center">2</div>
<div class="item-3 center">3</div>
<div class="item-4 center">4</div>
<div class="item-5 center">5</div>
<div class="item-6 center">6</div>
<div class="item-7 center">7</div>
<div class="item-8 center">8</div>
<div class="item-9 center">9</div>
</div>
1、容器和项目
采用网格布局的区域,称为"容器"(container)。上面代码中类名为grid的div为容器。 容器内部采用网格定位的子元素,称为"项目"(item)。对应上面代码中9个item对应的div
2、行和列
容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。
3、单元格
行和列的交叉区域,称为"单元格"(cell)。 正常情况下,n行和m列会产生n x m个单元格。比如,3行3列会产生9个单元格。
4、网格线
划分网格的线,称为"网格线"(grid line)。水平网格线划分出行,垂直网格线划分出列。 正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。
二、Grid属性
Grid布局属性分成两种,一种是容器上面的属性,另一种是定义到项目上的属性
1、容器属性
-
1.1 display 属性
给定元素采用网格布局
display: grid;默认情况下,容器元素都是块级元素,但也可以设成行内元素
div { display: inline-grid; }注意,设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。
-
1.2 grid-template-columns 属性,grid-template-rows 属性
grid-template-columns属性定义每一列的列宽 grid-template-rows属性定义每一行的行高。
.container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; }上面代码指定了一个三行三列的网格,列宽和行高都是100px。
示例
点击展开html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { box-sizing: border-box; } body { margin: 0; padding: 0; } .center { text-align: center; line-height: 100px; font-size: 40px; } .item-1 { background-color: #ef342a; } .item-2 { background-color: #f68f26; } .item-3 { background-color: #4ba946; } .item-4 { background-color: #0376c2; } .item-5 { background-color: #c077af; } .item-6 { background-color: #f8d29d; } .item-7 { background-color: #b5a87f; } .item-8 { background-color: #d0e4a9; } .item-9 { background-color: #4dc7ec; } .wrap { width: 400px; margin: 40px auto; } .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; } </style> </head> <body> <div class="wrap"> <div class="container"> <div class="item-1 center">1</div> <div class="item-2 center">2</div> <div class="item-3 center">3</div> <div class="item-4 center">4</div> <div class="item-5 center">5</div> <div class="item-6 center">6</div> <div class="item-7 center">7</div> <div class="item-8 center">8</div> <div class="item-9 center">9</div> </div> </div> </body> </html>也可以使用百分比单位进行设置
点击展开css代码
.container { display: grid; grid-template-columns: 33.33% 33.33% 33.33%; grid-template-rows: 33.33% 33.33% 33.33%; }
-
1.2.1 repeat函数
repeat() 函数可以重复相同的内容 repeat() 接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值。
点击展开代码
// 上面代码可以用这个函数进行简化 .container { display: grid; grid-template-columns: repeat(3, 33.33%); grid-template-rows: repeat(3, 33.33%); }repeat() 重复某种模式也是可以的。 repeat(2, 100px 20px 80px) -> 将第一列100px、第二列20px、第三列80px重复2次,及第四列为100px、第五列20px、第六列80px
点击展开代码
.container { display: grid; grid-template-columns: repeat(2, 100px 20px 80px); grid-template-rows: repeat(3, 100px); }
-
1.2.2 auto-fill 关键字
auto-fill关键字表示自动填充,直到容器不能放置更多的列
点击展开代码
```css .container { display: grid; grid-template-columns: repeat(auto-fill, 100px); grid-template-rows: repeat(3, 100px); } ```
-
1.2.3 fr 关键字
fr关键字(fraction 的缩写,意为"片段"),两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。
点击展开代码
.container { display: grid; grid-template-columns: 1fr 2fr 1fr; grid-template-rows: repeat(3, 100px); }
fr可以与绝对长度的单位结合使用,这时会非常方便。 第一列的宽度为200像素,第二列的宽度是第三列的一半。
点击展开代码
.container { display: grid; grid-template-columns: 200px 1fr 2fr; grid-template-rows: repeat(3, 100px); }
-
1.2.4 minmax()
minmax() 函数接受两个参数,分别为最小值和最大值。 grid-template-columns: 1fr 1fr minmax(100px, 1fr) 表示列宽不小于100px,不大于1fr,下图是当宽度小于100px显示样式
点击展开代码
.container { display: grid; grid-template-columns: 1fr 1fr minmax(100px, 1fr); grid-template-rows: repeat(3, 100px); }
-
1.2.5 auto 关键字
auto关键字表示由浏览器自己决定长度
第二列的宽度基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width,且这个值大于最大宽度。此时类似grid-template-columns: 100px 1fr 100px
点击展开代码
.container { display: grid; grid-template-columns: 100px auto 100px; grid-template-rows: repeat(3, 100px); }
-
1.2.6 网格线的名称
.container { display: grid; grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4]; grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4]; }使用方括号,指定每一根网格线的名字, 指定网格布局为3行 x 3列,因此有4根垂直网格线和4根水平网格线。 网格布局允许同一根线有多个名字,比如[fifth-line row-5]
示例-两栏布局
点击展开代码
.container { display: grid; grid-template-columns: 70% 30%; grid-template-rows: 300px 300px; }
-
1.3 row-gap 属性,column-gap 属性,gap 属性
row-gap属性设置行与行的间隔(行间距),column-gap属性设置列与列的间隔(列间距)。
点击展开代码
```css .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); row-gap: 20px; column-gap: 20px; } ```gap属性是column-gap和row-gap的合并简写形式,语法如下。
gap: <row-gap> <column-gap>;因此上面的布局效果也可以用下面的代码实现
.container { gap: 20px 20px; }如果gap省略了第二个值,浏览器认为第二个值等于第一个值
备注: gap属性曾经有一个grid-前缀,不过后来的标准进行了修改,目的是让他们能够在不同的布局方法中都能起作用。尽管现在这个前缀不会影响语义,但为了代码的健壮性,你可以把两个属性都写上。
.container { grid-gap: 20px; gap: 20px; }
-
1.4 grid-template-areas 属性
网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas属性用于定义区域。
点击展开代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { box-sizing: border-box; } body { margin: 0; padding: 0; } .center { text-align: center; line-height: 100px; font-size: 40px; } .wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-areas: "header header" "sidebar content" "footer footer"; grid-template-columns: 1fr 3fr; gap: 20px; } header { grid-area: header; } article { grid-area: content; } aside { grid-area: sidebar; } footer { grid-area: footer; } body { width: 90%; max-width: 900px; margin: 2em auto; font: 0.9em/1.2 Arial, Helvetica, sans-serif; } header, footer { border-radius: 5px; padding: 10px; background-color: rgb(207, 232, 220); border: 2px solid rgb(79, 185, 227); } aside { border-right: 1px solid #999; } </style> </head> <body> <div class="wrap"> <div class="container"> <header>This is my lovely blog</header> <article> <h1>My article</h1> <p> Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien. </p> <p> Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. </p> </article> <aside> <h2>Other things</h2> <p> Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. </p> </aside> <footer>Contact me@example.com</footer> </div> </div> </body> </html>
如果某些区域不需要利用,则使用"点"(.)表示。
点击展开css代码
.container { display: grid; grid-template-columns: 100px 300px 100px; grid-template-rows: repeat(3, 100px); grid-template-areas: 'a . c' 'd . f' 'g . i'; } .item-1 { background-color: #ef342a; grid-area: a; } .item-3 { background-color: #4ba946; grid-area: c; } .item-4 { background-color: #0376c2; grid-area: d; } .item-6 { background-color: #f8d29d; grid-area: f; } .item-7 { background-color: #b5a87f; grid-area: g; } .item-9 { background-color: #4dc7ec; grid-area: i; }点击展开html代码
<div class="container"> <div class="item-1 center">1</div> <div class="item-3 center">3</div> <div class="item-4 center">4</div> <div class="item-6 center">6</div> <div class="item-7 center">7</div> <div class="item-9 center">9</div> </div>
-
1.5 grid-auto-flow 属性
容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。
设置先列后行
点击展开css代码
grid-auto-flow: column;
如果要将上面布局中每一行的位置填充满,可以将设置grid-auto-flow:row dense, 先行后列
点击展开css代码
grid-auto-flow:row dense;
先列后行
点击展开css代码
grid-auto-flow:column dense;
-
1.6 justify-items 属性,align-items 属性,place-items 属性
justify-items属性设置单元格内容的水平位置(左中右),align-items属性设置单元格内容的垂直位置(上中下)。
.container { justify-items: start | end | center | stretch; align-items: start | end | center | stretch; } start:对齐单元格的起始边缘。 end:对齐单元格的结束边缘。 center:单元格内部居中。 stretch:拉伸,占满单元格的整个宽度(默认值)
place-items属性是align-items属性和justify-items属性的合并简写形式,如果省略第二个值,则浏览器认为与第一个值相等。
place-items: <align-items> <justify-items>;居其中一个示例用法, 水平和垂直方向都居中,需要注意给每一项都设置宽高,可以看到更明显。
点击展开css代码
.container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); place-items: center center } .item { text-align: center; line-height: 60px; height: 60px; font-size: 40px; border: 1px solid #ccc; width: 60px; }
-
1.7 justify-content 属性,align-content 属性,place-content 属性
justify-content属性是整个内容区域在容器里面的水平位置(左中右),align-content属性是整个内容区域的垂直位置(上中下)。
点击展开css代码
.container { justify-content: start | end | center | stretch | space-around | space-between | space-evenly; align-content: start | end | center | stretch | space-around | space-between | space-evenly; }
-
start - 对齐容器的起始边框。
点击展开css代码
.wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); justify-content: start; }
-
end - 对齐容器的结束边框。
点击展开css代码
.wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); justify-content: end; }
-
center - 容器内部居中
点击展开css代码
.wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); justify-content: center; }
-
stretch - 项目大小没有指定时,拉伸占据整个网格容器。
点击展开css代码
.wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: auto auto auto; grid-template-rows: repeat(3, 100px); justify-content: stretch; }
-
space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
点击展开css代码
.wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); justify-content: space-around; }
-
space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔。
点击展开css代码
.wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); justify-content: space-between; }
- space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
<details> <summary>点击展开css代码</summary> ```css .wrap { width: 500px; margin: 40px auto; } .container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(3, 100px); justify-content: space-evenly; } ``` </details>
place-content属性是align-content属性和justify-content属性的合并简写形式。如果省略第二个值,浏览器就会假定第二个值等于第一个值。 示例: 容器中水平均等间隔,垂直居中布局
点击展开css代码
// place-content: <align-content> <justify-content> place-content: space-around space-evenly; -
-
1.8 grid-auto-columns 属性,grid-auto-rows 属性
grid-auto-columns属性和grid-auto-rows属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns和grid-template-rows完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
示例:如下图,第三行不设置项目高度,没有设置高度的项目会按照grid-auto-rows设置的值显示
点击展开css代码
.container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(2, 100px); grid-auto-rows: 50px; }
-
1.9 grid-template 属性,grid 属性
grid-template属性是grid-template-columns、grid-template-rows和grid-template-areas这三个属性的合并简写形式。
grid属性是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow这六个属性的合并简写形式。
2、项目属性
-
1、grid-column-start 属性,grid-column-end 属性,grid-row-start 属性,grid-row-end 属性
这四个属性用来指定项目的四个边框,分别定位在哪根网格线
grid-column-start属性:左边框所在的垂直网格线 grid-column-end属性:右边框所在的垂直网格线 grid-row-start属性:上边框所在的水平网格线 grid-row-end属性:下边框所在的水平网格线
示例:将1号项目的左边框设置为第二根垂直网格线,右边框设置为第四根垂直网格线
点击展开css代码
.item-1 { background-color: #ef342a; grid-column-start: 2; grid-column-end: 4; }- 将1号项目指定四个边框位置的效果
点击展开css代码
.item-1 { background-color: #ef342a; grid-column-start: 1; grid-column-end: 3; grid-row-start: 2; grid-row-end: 4; }- 这四个属性的值,除了指定为第几个网格线,还可以指定为网格线的名字。
点击展开css代码
.container { display: grid; grid-template-columns: [header-start] 100px [c2] 100px [header-end] 100px [c4]; grid-template-rows: repeat(4, 100px); } .item-1 { background-color: #ef342a; grid-column-start: header-start; grid-column-end: header-end; }- 这四个属性的值还可以使用span关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格
点击展开css代码
.item-1 { background-color: #ef342a; grid-column-start: span 2; }
-
2、grid-column 属性,grid-row 属性
grid-column属性是grid-column-start和grid-column-end的合并简写形式, grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。 斜杠以及后面的部分可以省略,默认跨越一个网格。
.item { grid-column: <start-line> / <end-line>; grid-row: <start-line> / <end-line>; } // 举个示例 .item-1 { grid-column: 1 / 3; grid-row: 1 / 2; } /* 等同于 */ .item-1 { grid-column-start: 1; grid-column-end: 3; grid-row-start: 1; grid-row-end: 2; }这两个属性之中,也可以使用span关键字,表示跨越多少个网格。
.item-1 { background: #b03532; grid-column: 1 / 3; grid-row: 1 / 3; } /* 等同于 */ .item-1 { background: #b03532; grid-column: 1 / span 2; grid-row: 1 / span 2; }上面的代码效果如下,项目1占据的区域,包括第一行 + 第二行、第一列 + 第二列

-
3、grid-area 属性
grid-area属性指定项目放在哪一个区域
点击展开css代码
.container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(4, 100px); grid-template-areas: 'a b c' 'd e f' 'g h i'; } .item-1 { background-color: #ef342a; grid-area: e; }grid-area属性还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写形式,直接指定项目的位置。
.item { grid-area: <row-start> / <column-start> / <row-end> / <column-end>; }点击展开css代码
.container { display: grid; grid-template-columns: repeat(3, 100px); grid-template-rows: repeat(4, 100px); } .item-1 { background-color: #ef342a; grid-area: 1 / 1 / 3 / 3; }
-
4、justify-self 属性,align-self 属性,place-self 属性
justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。
align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目。
.item { justify-self: start | end | center | stretch; align-self: start | end | center | stretch; }示例: 将项目1设置为水平居中,其他项目默认\
点击展开css代码
.item-1 { background-color: #ef342a; justify-self: center; }place-self属性是align-self属性和justify-self属性的合并简写形式。 如果省略第二个值,place-self属性会认为这两个值相等。
// place-self: <align-self> <justify-self>; place-self: center center;