前端-CSS学习笔记19-Grid布局

1. 认识Grid布局

  • 对于界面布局:定位,浮动,flex布局

  • flex布局相对于前面的布局来说更加的强大

    • 但是flex是一个一维布局方案(one-dimensional layout)
    • 只能指定”项目”针对轴线的位置
    • 它主要的布局是在主轴(main axis)上进行操作,也提供了一些交叉轴(cross axis)属性
  • CSS为了进一步增强布局能力,提供了grid布局

    • CSS Grid Layout(又名“Grid”或“CSS Grid”)是一种基于二维的布局系统(two-dimensional layout)
    • 将容器划分成”行”和”列”,产生单元格,然后指定”项目所在”的单元格
  • 目前公司生产环境基本是使用flex布局为主,因为grid兼容性比flex布局差一些

2. grid布局重要概念

2.1. 容器和项目

  • Grid Container容器
    • 元素设置display为grid的盒子
  • Grid Item项目
    • grid container的直接子项(必须是直接子代)
1
2
3
4
5
6
7
8
9
10
<style>
.container {
display: grid;
}
</style>
<div class="container">
<div class="box1"><span>1</span></div>
<div class="box2"><span>2</span></div>
<div class="box3"><span>3</span></div>
</div>
  • 最外层的div.container就是容器,内层的div.box1,div.box2,div.box3就是项目
  • 但是项目就能是容器的直接子元素,内部的span元素就不是项目

2.2. 网格线

  • Grid Line

    • 构成网络结构的分割线

    • 可以是垂直的(列网格线)或水平的(行网格线)

  • n行有n+1根行网格线,m列有m+1根垂直网格线

2.3. 网格区域

  • Grid Area

    • 由四条网格线包围的总空间

    • 一个网格区域可以由任意数量的网格单元组成

2.4. 网格轨道

  • Grid Track
    • 两条相邻网格线之间的空间
    • 可以看成是网格的行或列

3. grid container常见属性

3.1. display

1
2
3
.container {
display: grid | inline-grid;
}
  • 将元素定义为网格容器,并为其内容建立网格格式化上下文
    • grid - 块级网格容器
    • inline-grid - 行内网格容器

3.2. grid-template-columns/rows

  • 使用以空格分隔的值列表定义网格的列和行

    • grid-template-columns定义列宽
    • grid-template-rows定义行高
  • 值可以是px,百分比,1fr

  • 值的个数代表项目的个数

3.2.1. 三行三列

  • 三行三列,列宽和行高都是100px
1
2
3
4
5
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}

3.2.2. repeat()

  • 可以使用repeat()函数,简化重复的值

    • 接受两个参数,第一个参数是重复的次数,第二个参数是所要重复的值

    • 如三行三列同100px

      1
      2
      3
      4
      5
      .container {
      display: grid;
      grid-template-columns: repeat(3,100px);
      grid-template-rows: repeat(3,100px);
      }
    • 6列

      1
      2
      3
      4
      .container {
      display: grid;
      grid-template-columns: repeat(2,20px 40px 60px);
      }

      等价于

      1
      2
      3
      4
      .container {
      display: grid;
      grid-template-columns: 20px 40px 60px 20px 40px 60px;
      }

3.2.3. auto-fill关键字

  • 固定单元格情况下,可以使用auto-fill关键字自动填充整个容器

    1
    2
    3
    .container {
    grid-template-columns: repeat(auto-fill,100px);
    }

3.2.4. fr关键字

  • 类似于flex布局中的flex-grow:1,占比容器剩余空间

    • 三列平分容器宽度
    1
    2
    3
    .container {
    grid-template-columns: repeat(3,1fr);
    }
    • 第一列50px,二三列平分剩余宽度
    1
    2
    3
    .container {
    grid-template-columns: 50px 1fr 1fr;
    }

3.2.5. auto关键字

  • 由浏览器决定长度
1
2
3
.container {
grid-template-columns: 50px auto 50px;
}
  • 第二列占满剩余空间

3.2.6. minmax()

  • 产生一个长度范围,参数为(最小值,最大值)
1
2
3
.container {
grid-template-columns: 50px minmax(100px,1fr) 50px;
}
  • 表示第二列列宽不小于100px,不大于1fr

3.2.7. line-name

  • 在属性值内使用方括号[ ]指定每一根网格线的名字

1
2
3
4
.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

3.3. grid-template-areas

  • 定义网格区域名,区域可以由一个或多个单元格组成
  • 注意,网格区域的命名会影响到网格线
    • 每个区域的起始网格线,会自动命名为区域名-start,终止网格线自动命名为区域名-end
    • 如果区域名为foo,则起始位置的水平网格线和垂直网格线叫做foo-start,终止位置的水平网格线和垂直网格线叫做foo-end

