FrankKai / FrankKai.github.io

FE blog
https://frankkai.github.io/
362 stars 39 forks source link

CSS进阶之Grid布局 #231

Open FrankKai opened 4 years ago

FrankKai commented 4 years ago

在css-tricks的A Complete Guide to Flexbox一文中,有这样一句话:

Flexbox layout is most appropriate to the components of an application, and small-scale layouts, while the Grid layout is intended for larger scale layouts.

我一直以来觉得flex布局已经够用了,因此一直没有学习grid布局。 但是看到这句话,让我对grid产生了一些兴趣,到底grid是不是如作者所说:“grid适用于大型布局”,暂时先画一个问号“?”

当这篇博文结束时,相信对这个问号会有一个好的答案。

初识grid布局

最简grid布局示例

image

<div class="wrapper">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
  <div class="four">Four</div>
  <div class="five">Five</div>
  <div class="six">Six</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr); // 3是重复次数,fr是flex系数
  grid-gap: 10px; // row-gap column-gap
  grid-auto-rows: minmax(100px, auto); // 行的最小最大宽度
}
.one {
  grid-column: 1 / 3; // grid-column-start, grid-column-end 从1开始到3结束(不包括3),可以理解成从1~3边区间内的面积。边的编号从1开始
  grid-row: 1; // grid-row-start, grid-row-end 1,auto区间内的面积。边的编号从1开始
}
.two { 
  grid-column: 2 / 4;
  grid-row: 1 / 3;
}
.three {
  grid-column: 1;
  grid-row: 2 / 5;
}
.four {
  grid-column: 3;
  grid-row: 3;
}
.five {
  grid-column: 2;
  grid-row: 4;
}
.six {
  grid-column: 3;
  grid-row: 4;
}

grid五大概念

固定和灵活的轨道尺寸

条目布局(item)

为已有内容增加额外的轨道(hold content)

对齐控制(alignment)

重叠内容控制(overlap)

Grid container、Grid Tracks(fr、repeat()、显隐式grid、minmax)、Grid lines、Grid cells、Grid areas、Gutters

Grid container

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>
.wrapper{
    display: grid;
}

通过为.wrapper设置display:grid属性,从默认的block变为grid,构建出一个grid container。 打开devtool选中某个grid item时,grid会有明显的虚线;普通布局不会有。

grid布局: image

普通布局: image

Grid Tracks

row track和column track

这是一个row track image

可以通过grid-template-columns定义列track的宽度

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: 200px 200px 200px;
}

image

fr、repeat()、显隐式grid、minmax
fr

track可以通过任何长度单位定义。 grid同样引入了一种特殊的长度单位去创建灵活的grid track。 这个单位就是fr,它代表的是网格容器中可用空间的一个部分。 下面的grid定义会创建三个等宽的track,宽度根据可用空间进行grow和shrink。

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

image

如果1和4想占据2个单位的宽度的话,可以这样:

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}

下面这样的如何表现呢?

.wrapper {
  display: grid;
  grid-template-columns: 500px 1fr 2fr;
}

第一个track 500px宽;剩余的空间3等分,按照1比2的比例分配出去。 image

repeat()函数

如果有很多重复的track的话,可以用repeat()函数来写。 例如下面的例子:

.wrapper {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
}

可以写成这样:

.wrapper {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}

不仅仅可以单独使用repeat()函数,还可以与px以及其他的组合使用。

.wrapper {
     display: grid;
     grid-template-columns: 20px repeat(6, 1fr) 20px;
}

而且可以repeat多个track,例如下面这样: 5个1:2分割的track,总计10个。

.wrapper {
    display: grid;
    grid-template-columns: repeat(5, 1fr 2fr);
}
显隐式grid

这个例子通过grid-auto-rows,确保隐式的grid高度为200px。

<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 200px;
}

image

minmax
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
}
<div class="wrapper">
  <div>One</div>
  <div>Two
    <p>I have some more content in.</p>
    <p>This makes me taller than 100 pixels.</p>
  </div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>

image

Grid lines

来看一个在这些属性上运用了grid line的例子:

<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
  <div class="box4">Four</div>
  <div class="box5">Five</div>
</div>
.wrapper { 
  display: grid; 
  grid-template-columns: repeat(3, 1fr); 
  grid-auto-rows: 100px; 
} 

.box1 { 
  grid-column-start: 1; 
  grid-column-end: 4; 
  grid-row-start: 1; 
  grid-row-end: 3; 
}

.box2 { 
  grid-column-start: 1; 
  grid-row-start: 3; 
  grid-row-end: 5; 
}

image

Grid cells
Grid areas
Gutter
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 10px;
  row-gap: 1em;
}
<div class="wrapper">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
</div>

image

嵌套grid布局

<div class="wrapper">
  <div class="box box1">
    <div class="nested">a</div>
    <div class="nested">b</div>
    <div class="nested">c</div>
  </div>
  <div class="box box2">Two</div>
  <div class="box box3">Three</div>
  <div class="box box4">Four</div>
  <div class="box box5">Five</div>
</div>

image

.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

image

grid-row-start: 2 image grid-row-start: 3 image

grid实现覆盖式的布局并通过z-index控制Grid层级、控制Grid顺序

grid实现覆盖式的布局

grid布局不可做覆盖式的布局。

<div class="wrapper">
  <div class="box box1">One</div>
  <div class="box box2">Two</div>
  <div class="box box3">Three</div>
  <div class="box box4">Four</div>
  <div class="box box5">Five</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
}

.box2 {
  grid-column-start: 1;
  grid-row-start: 2;
  grid-row-end: 4;
}

image

通过z-index控制Grid层级、控制Grid顺序

.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
}

.box1 {
  grid-column-start: 1;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 3;
  z-index: 2;
}

.box2 {
  grid-column-start: 1;
  grid-row-start: 2;
  grid-row-end: 4;
  z-index: 1;
}

image

学习和实践感悟