CSS 常见布局方式

CSS 常见布局方式

今天在网上看到一张图,是关于 CSS 常见的布局方式汇总的一张图,如下

最近刚好也在复习相关内容,所以就借着这个机会从新整理一下 CSS 当中比较常见的一些布局方式,就当是复习复习布局相关知识点,下面我们就一个一个来介绍,示例集合可见 demos 当中的 CSS 板块

文档流布局

示例可见 文档流布局,也是 CSS 当中最基本的布局方式,就是按照文档的顺序一个一个显示出来,块元素独占一行,行内元素共享一行,如下

浮动布局

示例可见 浮动布局,也是比较常见的布局方式,不过在 flex 流行以后,这种方式已经使用的比较少了,原理是使用 float 属性,使元素脱离文档流,浮动起来,不过需要注意在使用该属性时引起的其他问题(譬如高度崩塌)

定位布局

示例可见 定位布局,与浮动布局类似,也是使元素脱离文档流,浮动起来,不过使用的是 position 属性,结果与浮动布局是一致的

至于两者有何区别,简单来说各有各的优缺点,很多时候我们希望控制的布局流问题不需要 floatposition 实现,而应该通过显示模型定义来解决,比如现在的 column layoutflex box 等等,也就是下面将要说到的,都是在这个角度解决我们遇到的问题,它们应该才是正解

圣杯布局和双飞翼布局

两者的本质其实是差不多的,就是两边顶宽,中间自适应的三栏布局,中间栏要在放在文档流前面以优先渲染,详细的可以参考 CSS布局中圣杯布局与双飞翼布局的实现思路差异在哪里?,这里只截取部分

简单来说就是,双飞翼布局比圣杯布局多创建了一个 div,但是不需要使用相对布局了,圣杯布局和双飞翼布局解决问题的方案在前一半是相同的,也就是三栏全部 float 浮动,但左右两栏加上负 margin 让其跟中间栏 div 并排,以形成三栏布局,不同之处在于解决中间栏 div 内容不被遮挡问题的思路不一样

  • 圣杯布局,为了中间 div 内容不被遮挡,将中间 div 设置了左右 padding-leftpadding-right 后,将左右两个 div 用相对布局 position: relative 并分别配合 rightleft 属性,以便左右两栏 div 移动后不遮挡中间 div
  • 双飞翼布局,为了中间 div 内容不被遮挡,直接在中间 div 内部创建子 div 用于放置内容,在该子 div 里用 margin-leftmargin-right 为左右两栏 div 留出位置

对比下来可以发现,双飞翼布局多了一个 div,少用大致四个 CSS 属性,至于具体使用哪种方案可以根据实际情况来选择

圣杯布局

实现以后如下所示,示例可见 圣杯布局

页面布局如下,很简单的三个 div 被外层父元素包裹,没用多余的额外元素

1
2
3
4
5
<div class="wrapper">
<div class="content">Content</div>
<div class="left">Left</div>
<div class="right">Right</div>
</div>

核心 CSS 代码如下

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
.wrapper {
padding: 0 200px;
}

.content {
width: 100%;
height: 200px;
float: left;
}

.left {
width: 200px;
height: 200px;
float: left;
position: relative;
left: -200px;
margin-left: -100%;
}

.right {
width: 200px;
height: 200px;
float: left;
position: relative;
right: -200px;
margin-left: -200px;
}

双飞翼布局

如果你手动实现一遍以后就会发现,圣杯布局是有弊端的,当你将浏览器宽度缩短到一定程度的时候,会使得中间子元素的宽度比左右子元素宽度小的时候,这时候布局就会出现问题,而双飞翼布局的出现就是为了解决此类问题,实现的结果与圣杯布局是一致的,示例可见 双飞翼布局

页面布局如下,与圣杯布局相比有些许不同,可以发现在 Content 的外部多了一层 div,而这个 div 就是用来解决上述问题的

1
2
3
4
5
<div class="content-wrapper">
<div class="content">Content</div>
</div>
<div class="left">Left</div>
<div class="right">Right</div>

核心 CSS 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.content-wrapper {
width: 100%;
height: 200px;
float: left;
}

.content {
margin-left: 200px;
margin-right: 200px;
}