3.3.1. 值的选择

1
2
3
4
5
.container {
grid-template-areas:
"<grid-area-name> | . | none | ..."
"...";
}
  • grid-area-name - 由grid-name指定的网格区域名
  • . - 没有用到该单元格,或者该单元格不属于任何区域
  • none - 没有定义的网格区域 名

3.3.2. 三行四列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<style>
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}

.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: 50px 50px 50px;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}
.item {
background-color: orange;
border: 1px solid #999;
font-size: 12px;
text-align: center;
line-height: 50px;
}
</style>

<div class="container">
<div class="item item-a">header</div>
<div class="item item-b">main</div>
<div class="item item-c">sidebar</div>
<div class="item item-d">footer</div>
</div>

3.4. grid-template

  • grid-template-rows,grid-template-columns,grid-template-areas的连写

3.4.1. 值的选择

  • none - 都用默认值
  • grid-template-rows / grid-template-columns - 仅设置网格行列
1
2
3
.container {
grid-template: none | <grid-template-rows> / <grid-template-columns>;
}

3.4.2. 两行跨三列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 <style>
.item-a {
grid-area: header;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
grid-template:
[row1-start] "header header header" 50px [row1-end]
[row2-start] "footer footer footer" 50px [row2-end]
/ 50px 50px 50px;
}
.item {
background-color: orange;
border: 1px solid #999;
font-size: 12px;
text-align: center;
line-height: 50px;
}
</style>
<div class="container">
<div class="item item-a">header</div>
<div class="item item-d">footer</div>
</div>

等价于

1
2
3
4
5
6
7
.container {
grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
grid-template-areas:
"header header header"
"footer footer footer";
}

3.5. grid-column/row-gap

  • 指定网格线的大小。可以想象成行列之间的水槽宽度。
  • column-gap 设置列间距,row-gap 设置行间距
  • 可以使用 column-gap,row-gap
    • Chrome 68 + 、 Safari 11.2 Release50 + 和 Opera 54 + 已经支持无前缀属性
1
2
3
4
5
6
.container {
display: grid;
grid-template: repeat(3,50px)/repeat(3,60px);
grid-column-gap: 10px;
grid-row-gap: 15px;
}

3.6. grid-gap

  • grid-row-gap,grid-column-gap的连写
  • 可以直接使用gap属性
    • Chrome 68+, Safari 11.2 Release 50+, and Opera 54+已经支持
1
2
3
4
5
6
7
.container {
/* standard */
gap: <grid-row-gap> <grid-column-gap>;

/* old */
grid-gap: <grid-row-gap> <grid-column-gap>;
}
  • 如果行列间距一样,可以写成

    1
    grid-gap: 10px;

    等价于

    1
    grid-gap: 10px 10px;

3.7. justify-items

  • 设置网格项的水平(左中右)对齐方式
1
2
3
.container {
justify-items: start | end | center | stretch;
}
说明 表现
start 对齐起始左边缘
end 对齐结束右边缘
center 水平居中
stretch 拉伸。占满网格项的整个宽度

3.8. align-items

  • 设置网格项的垂直(上中下)对齐方式
1
2
3
.container {
align-items: start | end | center | stretch;
}
说明 表现
start 对齐起始上边缘
end 对齐结束下边缘
center 垂直居中
stretch 拉伸。占满网格项的整个高度

3.9. place-items

  • 同时设置align-items和justify-items属性值
  • 当两个属性值相同时,可以只写一个。如place-item: center;
1
2
3
.container {
place-items: <align-items> / <justify-items>;
}

3.10. justify-content

  • 如果所有的网格项目都使用像 px 这样不灵活的单位来调整大小,就会出现网格的总大小小于其网格容器的大小。在这种情况下,可以在网格容器中设置网格的对齐方式
  • justify-content属性就是设置整个内容区域在容器里面的水平位置
1
2
3
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
说明 表现
start 对齐容器的起始左边缘
end 对齐容器的结束右边缘
center 水平居中
stretch 拉伸。占满容器的整个宽度
space-between 每个项目间隔相等
项目与容器边缘没有间隔
space-around 每个项目两侧间隔相等
项目之间的间隔比项目与容器边缘的间隔大一倍
space-evenly 每个项目两侧间隔,项目与容器边缘的间隔都相等

3.11. align-content

  • align-content属性就是设置整个内容区域在容器里面的垂直位置
