题目要求:针对如下DOM结构,编写css,实现三栏水平布局,其中left、right分别位于左右两侧,left宽度为200px,right宽度为300px,main在中间,宽度自适应
要求:允许增加额外的DOM节点,但不能修改现有的节点顺序
<div class="container">
<div class="main">main</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
圣杯布局和双飞翼布局针对的都是三列布局,左右栏固定,中间自适应的网页布局。布局要求:
- 三列布局,中间宽度自适应,两边定宽
- 中间栏要在浏览器中优先展示渲染
- 允许任意列的高度最高
1. 圣杯布局
(1) 设置基本样式
.main{
background-color: blue;
}
.left{
width: 200px;
background-color: red;
}
.right{
width: 300px;
background-color: aqua;
}
如下所示:
(2) 设置container的padding,使之空出左右的空间, 效果如图:
.container{
padding: 0 300px 0 200px;
}
(3) 将main、left、right设置左浮动,并设置高度
.main, .left, .right{
float: left;
min-height: 100px
}
如果出现以下情况:
则需要设置main的宽度为100%
.main{
wdith: 100%;
}
将main撑开。如图所示:
(4)设置left和right的margin-left
明显圣杯布局left、main、right是依次并排的,但是目前的效果是left和right都在下一行,这里使用的技巧就是负的外边距,margin-left
.left{
margin-left: -100%
}
.right{
margin-left: -300px;
}
负的外边距让元素沿着文档流向左移动。如果数值比较大就会移动到上一行。
设置left部分的margin-left为-100%,就会使得left往左移动一个整行的宽度,一直移到上一行的开头,并且覆盖了main的部分。left上移之后,right就是处于当前行的开头位置。这个时候设置right部分的margin-left为负宽度,right就会移动到上一行的末尾。
(5)接下来只要使left和right分别挪到这两个位置就可以。可以使用相对定位移动
.left{
position: relative;
left: -200px;
}
.right{
position: relative;
right: -300px;
}
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>圣杯布局</title>
</head>
<style type="text/css">
.container{
height: 100px;
padding: 0 300px 0 200px;
}
.main, .left, .right{
float: left;
height: 100%;
}
.main{
width: 100%;
background-color: red;
}
.left{
width: 200px;
margin-left: -100%;
background-color: green;
position: relative;
left: -200px;
}
.right{
width: 300px;
background-color: blue;
margin-left: -300px;
position: relative;
right: -300px;
}
</style>
<body>
<div class="container">
<div class="main">main</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
2. 双飞翼布局
圣杯布局和双飞翼布局解决问题的方案前一部分是相同的,不同之处在于解决“中间栏div不背遮挡”的思路不一样。他的html结构发生了变化,添加了一个元素。
<div class="main">
<div class="content">main</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
解决的思路是content添加外边距。代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>双飞翼布局</title>
</head>
<style type="text/css">
.container{
height: 100px;
}
.main, .left, .right{
float: left;
height: 100%;
}
.main{
width: 100%;
background-color: red;
}
.left{
width: 200px;
margin-left: -100%;
background-color: green;
}
.right{
width: 300px;
background-color: blue;
margin-left: -300px;
}
.content{
margin: 0 300px 0 200px;
}
</style>
<body>
<div class="container">
<div class="main">
<div class="content">main</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
双飞翼布局比圣杯布局多使用了一个div但是少用了4个css属性,比圣杯布局更加直接简洁。双飞翼比圣杯布局多创建一个div,但是不用相对布局
3. Flex布局
任何一个容器都可以指定为Flex布局,flex布局将成为未来布局的首选方案
(1) 首先将container设置成一个flex容器
.container{
display: flex;
min-height: 100px;
}
那么container里面的三个子元素自动成为容器成员,即成为flex项目,简称为项目
(2) 对这三个项目的初始设置(颜色等)
(3) 通过order进行布局
由于元素的顺序不能更改,从上图可知三个项目的排序不一样了。为了使left排在第一个我们可以通过设置flex容器下的order属性来更改顺序。
.left{
order: -1;
}
对order属性来说,越小排序越靠前,默认为0。
(4) 设置main的flex-grow属性,撑满剩余空间
.main{
flex-grow: 1
}
(5) 用flex-basic设置left和right的宽度
.left{
flex-basic: 200px;
}
.right{
flex-basic: 300px;
}
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flex</title>
</head>
<style type="text/css">
.container{
display: flex;
}
.main{
background-color: blue;
flex-grow: 1;
}
.main, .left, .right{
min-height: 100px;
}
.left{
flex-basis: 200px;
order: -1;
background-color: red;
}
.right{
flex-basis: 300px;
background-color: aqua;
}
</style>
<body>
<div class="container">
<div class="main">main</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>
4. 绝对定位布局
绝对定位布局和相对定位布局不同。绝对定位元素会脱离文档流,不占据空间。相对定位元素实际上被当作是普通文档流的一部分,因为它是根据自身在普通文档流的位置进行定位的。
因为绝对定位的元素脱离的文档流,所以可以覆盖页面上的其他元素。并且通过设置z-index来控制他们的堆叠顺序。
可以通过position: absolution+margin来实现三栏布局。
具体代码实现如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绝对定位实现三栏布局</title>
</head>
<style type="text/css">
.container{
position: relative;
}
.left, .main, .right{
min-height: 100px;
}
.left{
position: absolute;
left: 0;
width: 200px;
top: 0;
background-color: red;
}
.right{
position: absolute;
right: 0;
top: 0;
width: 300px;
background-color: aqua;
}
.main{
margin: 0 300px 0 200px;
background-color: blue;
}
</style>
<body>
<div class="container">
<div class="main">main</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>