.left {
width: 200px;
height: 200px;
float: left;
margin-left: -100%;
}

.right {
width: 200px;
height: 200px;
float: left;
margin-left: -200px;
}

flex 布局

关于 flex 部分内容主要截取自 flex 布局,感觉讲的比较好理解,图文相对应,不过其中有一些调整,并且添加了一些内容,主要是方便自己比较好理解,如果想了解更多的话可以参考原文

flex 是一种新型的布局方式,使用该布局方式可以实现几乎所有你想要的效果,但是要注意其浏览器的兼容性,flex 只支持 IE 10 以上,flex 的使用方法很简单,只需要将元素的 display 属性设置为 flex 就可以,也可以设置行内的 flexinline-flex

有一个特别需要需要的地方,当设置元素为 flex 布局之后,子元素的 floatclearvertical-align 的属性将会失效

flex 中,最核心的概念就是容器和轴,所有的属性都是围绕容器和轴设置的,其中容器分为父容器和子容器,轴分为主轴和交叉轴

主轴默认为水平方向,方向向右,交叉轴为主轴顺时针旋转 90°

在使用 flex 的元素中,默认存在两根轴

  • 水平的主轴(main axis
    • 主轴开始的位置称为 main start
    • 结束的位置称为 main end
  • 垂直的交叉轴(cross axis
    • 交叉轴开始的位置称为 cross start
    • 结束的位置称为 cross end

在使用 flex 的子元素中,占据的主轴空间叫做 main size,占据的交叉轴空间叫做 cross size,如下图所示

之前整理过一篇关于子容器的 flex 取值相关问题,可见 关于子容器属性 flex 取值问题,不过关于容器和元素的属性也只是一笔带过,所以就在之前的基础上扩充一下吧

父容器

首先,实现 flex 布局需要先指定一个容器,任何一个容器都可以被指定为 flex 布局,这样容器内部的元素就可以使用 flex 来进行布局

父容器可以统一设置子容器的排列方式,子容器也可以单独设置自身的排列方式,如果两者同时设置,以子容器的设置为准

有下面六种属性可以设置在父容器上,它们分别是

  • flex-direction,主轴的方向
  • flex-wrap,超出父容器子容器的排列样式
  • flex-flowflex-direction 属性和 flex-wrap 属性的简写形式
  • justify-content,子容器在主轴的排列方向
  • align-items,子容器在交叉轴的排列方向
  • align-content,多根轴线的对齐方式

下面我们就来一个一个深入了解一下

flex-direction

决定主轴的方向(即项目的排列方向),但是主轴的方向不一定是水平的,这个属性就是设置主轴的方向,默认是水平方向,从左至右,如果主轴方向设置完毕,那么交叉轴就不需要设置,交叉轴永远是主轴顺时针旋转 90°

1
2
3
4
5
6
.div {
flex-direction: row; // 默认值,主轴为水平方向,起点在左端
flex-direction: row-reverse; // 主轴为水平方向,起点在右端
flex-direction: column; // 主轴为垂直方向,起点在上
flex-direction: column-reverse; // 主轴为垂直方向,起点在下
}

flex-wrap

flex-wrap 属性决定子容器是否换行排列,不但可以顺序换行而且支持逆序换行

1
2
3
4
5
.ele {
flex-wrap: nowrap; // 默认,不换行
flex-wrap: wrap; // 换行,第一行在上方
flex-wrap: wrap-reverse // 换行,第一行在下方,也就是逆序换行
}

justify-content

主要用于定义如何沿着主轴方向排列子容器

1
2
3
4
5
6
7
8
.ele{
justify-content: flex-start; // 默认,左对齐
justify-content: flex-end; // 右对齐
justify-content: center; // 居中
justify-content: space-between; // 两端对齐,项目之间的间隔都相等
justify-content: space-around; // 每个项目两侧的间隔相等,所以项目之间的间隔比项目与边框的间隔大一倍
//(即位于首尾两端的子容器到父容器的距离是子容器间距的一半)
}

flex-flow

flow 即流向,也就是子容器沿着哪个方向流动,流动到终点是否允许换行,比如 flex-flow: row wrapflex-flow 是一个复合属性,相当于 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap

  • rowcolumn 等,可单独设置主轴方向
  • wrapnowrap 等,可单独设置换行方式
  • row nowrapcolumn wrap 等,也可两者同时设置
align-items

align-items 属性定义子容器在交叉轴上如何对齐,具体的对齐方式与交叉轴的方向有关,假设交叉轴从上到下

1
2
3
4
5
6
7
8
9
10
.ele{
align-items: flex-start; // 交叉轴的起点对齐,
align-items: flex-end; // 交叉轴的终点对齐,
align-items: center; // 交叉轴的中点对齐,
align-items: baseline; // 项目的第一行文字的基线对齐
// 这里的 baseline 默认是指首行文字,即 first baseline,所有子容器向基线对齐
// 交叉轴起点到元素基线距离最大的子容器将会与交叉轴起始端相切以确定基线)
align-items: stretch; // 默认,如果项目未设置高度或设为 auto,将占满整个容器的高度
//(子容器沿交叉轴方向的尺寸拉伸至与父容器一致)
}

align-content

align-content 属性定义了多根轴线的对齐方式,如果项目只有一根轴线,该属性不起作用,简单来说就是当子容器多行排列时,设置行与行之间的对齐方式

1
2
3
4
5
6
7
8
.ele{
align-content: flex-start; // 与交叉轴的起点对齐
align-content; flex-end; // 与交叉轴的终点对齐
align-content: center; // 与交叉轴的中点对齐
align-content: space-between; // 与交叉轴两端对齐,轴线之间的间隔平均分布
align-content: space-around; // 每根轴线两侧的间隔都相等,所以,轴线之间的间隔比轴线与边框的间隔大一倍
align-content: stretch; // 默认 轴线占满整个交叉轴
}

子容器

子容器也有六个属性

  • order,子容器的排列顺序
  • flex-grow,子容器剩余空间的拉伸比例
  • flex-shrink,子容器超出空间的压缩比例
  • flex-basis,子容器在不伸缩情况下的原始尺寸
  • flexflex-growflex-shrinkflex-basis 的简写
  • align-self,允许子容器与其他项目采用不一样的对齐方式
order

order 属性定义项目的排列顺序,可以为负值,数值越小,排列越靠前,默认为 0

1
2
3
.ele{
order: num;
}

flex-grow

flex-grow 属性定义子容器的伸缩比例,按照该比例给子容器分配空间,默认值为 0

1
2
3
.ele{
flex-grow: <number>;
}

flex-shrink

flex-shrink 属性定义了子容器弹性收缩的比例,如图,超出的部分按 1: 2 的比例从给子容器中减去

此属性要生效,父容器的 flex-wrap 属性要设置为 nowrap,默认值为 0

1
2
3
.ele{
flex-shrink: <number>;
}

flex-basis

flex-basis 属性定义了子容器在不伸缩情况下的原始尺寸,主轴为横向时代表宽度,主轴为纵向时代表高度,默认值为 0

1
2
3
.ele{
flex-basis: <length> | auto;
}

flex

子容器是有弹性的,它们会自动填充剩余空间,子容器的伸缩比例由 flex 属性确定,flex 的值可以是无单位数字(如:123),也可以是有单位数字(如:15px30px60px),还可以是 none 关键字,子容器会按照 flex 定义的尺寸比例自动伸缩,如果取值为 none 则不伸缩,虽然 flex 是多个属性的缩写,允许 1 - 3 个值连用,但通常用 1 个值就可以满足需求,它的全部写法可参考下图

具体取值规则可以参考之前整理的一篇文章 关于子容器属性 flex 取值问题

align-self

子容器的 align-self 属性允许单个项目有与其他项目不一样的对齐方式,它会覆盖父容器 align-items 属性,如果两者同时设置则以子容器的 align-self 属性为准,默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch

1
2
3
4
5
6
7
8
.ele{
align-self: auto; // 继承父元素的 align-items 属性
align-self: flex-start; // 交叉轴的起点对齐
align-self: flex-end; // 交叉轴的终点对齐
align-self: center; // 交叉轴的中点对齐
align-self: baseline; // 项目的第一行文字的基线对齐
align-self: stretch; // 默认,如果项目未设置高度或设为 auto,将占满整个容器的高度
}

下面是一张各属性的汇总图

grid 布局

主要参考的 Learn CSS Grid in 5 minutes,按照惯例,在使用之前我们先来看一下 CSS Grid 的兼容性,如下

可以发现,主流浏览器(SafariChromeFirefoxEdge)的支持还是不错的,那么我们就来看看 CSS Grid 到底是个什么东西,全部示例可见 网格布局网格版圣杯布局

基本概念

我们先从一个简单的示例开始,然后在深入了解其中的概念,CSS Grid 布局由两个核心组成部分是 wrapper(父元素)和 items(子元素),wrapper 是实际的 grid(网格),items 是网格内的内容,下面是一个 wrapper 元素,内部包含六个 items

1
2
3
4
5
6
7
8
<div class="wrapper">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>

要把 wrapper 元素变成一个网格,只要简单地把其 display 属性设置为 grid 即可

1
2
3
.wrapper {
display: grid;
}

在这种情况下,我们并没有做其他的操作,它只会简单地将六个 div 堆叠在一起,如下图所示

为了使其成为二维的网格容器,我们需要定义列和行,让我们创建 3 列和 2 行,我们将使用 grid-template-rowgrid-template-column 属性

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 50px 50px;
}

这些值决定了我们希望我们的列有多宽(100px),以及我们希望行数是多高(50px),结果如下

也可以来稍微的调整一下,比如应用以下 CSS 样式

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: 200px 50px 100px;
grid-template-rows: 100px 30px;
}

