左右定宽,中间自适应
先看效果图
利用float + margin
parent最小宽度不小于400px,不然子元素会换行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>float + margin</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
div {
height: 500px;
}
.parent {
position: relative;
}
.left {
float: left;
width: 200px;
background: green;
}
.right {
float: right;
width: 200px;
background: red;
}
.middle {
margin-left: 200px; /* 大于或等于左列宽度 */
margin-right: 200px; /* 大于或等于右列宽度 */
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="left">左列定宽</div>
<div class="right">右列定宽</div>
<div class="middle">中间自适应</div>
</div>
</body>
</html>
利用绝对定位
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>absolute + margin</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
div {
height: 500px;
}
.parent {
position: relative;
}
.left, .right {
position: absolute;
top: 0;
width: 200px;
}
.left {
left: 0;
background: green;
}
.right {
right: 0;
background: red;
}
.middle {
margin-left: 200px; /*或者parent设置 padding-left: 200px */
margin-right: 200px; /*或者parent设置 padding-right: 200px */
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="left">左列定宽</div>
<div class="middle">中间自适应</div>
<div class="right">右列定宽</div>
</div>
</body>
</html>
利用table实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>table</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
div {
height: 500px;
}
.parent {
display: table;
width: 100%;
table-layout: fixed;
}
.parent div {
display: table-cell;
}
.left, .right {
width: 200px;
}
.left {
background: green;
}
.right {
background: red;
}
.middle {
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="left">左列定宽</div>
<div class="middle">中间自适应</div>
<div class="right">右列定宽</div>
</div>
</body>
</html>
利用flex实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>flex</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
div {
height: 500px;
}
.parent {
display: flex;
width: 100%;
}
.left, .right {
width: 200px;
}
.left {
background: green;
}
.right {
background: red;
}
.middle {
flex: 1;
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="left">左列定宽</div>
<div class="middle">中间自适应</div>
<div class="right">右列定宽</div>
</div>
</body>
</html>
利用grid实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>grid</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
div {
height: 500px;
}
.parent {
display: grid;
width: 100%;
grid-template-columns: 200px auto 200px; /* auto 改为1fr也行*/
}
.left {
background: green;
}
.right {
background: red;
}
.middle {
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="left">左列定宽</div>
<div class="middle">中间自适应</div>
<div class="right">右列定宽</div>
</div>
</body>
</html>
圣杯布局
圣杯布局用到了浮动float、负边距、相对定位relative
html
<div class="parent">
<div class="middle">中间内容</div>
<div class="left">左侧区域</div>
<div class="right">右侧区域</div>
</div>
解析:
1. 先左右宽度分别为200px, 300px, 中间区域设置为100%撑满;
.parent {
height: 200px;
}
.middle {
width: 100px;
background:yellow;
}
.left {
width: 200px;
background: green;
}
.right {
width: 300px;
background: red;
}
2. 三列全部设置为全浮动;
.parent div {
height: 100%;
float: left;
}
3. left元素设置margin-left:100%;
跟middle同一水平线 让left回到上一行最左侧
可以看出左侧盖在了middle中间区域上
4. right元素设置margin-left: -300px;
跟middle同一水平线 让right回到上一行最右侧
5. 给parent设置padding,给两侧留坑
现在的问题就是左右两边的元素覆盖了middle元素的内容,我们可以给容器parent加上两边padding:
.parent {
padding: 0 300px 0 200px; /*把两边的坑留好*/
height: 200px;
}
6. 设置定位
在设置了padding后,左右元素都被挤了进来,我们可以设置position:relative解决,因为浮动元素已经脱离了文档流,所以不能设置absolute。 通过设置left和right元素的相对位置,实现定位:
.left {
width: 200px;
background: green;
margin-left: -100%; /* 跟middle同一水平线 让left回到上一行最左侧*/
position: relative; /* 定位 */
left: -200px; /*占左侧的坑*/
}
.right {
width: 300px;
background: red;
margin-left: -300px; /* 跟middle同一水平线 让right回到上一行最右侧*/
position: relative; /* 定位 */
right: -300px; /*占右侧的坑*/
}
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" middle="width=device-width, initial-scale=1.0" />
<title>圣杯布局</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
.parent {
padding: 0 300px 0 200px; /*把两边的坑留好*/
height: 500px;
}
.parent div {
height: 100%;
float: left;
}
.middle {
width: 100%;
background:yellow;
}
.left {
width: 200px;
background: green;
margin-left: -100%; /* 跟middle同一水平线 让left回到上一行最右侧*/
position: relative;
left: -200px; /*占左侧的坑*/
}
.right {
width: 300px;
background: red;
margin-left: -300px; /* 跟middle同一水平线 让right回到上一行最左侧*/
position: relative;
right: -300px; /*占右侧的坑*/
}
</style>
</head>
<body>
<div class="parent">
<div class="middle">中间内容</div>
<div class="left">左侧区域</div>
<div class="right">右侧区域</div>
</div>
</body>
</html>
双飞翼布局
双飞翼布局源于淘宝的UED,可以说是灵感来自于页面渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" middle="width=device-width, initial-scale=1.0" />
<title>双飞翼布局</title>
<style>
html, body, div {
padding: 0;
margin: 0;
}
.parent div {
height: 500px;
}
.middle {
float: left;
width: 100%;
}
.middle-content {
margin-left: 200px;
margin-right: 300px;
background:yellow;
}
.left {
width: 200px;
background: green;
float: left;
margin-left: -100%;
}
.right {
width: 300px;
background: red;
float: left;
margin-left: -300px;
}
</style>
</head>
<body>
<div class="parent">
<div class="middle">
<div class="middle-content">中间内容</div>
</div>
<div class="left">左侧区域</div>
<div class="right">右侧区域</div>
</div>
</body>
</html>
对比圣杯布局和双飞翼布局:
1. 都是左右栏定宽,中间栏自适应的三栏布局,中间栏都放到文档流前面,保证先行渲染
2. 解决方案基本相似:都是三栏全部设置左浮动float:left, 设置负margin解决中间栏内容被覆盖的问题
3. 解决中间栏内容被覆盖问题时,圣杯布局设置父元素的padding,双飞翼布局在中间栏嵌套一个div,内容放到新的div中,并设置margin,实际上,双飞翼布局就是圣杯布局的改进方案
欢迎查看其他布局系列文章