Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS进阶之Grid布局 #231

Open
FrankKai opened this issue Jul 2, 2020 · 0 comments
Open

CSS进阶之Grid布局 #231

FrankKai opened this issue Jul 2, 2020 · 0 comments
Labels

Comments

@FrankKai
Copy link
Owner

FrankKai commented Jul 2, 2020

在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布局适用于更大型的布局,宏观布局

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

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

  • 初识grid布局
  • grid五大概念
  • Grid container、Grid Tracks(fr、repeat()、显隐式grid、minmax)、Grid lines、Grid cells、Grid areas、Gutters
  • 嵌套grid布局
  • grid实现覆盖式的布局并通过z-index控制Grid层级、控制Grid顺序

初识grid布局

  • CSS的grid布局,通过定义HTML元素的size,position和layer的关系,可以将一个页面划分成几个主要区域。
  • CSS的grid布局,使作者能够将元素对齐成为列和行。很多情况下的布局,通过grid要比table布局简单得多。例如,一个grid容器的子元素可以定位自身,因此可以实现重叠和层级关系,这跟CSS定位元素是类似的

最简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五大概念

  • 固定和灵活的轨道尺寸(fixed flexible)
  • 条目布局(item)
  • 为已有内容增加额外的轨道(hold content)
  • 对齐控制(alignment)
  • 重叠内容控制(overlap)

固定和灵活的轨道尺寸

  • 固定的轨道尺寸:可以理解为通过像素px创建网格,为网格设置了指定的大小
  • 灵活的轨道尺寸:可以理解为通过百分比或者是全新的fr单位创建的网格

条目布局(item)

  • 可以通过line number,name或者指定网格区域,将元素布局在网格的指定区域
  • grid有自己的算法:即使没有明确指定位置,在网格上也可以布局元素

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

  • 可以在网格布局上定义明确的网格
  • 网格布局很灵活,在需要时可以添加额外的列和行
  • 包括“将尽可能多的列添加到容器”特性

对齐控制(alignment)

  • 可以控制单个网格的对齐
  • 可以控制整体网格的对齐

重叠内容控制(overlap)

  • 一个网格上可以放置多个元素,可以部分重叠,可以通过z-index属性做重叠
  • 当grid与其他的CSS类似flexbox结合时,可以构建出之前无法构建的布局

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

Grid container

  • 通过display:grid或display:inline-grid可以创建出一个grid container
  • 创建了grid container之后,所有grid container下属的子元素都成为了grid item
<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

  • 通过grid-template-columns和grid-template-rows定义行和列,叫做grid track,一个grid track指的是两条线之间的空间
  • 与Grid track相关的概念还有:fr、repeat()函数、隐式grid和显式grid、track大小和minmax
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-template-columns去定义列track的话,grid也会同时创建行,这些行时是隐式grid布局形成的
  • 显式的行grid和列grid,是通过grid-template-columns和grid-template-rows定义出来的
  • 可以通过grid-auto-rows和grid-auto-columns定义隐式grid的tracks

这个例子通过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
  • 创建明确grid布局或者自动创建row和column时,我们希望给track一个最小的大小,同时希望任何添加的内容都能展开。例如,假设我想要我的行不比100像素小,但是我的内容最多拉伸到300像素高,就可以通过minmax()函数来实现。
  • minmax()函数仅仅适用于grid布局。
.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布局我们定义的是track,但是可以通过grid line去为单个track定义占比
  • grid line从1开始计数
    image

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

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
<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中的最小单位是grid cell
  • 最左上角的cell,grid-column-start/grid-column-end和grid-row-start/grid-row-end都为1
    image
Grid areas
  • grid item可以占据多个grid cell,row方向和column方向都行,占据了多个cell叫做area
  • grid area必须是矩形,不能构建出L形的grid区域
Gutter
  • 可以通过column-gap和row-gap为grid cell设置grid cell之间的间隙
  • 通常为了布局美观,需要为grid container增加一个padding
.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

  • 通过display: grid;grid-template-columns: repeat(3, 1fr);将第一行内的子元素变为grid布局
  • 通过grid-row-start: 1;控制box1的顺序;grid-row-start: 2;grid-row-start: 3;可以将其放置在下面

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

学习和实践感悟

  • grid布局与flex布局最大的不同,在于实现多行布局更加便捷,这是因为在一个flex容器内,实现多行布局较为困难,而grid可以很方便的通过grid lines去划分自己占据的空间
  • css tricks上的文章所说的 “grid布局适用于更大型的布局,宏观布局” ,这句话我认为是非常正确的;现代化的布局,应该是 “宏观grid + 微观flex布局” 的组合
@FrankKai FrankKai added the CSS label Jul 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant