网页开发入门|12 布局

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

网页开发入门|12 布局

在之前的课程中,我们探讨的大多是一些元素级别的问题,这次让我们放眼整个网页,来研究一下网页的布局Layout问题。

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

说到布局,最经典的布局就是圣杯布局(Holy Grail Layout)了:

圣杯布局
圣杯布局

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

一只圣杯
一只圣杯

圣杯布局也因为中间部分分割为了3个纵向排列的区域,所以也称作三栏式布局。

圣杯布局非常经典,所以很多很多的网站都采用了圣杯布局。

网易首页采用了标准的圣杯布局
网易首页采用了标准的圣杯布局

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

知乎采用了双栏式布局
知乎采用了双栏式布局

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

微软官网采用了单栏式布局
微软官网采用了单栏式布局

大部分的网页布局都可以通过综合使用「盒模型+定位+(我们没有讲的)浮动」来实现,在网络上很多教程里也是这样教的。

但是这个实现方法,多少会有一些「凑巧奏效」的感觉,经常会埋下很多的隐患,在后续的使用和维护中带来莫名其妙的Bug。

每个元素的细微错误都可能导致整体结构崩坏
每个元素的细微错误都可能导致整体结构崩坏

为了不让你陷入困境,本课程完全不打算向你讲解「浮动Float」是怎么回事,更不打算展开讲解「盒模型+定位+浮动」布局实现,而是向你介绍两个更现代的、更方便的布局实现方案:

Flex弹性布局和Grid网格布局。

弹性布局Flex

弹性布局是靠一种叫做「弹性元素」的容器来实现的。

「弹性元素」是一种特殊的「块级元素」,不过与块级元素强调的是「本元素要独占一行」不同,弹性元素强调的是它作为容器时的特性,即它的子元素们应该按照什么方式排列。

所谓容器呢,就是允许有子元素的元素。尽管很多元素都可以充当容器,但没有其它任何效果的div,是一个更受欢迎的容器。

通过将某个divdisplay: 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>
flex实现圣杯布局
flex实现圣杯布局

网格布局Grid

「弹性布局」因足够的灵活,给了子元素充分的「活动空间」,所以称之为「弹性布局Flex」。

与之相对的,还有一种将子元素约束在某个准确位置上的布局方案称为「网格布局Grid」,也有翻译为「栅格布局」的。

在「网格布局」的世界里,页面将被划分为若干行和若干列,就好像是一张大的Excel表格,只不过网格线默认是透明的。

实际的网格布局中网格线默认是透明的
实际的网格布局中网格线默认是透明的

想要实现网格布局,同样需要一个网格容器,通过将某个divdisplay: 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>
使用grid实现了圣杯布局
使用grid实现了圣杯布局
这里用到了一个class的小技巧,将多个class名字之间以空格隔开,即可对元素可以同时设定多个class。

小结

Flex弹性布局和Grid网格布局都是非常好用的现代化布局实现方案,除了文章中提到的属性以外,还有更多样式属性可以帮助实现更复杂的布局需求,你可以到W3C的官网去查询,此处不再赘述。

使用Flex弹性布局或者Grid网格布局,都可以很好的解决综合练习二中的对齐问题。

成稿中三个部分之间没有居中对齐
成稿中三个部分之间没有居中对齐

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

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