理解双飞翼与圣杯布局

waterhydroxyl 发布于

今天网上冲浪看到一篇小米面经,其中三面有一道经典的两侧定宽,中间自适应的题目,但是加了点东西,就是头部一个header,header下面是经典案例,但是要求各个元素有显示顺序,header->center->left->right。可以用双飞翼布局实现

什么是双飞翼布局?

双飞翼布局则是源于淘宝的UED,可以说是灵感来自于页面渲染。一起来看看淘宝的头部实现:就是两边定宽,中间自适应的三栏布局,中间栏要放在文档流前面以优先渲染。

double-wings

总的来说,双飞翼布局主要解决俩问题:1、三列布局,中间宽度自适应,两边定宽; 2、中间栏要在浏览器中优先展示渲染。

在css布局中,有三种技术是经常被使用的:

  • (1)浮动 (float)

  • (2)负边距 (negative margin)

  • (3)定位 (position)

这是实现布局的三个最基本的原子技术。只要巧妙组合,并加以灵活运用,就能“拼”出各种布局的实现方案。

如果三列布局不使用双飞翼布局,左右分别float:lef和right,中间不浮动,存在问题:

(1)中间栏必须放在left和right之后,会最后被渲染

(2)浮动元素和非浮动元素相碰会出现问题,比如脱离文档流的会挤压文档流中元素的文字(非浮动元素中间还是会占100%的宽度,左右骑在中间上面)

如何双飞翼布局

为了让主体(中央)内容第一时间渲染展示,布局时将主体内容块放最前面,比如

1
2
3
4
5
<div class="center">center
<div class="context">我是center里的内容</div>
</div>
<div class="left">left</div>
<div class="right">right</div>

实现要求:主间部分内容的宽度是要自适应的,左、右两边宽度分别为20%,20%

首先先让三列内容浮动起来

1
2
3
4
.center, .left, .right {
float: left
height: 200px
}

主体main的宽度要自适应,那么可以先设置为100%,这样main既是浮动元素,又有块级元素的特性

1
2
3
4
.main {
width: 100%;
background: antiquewhite;
}

接下来就是left和riht“双翼”的位置设置了
先将left居左,想要left居左,那么我们可以设置负边距: margin-left:-100%; 即:

1
2
3
4
5
.left {
background-color: aqua;
width: 200px;
margin-left: -100%;
}

说明:这里的100%为main的宽度,相当于是把left给左移了,刚好实现左边与center对齐。

对于right居右问题,也是类似可以设置负边距:margin-left:200px; 即:

1
2
3
4
5
.right {
background-color: aquamarine;
width: 200px;
margin-left: -200px;
}

说明:这里的200px为right自身的宽度,相当于是自己向左移了自身的一个宽度,刚好实现右边与center的对齐。

最后完善:
关键的一步,即center的位置该如何设置?目前,他的左边及右边部分元素是会被left/right挡住的

所以我们还必须在center里面多加一个div区块用来“装”具体的内容,在main内添加一个div(class=”context”),设置margin:0 200px;,把两边内容给挤开,这样完成了最主要的双飞翼布局。

也可以给main(三列的父元素)设置padding或margin,再用给left和right相对定位在center左右两侧,(圣杯布局)

关于CSS布局中圣杯布局与双飞翼布局的实现思路差异在哪里?

最后加入header和footer

由于双飞翼布局里的元素均为浮动,此时在文档流最后加入footer会使浮动元素覆盖掉footer,这时得设置一个块级元素包裹住双飞翼布局,避免浮动给文档流带来影响


完整代码如下:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.center, .left, .right {
float: left;
height: 200px;
}
.main {
height: 200px;
}
.center {
background-color: antiquewhite;
width: 100%;
}
.context {
margin: 0 200px;
}
.left {
background-color: aqua;
width: 200px;
margin-left: -100%;
}
.right {
background-color: aquamarine;
width: 200px;
margin-left: -200px;
}
.header, .footer {
background-color: gray;
}
.header {
height: 200px;
}
.footer {
height: 200px;
}
</style>
</head>
<body>
<div class="header">Header</div>
<div class="main">
<div class="center">
<div class="context">我是center里的内容</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<div class="footer">Footer</div>
</body>
</html>