题目要求:针对如下DOM结构,编写CSS,实现三栏水平布局,其中left、right分别位于左右两侧,left宽度为200px,right宽度为300px,main处在中间,宽度自适应。
要求:允许增加额外的DOM节点,但不能修改现有节点顺序。
1 | <div class="container"> |
2 | <div class="main">main</div> |
3 | <div class="left">left</div> |
4 | <div class="right">right</div> |
5 | </div> |
圣杯布局
设置基本样式
css1
.left {
2
background: green;
3
width: 200px;
4
}
5
.main {
6
background: blue;
7
}
8
.right {
9
background: red;
10
width: 300px;
11
}
圣杯布局是一种相对布局,首先设置父元素container的位置:
css1
.container {
2
padding: 0 300px 0 200px;
3
}
实现效果是左右分别空出200px和300px区域
将主体部分的三个子元素都设置左浮动
css1
.left,.main,.right {
2
float: left;
3
}
设置main宽度为width:100%,让其单独占满一行
css1
.main {
2
background: blue;
3
width: 100%;
4
}
设置left和right 负的外边距
我们的目标是让left、main、right依次并排,但是上图中left和right都是位于下一行,这里的技巧就是使用负的margin-left:
css1
.left {
2
margin-left: -100%;
3
background: green;
4
width: 200px;
5
}
6
7
.right {
8
margin-right: -300px;
9
background: red;
10
width: 300px;
11
}
负的margin-left会让元素沿文档流向左移动,如果负的数值比较大就会一直移动到上一行。关于负的margin的应用也是博大精深,这里肯定是不能详细介绍了。
设置left部分的margin-left为-100%,就会使left向左移动一整个行的宽度,由于left左边是父元素的边框,所以left继续跳到上一行左移,一直移动到上一行的开头,并覆盖了main部分(仔细观察,你会发现main里面的字“main”不见了,因为被left遮住了),left上移过后,right就会处于上一行的开头位置,这时再设置right部分margin-left为负的宽度,right就会左移到上一行的末尾。
接下来只要把left和right分别移动到这两个留白就可以了。可以使用相对定位移动 left和right部分。
css1
.left,.main,.right {
2
postion: relative;
3
float: left;
4
}
5
.left {
6
left: -200px;
7
margin-left: -100%;
8
background: green;
9
width: 200px;
10
}
11
12
.right {
13
right: -300px;
14
margin-right: -300px;
15
background: red;
16
width: 300px;
17
}
至此,我们完成了三列中间自适应的布局,也就是传说中的圣杯布局。完整的代码如下:
1 |
|
2 | <html lang="en"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
6 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> |
7 | <title>Document</title> |
8 | <style> |
9 | .container { |
10 | padding: 0 300px 0 200px; |
11 | } |
12 | .left,.main,.right { |
13 | postion: relative; |
14 | float: left; |
15 | } |
16 | .left { |
17 | left: -200px; |
18 | margin-left: -100%; |
19 | background: green; |
20 | width: 200px; |
21 | } |
22 | .main { |
23 | background: blue; |
24 | width: 100%; |
25 | } |
26 | .right { |
27 | right: -300px; |
28 | margin-right: -300px; |
29 | background: red; |
30 | width: 300px; |
31 | } |
32 | </style> |
33 | </head> |
34 | <body> |
35 | <div class="container"> |
36 | <div class="main">main</div> |
37 | <div class="left">left</div> |
38 | <div class="right">right</div> |
39 | </div> |
40 | </body> |
41 | </html> |
双飞燕布局
圣杯布局和双飞翼布局解决问题的方案在前一半是相同的,也就是三栏全部float浮动,但左右两栏加上负margin让其跟中间栏div并排,以形成三栏布局。不同在于解决 “中间栏div内容不被遮挡”问题的思路不一样。
他的HTML结构发生了变化:
1 | <div class="container"> |
2 | <div class="main"> |
3 | <div class="content"> |
4 | main |
5 | </div> |
6 | </div> |
7 | <div class="left">left</div> |
8 | <div class="right">right</div> |
9 | </div> |
完整代码如下:
1 |
|
2 | <html lang="en"> |
3 | |
4 | <head> |
5 | <meta charset="UTF-8"> |
6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
7 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> |
8 | <title>Document</title> |
9 | <style> |
10 | .left,.main,.right { |
11 | float: left; |
12 | text-align: center; |
13 | } |
14 | .left { |
15 | margin-left: -100%; |
16 | background: green; |
17 | width: 200px; |
18 | } |
19 | .main { |
20 | background: blue; |
21 | width: 100%; |
22 | } |
23 | .right { |
24 | margin-left: -300px; |
25 | background: red; |
26 | width: 300px; |
27 | } |
28 | .content { |
29 | margin: 0 300px 0 200px; |
30 | } |
31 | </style> |
32 | </head> |
33 | <body> |
34 | <div class="container"> |
35 | <div class="main"> |
36 | <div class="content"> |
37 | main |
38 | </div> |
39 | </div> |
40 | <div class="left">left</div> |
41 | <div class="right">right</div> |
42 | </div> |
43 | </body> |
44 | </html> |
双飞翼布局比圣杯布局多使用了1个div,少用大致4个css属性(圣杯布局container的 padding-left和padding-right这2个属性,加上左右两个div用相对布局position: relative及对应的right和left共4个属性,;而双飞翼布局子div里用margin-left和margin-right共2个属性,比圣杯布局思路更直接和简洁一点。简单说起来就是:双飞翼布局比圣杯布局多创建了一个div,但不用相对布局了。
flex布局
首先将container块设置为一个Flex容器
css1
.container {
2
display:flex;
3
}
那么container下属的main、left和right这三个子元素自动成为容器成员,称为 Flex 项目(flex item),简称”项目”。
对这三个项目做初始设置
css1
.left {
2
background: green;
3
}
4
.main {
5
background: blue;
6
}
7
.right {
8
background: red;
9
}
通过order属性设置排列顺序
可以看出三个项目的排序方式不一样了,main排在了第一个,要让main在中间,left在左边,可以通过Flex容器下的项目的属性“order”属性来设置:
css1
.left {
2
order: -1;
3
background: green;
4
}
对于order属性:定义项目的排列顺序,越小越靠前,默认为0。
通过项目属性flex-grow设置main的放大比例,将空余的空间用main来填充,使三个项目不满一整行;默认为0,也就是对剩余空间不做处理。
css1
.main {
2
flex-grow: 1;
3
background: blue;
4
}
通过项目属性flex-basis 设置left和right的固定宽度
css1
.left {
2
order: -1;
3
flex-basis: 200px;
4
background: green;
5
}
6
.right {
7
flex-basis: 300px;
8
background: red;
9
}
完整的代码如下:
1 |
|
2 | <html lang="en"> |
3 | <head> |
4 | <meta charset="UTF-8"> |
5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
6 | <meta http-equiv="X-UA-Compatible" content="ie=edge"> |
7 | <title>Document</title> |
8 | <style> |
9 | .container { |
10 | display:flex; |
11 | } |
12 | .main { |
13 | flex-grow: 1; |
14 | background: blue; |
15 | } |
16 | .left { |
17 | order: -1; |
18 | flex-basis: 200px; |
19 | background: green; |
20 | } |
21 | .right { |
22 | flex-basis: 300px; |
23 | background: red; |
24 | } |
25 | </style> |
26 | </head> |
27 | <body> |
28 | <div class="container"> |
29 | <div class="main">main</div> |
30 | <div class="left">left</div> |
31 | <div class="right">right</div> |
32 | </div> |
33 | </body> |
34 | </html> |
绝对定位布局
绝对定位使元素的位置与文档流无关,因此不占据空间。这一点与相对定位不同,相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。
提示:因为绝对定位的框与文档流无关,所以它们可以覆盖页面上的其它元素。可以通过设置 z-index 属性来控制这些框的堆放次序。
言归正传:
绝对定位,就相当于万金油一样的存在,不论什么样的布局,使用绝对定位都能实现,所以对于具体的实现过程就不赘述
引用:https://blog.csdn.net/wangchengiii/article/details/77926868