就变成了如下

此时,我们已经了解了 CSS Grid 布局的基本过程,下面我们就来了解一下相应的术语

网格容器(Grid Container)

应用 display: grid 的元素,就是所有网格项(grid item)的直接父级元素,在上面的例子中 wrapper 就是网格容器(Grid Container

1
2
3
<div class="wrapper">
...
</div>

网格项(Grid Item)

网格容器(Grid Container)的子元素(例如直接子元素),比如下面这里 item 元素就是网格项(Grid Item),但是 sub-item 不是

1
2
3
4
5
6
7
<div class="wrapper">
<div class="item"></div>
<div class="item">
<p class="sub-item"></p>
</div>
<div class="item"></div>
</div>

网格线(Grid Line)

网格线组成了网格,他是网格的水平和垂直的分界线,一个网格线存在行或列的两侧,我们可以引用它的数目或者定义的网格线名称

网格轨道(Grid Track)

网格轨道是就是相邻两条网格线之间的空间,就好比表格中行或列,所在在网格中其分为 grid columngrid row,每个网格轨道可以设置一个大小,用来控制宽度或高度

网格单元格(Grid Cell)

网格单元格是指四条网格线之间的空间,所以它是最小的单位,就像表格中的单元格

网格区域(Grid Area)

网格区域是由任意四条网格线组成的空间,所以他可能包含一个或多个单元格,相当于表格中的合并单元格之后的区域

以上就是网格布局中的一些基本概念,下面我们来看具体的操作方法

使用 Grid 布局

我们还是在最开始部分的示例之上来进行扩展,首先还是先创建一个 3×3 的网格

需要注意的是,同 flex 布局一样,当元素设置了网格布局之后,元素的 columnfloatclearvertical-align 属性都是无效的

1
2
3
4
5
6
7
8
<div class="wrapper">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
<div class="item6">6</div>
</div>

应用的 CSS 代码如下

1
2
3
4
5
.wrapper {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}

将得到以下布局

细心对比可以发现,我们只在页面上看到 3×2 的网格,而我们定义的则是 3×3 的网格,这是因为我们只有六个子元素来填满这个网格,如果我们再加三个子元素,那么最后一行也会被填满

如果还存在更多的子元素,则是被忽略(即默认是不可见的)

如果要定位和调整子元素大小,我们将使用 grid-columngrid-row 属性来设置

1
2
3
4
.item1 {
grid-column-start: 1;
grid-column-end: 4;
}

我们在这里要做的是,我们希望 item1 占据从第一条网格线开始,到第四条网格线结束,换句话说,它将独立占据整行, 以下是在屏幕上显示的内容

可以发现,当我们把第一个子元素设置为占据整个第一行时,它会把剩下的子元素都推到了下一行,至于为什么会有四条网格线,可以参考下面这个图

当然,也可以使用简写方式来实现

1
2
3
.item1 {
grid-column: 1/4;
}

下面我们就可以将所有的子元素进行自定义排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.item1 {
grid-column-start: 1;
grid-column-end: 3;
}

.item3 {
grid-row-start: 2;
grid-row-end: 4;
}

.item4 {
grid-column-start: 2;
grid-column-end: 4;
}

也可以采用简写的方式

1
2
3
4
5
6
7
8
9
10
11
.item1 {
grid-column: 1/3;
}

.item3 {
grid-row: 2/4;
}

.item4 {
grid-column: 2/4;
}

最终结果如下

我们也可以像 flex 一样设置每一列的宽度

1
2
3
4
.wrapper {
grid-template-rows: 50px 100px 60px;
grid-template-columns: 1fr 1fr 1fr;
}

可以发现,在上面的示例当中我们使用了一个新的单位 fr

fr 单位是一个自适应单位,fr 单位被用于在一系列长度值中分配剩余空间,如果多个已指定了多个部分,则剩下的空间根据各自的数字按比例分配

fr 是基于网格容器可用空间来计算的(flex 也是一样),所以我们可以和其他单位混合使用(如果需要的话)

结果如下

也可以利用这个特性来进行单元格的合并

行或列最小和最大尺寸

minmax() 函数来创建行或列的最小或最大尺寸,第一个参数定义网格轨道的最小值,第二个参数定义网格轨道的最大值,可以接受任何长度值,也接受 auto 值,auto 值允许网格轨道基于内容的尺寸拉伸或挤压,我们来试试将第一行的高度设置为 minmax(100px, 200px),第二行的高度设置为 minmax(50px, 200px),容器总高度设置为 300px,如下

1
2
3
4
5
.wrapper {
height: 300px;
grid-template-rows: minmax(100px, 200px) minmax(50px, 200px);
grid-template-columns: 1fr 1fr 1fr;
}

具体逻辑为,先判断『总高度』和『第一列高度的最大值和第二列高度的最大值之和』的两者之间的大小

  • 如果大于,那么第一列和第二列的高度都为设置的最大值
  • 如果是小于,那么第一列和第二列的高度都为设置的最小值

在上面的情况当中是属于小于的情况,所以会先使用总高度减去两列的最小高度得出一个值,在根据这个值来计算最终的高度

  • 总高度为,第一列最小高度 - 第二列最小高度 = 150px300px - 100px - 50px = 150px
  • 第一列高度为,(第一列最小高度 100px+ 150px/2 = 175px
  • 第二列高度为,(第一列最小高度 50px+ 150px/2 = 125px

如下图所示

重复行或者列

repeat() 属性可以创建重复的网格轨道,这个适用于创建相等尺寸的网格项目和多个网格项目,repeat() 也接受两个参数,第一个参数定义网格轨道应该重复的次数,第二个参数定义每个轨道的尺寸,简单来说就是简化同样的赋值操作,结果如下图

间距

主要使用 grid-column-gapgrid-row-gap 两个属性

  • grid-column-gap,创建列与列之间的距离
  • grid-row-gap,行与行之间的距离
  • grid-gap,简写方式,第一个参数为行间距,第二个参数为列间距
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.wrapper {
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
grid-row-gap: 10px;
grid-column-gap: 20px;
}

/* 等同于 ==> */

.wrapper {
grid-template-rows: 100px 100px;
grid-template-columns: 100px 100px 100px;
grid-gap: 10px 20px;
}

网格区域(grid-template-areas)

所谓网格区域(网格区域),简单来说就是一个逻辑空间,主要用来放置一个或多个网格单元格(Grid Cell),它由四条网格线(Grid line)构成,网格区域每边一条,四边相交组织的网格轨道(Grid Track

简单点理解,网格区域是有四条网格线交织组成的网格空间,这个空间中可能是一个网格单元格,也可能是多个网格单元格,在 CSS Grid Layout 中定义网格区域有两种方式,一种是通过网格线来定义,另一种是通过 grid-template-areas 来定义

网格线定义网格区域

简单来说有下面三个步骤

  • 使用网格线定义网格区域的方法非常的简单,首先依赖于 grid-template-columnsgrid-template-rows 显式定义网格线,甚至是由浏览器隐式创建网格线
  • 然后通过 grid-area 属性通过取网格线,组成网格线交织区域,那么这个区域就是所讲的网格区域
  • 在使用 grid-area 属性调用网格线,其遵循的取值规则如下
1
grid-area: row-start/column-start/row-end/column-end
使用 grid-template-areas 定义网格区域

除了使用网格线的交组来定义网格区域之外,在 CSS Grid Layout 中还可以通过 grid-template-areas 属性来定义网格区域的名称,然后需要放在对应网格区域的元素,可以通过 grid-area 属性来指定,而且重复区域可以使用同一个名称来实现跨区域,另外对于空的轨道区域,可以使用点号 . 来代表

具体的使用细节我们就通过下面这个实例来充分的了解一下所谓的网格区域

实例

我们要实现的最终结果如下

接下来,我们就一步一步来进行实现

HTML 结构

首先我们需要一个容器,如下

1
2
3
4
5
6
<div class="container">
<div class="header">HEADER</div>
<div class="menu">MENU</div>
<div class="content">CONTENT</div>
<div class="footer">FOOTER</div>
</div>
设置基本的 CSS

在来设置一些基本的 CSS

1
2
3
4
5
6
.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 50px 350px 50px;
grid-gap: 5px;
}

经过前面的一些铺垫,这里应用的 CSS 应该很容易理解

  • 使用 grid-template-columns 属性创建一个 12 列的网格,每个列都是一个单位宽度(总宽度的 1/12
  • 使用 grid-template-rows 属性创建 3 行,第一行高度是 50px ,第二行高度是 350px 和第三行高度是 50px
  • 最后,使用 grid-gap 属性在网格中的网格项之间添加一个间隙
添加 grid-template-areas

下面就是重点部分,来添加我们的网格区域,简单来说也就是定义 grid-template-areas 属性

1
2
3
4
5
6
7
8
9
10
.container {
display: grid;
grid-gap: 5px;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 50px 350px 50px;
grid-template-areas:
"h h h h h h h h h h h h"
"m m c c c c c c c c c c"
"f f f f f f f f f f f f";
}

grid-template-areas 属性背后的逻辑是你在代码中创建的网格可视化表示,正如所见,它有 312 列,和我们在 grid-template-columnsgrid-template-rows 中定义的正好呼应,每行代表一行,用网格术语来说是 网格轨道(Grid Track) ,每个字符(hmcf)代表一个网格单元格,四个字母中的每一个现在都形成一个矩形 grid-area(当然你也可以使用自定义字符)

给网格项设定网格区域名称

现在我们需要将这些字符与网格中的网格项建立对应的连接,要做到这一点,我们将在网格项使用 grid-area 属性

1
2
3
4
5
6
7
8
9
10
11
12
.header {
grid-area: h;
}
.menu {
grid-area: m;
}
.content {
grid-area: c;
}
.footer {
grid-area: f;
}

最终的结果如下(添加了一些额外的 CSS 样式用于展示)

尝试其他布局

现在,我们可以探讨一下使用网格布局的精妙之处,因为我们可以很容易地对布局进行修改尝试,只需修改 grid-template-areas 属性的字符即可,举个例子,比如把 menu 移到右边

1
2
3
4
5
6
.wrapper {
grid-template-areas:
"h h h h h h h h h h h h"
"c c c c c c c c c c m m"
"f f f f f f f f f f f f";
}

可以使用点 . 来创建空白的网格单元格

1
2
3
4
5
6
.wrapper {
grid-template-areas:
". h h h h h h h h h h ."
"c c c c c c c c c c m m"
". f f f f f f f f f f .";
}

还可以添加响应式布局

1
2
3
4
5
6
7
8
@media screen and (max-width: 640px) {
.container {
grid-template-areas:
"m m m m m m h h h h h h"
"c c c c c c c c c c c c"
"f f f f f f f f f f f f";
}
}

最终结果如下

参考

# CSS

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×