网页开发入门|12 布局
布局的意义在于让网页中丰富的内容有机的组织起来,让用户更快的找到需要的信息。

在之前的课程中,我们探讨的大多是一些元素级别的问题,这次让我们放眼整个网页,来研究一下网页的布局Layout问题。
布局的意义在于让网页中丰富的内容有机的组织起来,让用户更快的找到需要的信息。
说到布局,最经典的布局就是圣杯布局(Holy Grail Layout)了:

大概是因为头部和底部比较大,腰比较瘦,有那么一点像是圣杯的造型,因此得名。

圣杯布局也因为中间部分分割为了3个纵向排列的区域,所以也称作三栏式布局。
圣杯布局非常经典,所以很多很多的网站都采用了圣杯布局。

还有一些是简化版的圣杯布局,在中间部分省略为2个纵向排列的区域,也称作双栏式布局。

还有干脆只留下一个核心区的单栏式布局。

大部分的网页布局都可以通过综合使用「盒模型+定位+(我们没有讲的)浮动」来实现,在网络上很多教程里也是这样教的。
但是这个实现方法,多少会有一些「凑巧奏效」的感觉,经常会埋下很多的隐患,在后续的使用和维护中带来莫名其妙的Bug。

为了不让你陷入困境,本课程完全不打算向你讲解「浮动Float」是怎么回事,更不打算展开讲解「盒模型+定位+浮动」布局实现,而是向你介绍两个更现代的、更方便的布局实现方案:
Flex弹性布局和Grid网格布局。
弹性布局Flex
弹性布局是靠一种叫做「弹性元素」的容器来实现的。
「弹性元素」是一种特殊的「块级元素」,不过与块级元素强调的是「本元素要独占一行」不同,弹性元素强调的是它作为容器时的特性,即它的子元素们应该按照什么方式排列。
所谓容器呢,就是允许有子元素的元素。尽管很多元素都可以充当容器,但没有其它任何效果的div
,是一个更受欢迎的容器。
通过将某个div
的display: flex
,即可将其变为弹性元素,也可以称为弹性容器Flex Container,其子元素则会自动变成弹性项目Flex Item。
让我们在workspace
中创建一个新的文件layout.html
来看体验一下效果。
.flex-container {
display: flex;
}
.red-item {
background-color: red;
width: 120px;
height: 120px;
}
.green-item {
background-color: green;
width: 120px;
height: 240px;
}
.blue-item {
background-color: blue;
width: 60px;
height: 120px;
}
<div class="flex-container">
<div class="red-item"></div>
<div class="green-item"></div>
<div class="blue-item"></div>
</div>

可以看到在弹性布局下,最显著的变化是:原本应该独占一行的div
子元素们,现在现在变成了横向排列,就好像把它们设置成了inline-block
一样。
不用inline-block
的好处除了减少了代码量以外,还体现了在软件设计中重要的哲学:「低耦合」,可以简单理解为「各司其职」。即容器里的子元素们管好自己的样式就好,如何排列这些子元素应该由容器来决定。
弹性容器就是这样一种负责任的容器,可以很方便的设定子元素应该如何排列。
比如说,可以设定子元素的排列方向:
.flex-container {
display: flex;
flex-direction: row-reverse; /* 反向排列 */
}

.flex-container {
display: flex;
flex-direction: column; /* 纵向排列 */
}

还可以设定元素之间的对齐方式:
.flex-container {
display: flex;
justify-content: center; /* 居中 */
}

.flex-container {
display: flex;
justify-content: space-between; /* 拉伸 */
}

.flex-container {
display: flex;
justify-content: space-around; /* 均匀 */
}

当然,还可以设定纵向的对齐:
.flex-container {
display: flex;
align-items: flex-end; /* 底部对齐 */
}

.flex-container {
display: flex;
align-items: center; /* 居中对齐 */
}

有了Flex,想要去实现圣杯布局就非常容易了,只需在这个容器的上面和下面分别放一个块级元素即可。
<div class="header"></div>
<div class="flex-container">
<div class="red-item"></div>
<div class="green-item"></div>
<div class="blue-item"></div>
</div>
<div class="footer"></div>

网格布局Grid
「弹性布局」因足够的灵活,给了子元素充分的「活动空间」,所以称之为「弹性布局Flex」。
与之相对的,还有一种将子元素约束在某个准确位置上的布局方案称为「网格布局Grid」,也有翻译为「栅格布局」的。
在「网格布局」的世界里,页面将被划分为若干行和若干列,就好像是一张大的Excel
表格,只不过网格线默认是透明的。

想要实现网格布局,同样需要一个网格容器,通过将某个div
的display: grid
,即可将其变为网格容器,其子元素将自动成为网格项目。
除此之外,还需要明确的定义这个网格有多少行和多少列,并且多高多宽。
.grid-container {
display: grid;
grid-template-columns: 120px 120px 60px;
grid-template-rows: 60px 120px 60px;
}
.grid-item {
background-color: brown;
margin: 10px;
}
我们定义一个三行三列的网格,每个格子宽和高也同时进行了设定,并放入9个子元素。为了方便看清子元素,也给它们加上10px的外边距。
<div class="grid-container">
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
</div>
网格容器中的元素将被依次分配进入到网格中的格子,也因此元素的宽高尺寸不再由自己决定,而是由格子的尺寸来决定。

网格布局真正有用的地方在于,它允许子元素跨越多个格,即类似Excel中「合并单元格」的效果。
当然,这需要调整子元素的CSS
:
.long-grid-item {
grid-column: span 3;
}
<div class="grid-container">
<div class="grid-item long-grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item long-grid-item"></div>
</div>

这里用到了一个class的小技巧,将多个class名字之间以空格隔开,即可对元素可以同时设定多个class。
小结
Flex弹性布局和Grid网格布局都是非常好用的现代化布局实现方案,除了文章中提到的属性以外,还有更多样式属性可以帮助实现更复杂的布局需求,你可以到W3C
的官网去查询,此处不再赘述。
使用Flex弹性布局或者Grid网格布局,都可以很好的解决综合练习二中的对齐问题。

稍微看一下B站的源码,它是使用Flex方案实现的。而且不但导航栏整体是flex,而且其中每一个部分也都是用flex实现的。

我将本课程所有的代码托管在gitee
上了,你可以点击这个链接,或到gitee.com
上搜索弦五 网页开发入门,查看和获取本课程的全部代码。