1
2
3
.container {
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
说明 表现
start 对齐容器的起始上边缘
end 对齐容器的结束下边缘
center 垂直居中
space-between 每个项目间隔相等
项目与容器边缘没有间隔
space-around 每个项目两侧间隔相等
项目之间的间隔比项目与容器边缘的间隔大一倍
space-evenly 每个项目两侧间隔,项目与容器边缘的间隔都相等

3.12. place-content

  • 同时设置align-content 和 justify-content属性值
  • 除 Edge 之外的所有主要浏览器都支持 place-content 属性
1
2
3
.container {
place-content: <align-content> / <justify-content>;
}

3.13. grid-auto-columns/rows

  • 一些项目的指定位置,在现有网格的外部。比如网格只有2行2列,但是某一个项目指定在第5列。这时,浏览器会自动生成网格线,形成隐式网格轨道,以便放置项目

  • grid-auto-columns属性和grid-auto-rows属性用来指定自动生成的网格轨道(即隐式网格轨道)的大小,写法和grid-template-columns/rows一样

  • 举例:原有2行2列的容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .container {
    width: 500px;
    display: grid;
    grid-template-columns: 60px 60px;
    grid-template-rows: 90px 90px;
    }
    .item {
    background-color: orange;
    font-size: 16px;
    text-align: center;
    line-height: 90px;
    }
    • 需要在(第1列,第2行),(第5列,第2行)放项目
    1
    2
    3
    4
    5
    6
    7
    8
    .item-a {
    grid-column: 1 / 2;
    grid-row: 2 / 3;
    }
    .item-b {
    grid-column: 5 / 6;
    grid-row: 2 / 3;
    }
    1
    2
    3
    4
    <div class="container">
    <div class="item item-a">3</div>
    <div class="item item-b">4</div>
    </div>
    • div.item-b左右被line5,line6包围,上下被row1-end,row2-start包围,形成一个网格轨道

    • 但是line5,line6是不存在的。因为引用了不存在的网格线,所以会创建隐式轨道来填补空白。如果不指定隐式轨道的宽度,会取容器的剩余空间平分

    • 通过grid-auto-columns指定这些隐式轨道的宽度

      1
      grid-auto-columns: 60px;

3.14. grid-auto-flow

  • 如果没有指明网格上的网格项位置,那么将启用自动放置算法以自动放置这些项
  • grid-auto-flow属性控制自动放置算法的工作方式
1
2
3
.container {
grid-auto-flow: row | column | row dense | column dense;
}
说明
row 默认值。告诉自动布局算法依次填充每一行,根据需要添加新行
column 告诉自动布局算法依次填充每一列,根据需要添加新列
dense 告诉自动布局算法使用一种“稠密”堆积算法,如果后面出现了稍小的元素,则会试图去填充网格中前面留下的空白。这样做会填上稍大元素留下的空白,但是会改变项目的视觉顺序,并可能导致项目出现顺序错误,这对可访问性不利

3.14.1. 两行五列 - 横排

  • div.item-a,div.item-e的位置固定,中间的三个div默认填充行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<style>
.item-a {
grid-column: 1;
grid-row: 1/3;
}
.item-e {
grid-column: 5;
grid-row: 1/3;
}

.container {
display: grid;
grid-template-columns: repeat(5,60px);
grid-template-rows: 60px 60px;
}
.item {
background-color: orange;
border: 1px solid #999;
font-size: 16px;
text-align: center;
line-height: 60px;
}
</style>

<div class="container">
<div class="item item-a">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item item-e">5</div>
</div>

3.14.2. 两行五列-竖排

  • div.item-a,div.item-e的位置固定,中间的三个div现在填充列
1
2
3
4
5
6
.container {
display: grid;
grid-template-columns: repeat(5,60px);
grid-template-rows: 60px 60px;
grid-auto-flow: column;
}

3.15. grid

  • grid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns,grid-auto-flow的连写

3.15.1. 值的选择

  • none - 都用默认值
  • grid-template - grid-template-rows,grid-template-columns,grid-template-areas的连写
  • <grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>?
    • grid-template-rows设置值
    • 如果 auto-flow 关键字位于斜杠的右侧,则将 grid-auto-flow 设置为 column
    • 如果另外指定了dense稠密关键字,则自动放置算法使用“稠密”打包算法
    • grid-auto-columns 如果不设置,值为auto
  • [ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>
    • grid-template-columns 设置值
    • 如果 auto-flow 关键字位于斜杠的左侧,则将 grid-auto-flow 设置为 row
    • grid-auto-rows 如果不设置,值为auto

3.15.2. 举例

  • grid-template

    1
    2
    3
    4
    5
    6
    7
    8
    .container {
    grid: 100px 300px / 3fr 1fr;
    }

    .container {
    grid-template-rows: 100px 300px;
    grid-template-columns: 3fr 1fr;
    }
  • [ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>

    1
    2
    3
    4
    5
    6
    7
    8
    .container {
    grid: auto-flow / 200px 1fr;
    }

    .container {
    grid-auto-flow: row;
    grid-template-columns: 200px 1fr;
    }
  • <grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .container {
    grid: 100px 300px / auto-flow 200px;
    }

    .container {
    grid-template-rows: 100px 300px;
    grid-auto-flow: column;
    grid-auto-columns: 200px;
    }

4. grid item常见属性

  • float、 display: inline-block、 display: table-cell、vertical-align 和 column-* 属性对网格项没有影响

4.1. grid-column/row-start/end

  • 通过引用特定的网格线确定网格项在网格中的位置
  • grid-column-start/grid-row-start 是项目开始的行,grid-column-end/grid-row-end 是项目结束的行

4.1.1. 值的选择

1
2
3
4
5
6
.item {
grid-column-start: <number> | <name> | span <number> | span <name> | auto;
grid-column-end: <number> | <name> | span <number> | span <name> | auto;
grid-row-start: <number> | <name> | span <number> | span <name> | auto;
grid-row-end: <number> | <name> | span <number> | span <name> | auto;
}
  • 如果没有声明 grid-column-end/grid-row-end,默认情况下该项将跨越1个轨道
  • 项目可以相互重叠。可以使用 z-index 来控制堆叠顺序
说明
number 表示编号网格线的数字
name 表示指定网格线名
span number 跨越所提供的网格轨道数量
span name 跨越所提供的网格线名
auto 表示自动放置、自动跨度或默认跨度为1

4.1.2. (2-5,1-3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
.container {
display: grid;
grid-template-columns: [first] 30px [line2] 30px [line3] 60px [col4-start] 30px [five] 30px [end];
grid-template-rows: [row1-start] 60px [row1-end] 60px [thrid-line] 60px [last-line];
}
.item-a {
grid-column-start: 2;
grid-column-end: five;
grid-row-start: row1-start;
grid-row-end: 3;
background-color: orange;
}
</style>
<div class="container">
<div class="item item-a"></div>
</div>

4.1.3. (1-4,2-4)

1
2
3
4
5
6
.item-b {
grid-column-start: 1;
grid-column-end: span col4-start;
grid-row-start: 2;
grid-row-end: span 2;
}

4.2. grid-column/row

  • grid-column-start,grid-column-end,grid-row-start,grid-row-end的连写
1
2
3
4
.item {
grid-column: <start-line> / <end-line> | <start-line> / span <value>;
grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
  • (2-5,1-3)就可以写成

    1
    2
    3
    4
    .item-a {
    grid-column: 2 / span 3;
    grid-row: row1-start / span 2;
    }
  • (1-4,2-4) 就可以写成

    1
    2
    3
    4
    .item-a {
    grid-column: 1 / span col4-start;
    grid-row: 2 / 4;
    }
  • 当只跨一个轨道,可以只写一个start-line

    1
    2
    3
    4
    .item-a {
    grid-cloumn: 1;
    grid-row: 2;
    }

4.3. grid-area

  • 为网格项提供一个名称,以便可以由使用 grid-template-area 属性创建的模板引用该网格项
  • 或者,此属性可以用作 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的更简短的缩写

4.3.1. 作为网格项名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<style>	
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: footer;
}
.container {
display: grid;
grid-template:
". header header" 50px
"main main ." 50px
". footer footer" 50px
/ 50px 50px 50px;
}
.item {
background-color: orange;
text-align: center;
line-height: 50px;
}
</style>
<div class="container">
<div class="item item-a">header</div>
<div class="item item-b">main</div>
<div class="item item-c">footer</div>
</div>

4.3.2. 作为网格项位置的连写

  • grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<style>
.item-d {
grid-area: 1 / col4-start / last-line / 6;
}
.container {
display: grid;
grid-template-columns: [first] 30px [line2] 30px [line3] 60px [col4-start] 30px [five] 30px [end];
grid-template-rows: [row1-start] 60px [row1-end] 60px [thrid-line] 60px [last-line];
}
.item {
background-color: orange;
}
</style>
<div class="container">
<div class="item item-d"></div>
</div>

4.4. justify-self

  • 单元格内网格项在行轴的对齐方式
1
2
3
.item {
justify-self: start | end | center | stretch;
}
说明 表现
start 对齐单元格的起始左边缘
end 对齐单元格的结束右边缘
center 水平居中
stretch 拉伸。占满单元格整个宽度

4.5. align-self

  • 单元格内网格项在列轴的对齐方式
1
2
3
.item {
align-self: start | end | center | stretch;
}
说明 表现
start 对齐单元格的起始上边缘
end 对齐单元格的起始下边缘
center 垂直居中
stretch 拉伸。占满整个单元格的高度

4.6. place-self

  • align-self 和 justify-self 的连写
  • align-self 和 justify-self 值相同时,可以只写一个值
1
place-self: auto | <align-self> / <justify-self>
本文结束  感谢您的阅读