前言
在我们前端开发时,经常会遇到不同的场景页面布局问题,页面框架搭建是前端开发基础。本文先是对页面开发基本流程思路进行了总结,在此基础上对CSS布局常见方案进行梳理,涉及水平垂直居中、单列布局、两栏布局、圣杯布局、双飞翼布局等。
全文概要
1 页面开发流程布局思路
1.1 确定页面版心
常见的版心宽度:
- 知乎 960px
- 淘宝 1000px
- 网易 1200px
- 京东 1210px
- 腾讯 1400
1.2 页面整体布局
- 先分析行模块再分析列模块。
- 如果一行当中有多个模块,一定要放在同一个父模块中。列模块一般都用浮动或者
flex
。具体坐标,有层叠概念的一般是通过定位方式实现。
1.3 单个模块布局
- 先给模块宽高(高度最终完成是要去除的)背景颜色,实例化这个盒子。
- 然后再分析模块的文本属性,背景其他属性。
CSS书写顺序:
- 位置属性(position, top, right, z-index, display, float等)
- 大小(width, height, padding, margin)
- 文本(font, line-height, letter-spacing, color- text-align等)
- 背景(background, border等)
- 其他(animation, transition等)
- 一般模块是由标题和内容两个部分组成。
- 如果盒子本身有宽高,使用
padding
需要进行计算,使用margin
有时会导致外边距合并塌陷问题。
2 水平垂直居中布局
行内元素水平垂直居中常用方法有两种:
- 水平居中:
text-align: center
- 垂直居中:
height=line-height
(适合纯文字类)
块级元素居中分为:
- 居中元素宽高固定
- 居中元素宽高不固定
2.1 固定宽高
公共代码
<head>
<meta charset="utf-8">
<title>公共代码</title>
<style>
.father{
width: 500px;
height: 300px;
border: 1px solid red;
}
.son{
width: 100px;
height: 100px;
background-color:red;
}
</style>
</head>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
(1) absolute + 负margin
- 子元素绝对定位,父元素相对定位
- 子元素先基于父元素移动50%,再利用
-margin
往回移动自身的一半
.father {
position: relative;
}
.son {
position: absolute;
/*水平居中*/
left: 50%;
margin-left: -50%;
/*垂直居中*/
top: 50%;
margin-top: -50%;
}
(2) absolute + margin auto
- 子元素绝对定位,父元素相对定位
- 子元素各个方向距离设为0,再将
margin
设为auto
.father {
position: relative;
}
.son {
position: absolute;
margin: auto;
/*水平居中*/
left: 0;
right: 0;
/*垂直居中*/
top: 0;
bottom: 0;
}
为什么设置auto
可以实现元素的水平垂直居中呢?这和auto
属性有关,auto
的取值有以下两种情况:
- 当元素布局为
static/relative
且宽度已知时,auto
为父元素剩余宽度。 - 当元素布局为
postion/absolute/fixed/float/inline
或者宽高未知时,auto
为0。 需要注意的是,当auto
取值均为水平方向,垂直方向上,auto
不会自动填充。
那我们如何利用auto
实现元素的水平垂直居中呢?
答案是利用元素的流行特征——当一个绝对定位元素,其四个定位方向同时设置具体数值时,流行特征就会发生。
流行特征好处在于,元素可自动填充父级元素的可用尺寸。
我们通过给元素设置left、right、top、bottom
的值,然后将水平/垂直方向的 margin
均设为 auto
,这样一来,auto
就会自动平分父元素的剩余空间了
2.2 不固定宽高
然而并不是所有的场景都已知子元素的宽高,在宽高不定的情况下,我们可以使用以下方法实现垂直居中:
(1) absolute + transform
- 子元素绝对定位,父元素相对定位
- 利用
transform
往回移动自身的一半
.father{
position: relative;
}
.son{
position: absolute;
/*水平居中*/
left: 50%;
transform: translate(-50%,0);
/*垂直居中*/
top: 50%;
transform: translate(0,-50%);
}
transform
是css3中新增的属性,它可以对元素进行旋转、缩放、移动和倾斜,这里我们用到的translate
,就是对元素进行移动。
translate
接受两个参数,分别对应元素沿 X 轴的移动量和沿 Y 轴的移动量。
(2) flex
- 水平居中:父元素display: flex+justify-content: center
- 垂直居中:父元素display: flex+align-items: center
.father {
display: flex;
/*水平居中*/
justify-content: center;
/*垂直居中*/
align-items: center;
}
(3) table布局
水平居中:
- 父元素:
text-align:center
- 子元素:
display:block
.father{
text-align: center;
}
.son {
display: inline-block;
}
垂直居中:
- 父元素:
display:table-cell
- 父元素:
vertical-align: middle
.father{
display: table-cell;
vertical-align: middle;
}
table
布局属于历史悠久的布局啦,由于兼容性不错,实际开发中也有会用到。
3 单列布局
3.1 普通布局
头部、内容、底部
<head>
<meta charset="utf-8">
<title>单列布局-普通布局</title>
<style>
.header{
margin:0 auto;
max-width: 960px;
height:100px;
background-color:pink;
}
.container{
margin: 0 auto;
max-width: 960px;
height: 500px;
background-color: aquamarine;
}
.footer{
margin: 0 auto;
max-width: 960px;
height: 100px;
background-color:skyblue;
}
</style>
</head>
<body>
<div class="header"></div>
<div class="content"></div>
<div class="footer"></div>
</body>
3.2 内容居中
内容区域(版心)为960px,采用margin:0 auto实现水平居中
<head>
<meta charset="utf-8">
<title>普通布局-内容居中</title>
<style>
.header{
margin:0 auto;
height:100px;
background-color:pink;
}
.content{
margin: 0 auto;
height: 500px;
width:960px;
background-color: aquamarine;
}
.footer{
margin: 0 auto;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="header"></div>
<div class="center">
<div class="content"></div>
</div>
<div class="footer"></div>
</body>
4 两栏布局
所谓两栏布局是指:左侧定宽,右侧自适应。
4.1 float
实现思路:
普通流体BFC后(float:left)和浮动元素不会产生交集,顺着浮动元素形成自己的封闭上下文。
<head>
<meta charset="utf-8">
<title>两栏布局-float</title>
<style>
.left {
width: 300px;
background-color: pink;
float: left;
height:500px;
}
.right {
width:100%;
background-color: aquamarine;
height:500px;
}
</style>
</head>
<body>
<div class="warp">
<div class="left">定宽</div>
<div class="right">自适应</div>
</div>
</body>
4.2 flex
实现思路:
父元素开启弹性空间,左盒子设置固定宽度,右盒子flex:1
<head>
<meta charset="utf-8">
<title>两栏布局-flex</title>
<style>
.warp{
display:flex;
}
.left {
width: 300px;
background-color: pink;
height:500px;
}
.right {
background-color: aquamarine;
height:500px;
flex:1
}
</style>
</head>
<body>
<div class="warp">
<div class="left">定宽</div>
<div class="right">自适应</div>
</div>
</body>
5 三栏布局
5.1 什么是三栏布局
- 左右固定,中间自适应
- 中间栏放在文档流前面,保证优先加载。
- 实现方案有三种:flex布局、圣杯布局、双飞翼布局
- 圣杯起源于a list part的一篇文章,双飞翼起源于淘宝UED,灵感来源于页面渲染。
5.2 flex布局
- 将中间盒子放置html最开始,保证优先加载
- 使用flex order属性决定三个盒子顺序,左,中,右
- 左盒子和右盒子固定宽度,中间盒子flex:1
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>flex布局</title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
min-width: 800px;
height: 600px;
background: gray;
display: flex;
}
.left{
width:200px;
height: 600px;
background: pink;
order:-1
}
.center{
height: 600px;
background: aquamarine;
width:100%;
flex:1
order:1
}
.right{
width:200px;
height: 600px;
background: skyblue;
order:2
}
</style>
</head>
<body>
<div class="box">
<div class="center">中哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈中</div>
<div class="left">左</div>
<div class="right">右</div>
</div>
</body>
</html>
5.3 圣杯布局
-
三个盒子都设置浮动
-
左盒子走负margin-left:100%,右盒子走负自身的宽度
-
大盒子padding left和right左右盒子宽度
-
左右盒子相对定位,left,right-往回走
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>圣杯布局</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.box{
min-width: 800px;
height: 600px;
/* 4、padding左右盒子的宽度 */
padding-left:200px;
padding-right:200px;
}
.left{
/* 1、三个盒子都设置浮动 */
float:left;
width:200px;
height: 600px;
/* 2、走中间盒子的-100% */
margin-left:-100%;
background: pink;
/* 5 相对定位,往回走 */
position:relative;
left:-200px;
}
.center{
float:left;
width: 100%;
height: 600px;
background: aquamarine;
}
.right{
float:left;
width:200px;
height: 600px;
/*/3、走负自身的宽度 */
margin-left:-200px;
background: skyblue;
/* 6 相对定位,往回走 */
position:relative;
right:-200px;
}
</style>
</head>
<body>
<div class="box">
<div class="center">中哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈中</div>
<div class="left">左</div>
<div class="right">右</div>
</body>
</html>
5.4 双飞翼布局
- 三个盒子都设置浮动
- 左盒子走负margin-left:100%,右盒子走负自身的宽度
- 调整中间盒子margin
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>双飞翼布局</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.box{
min-width: 800px;
height: 600px;
}
.left{
/* 1、三个盒子都设置浮动 */
float:left;
width:200px;
height: 600px;
/* 2、走中间盒子的-100% */
margin-left:-100%;
background: pink;
}
.content{
/* 4、调整中间盒子margin */
margin-left:200px;
margin-right:200px;
background-color: yellowgreen;
}
.center{
float:left;
width: 100%;
height: 600px;
background: aquamarine;
}
.right{
float:left;
width:200px;
height: 600px;
/*3、走负自身的宽度 */
margin-left:-200px;
background: skyblue;
}
</style>
</head>
<body>
<div class="box">
<div class="center">
<div class="content">
中哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈中
</div>
</div>
<div class="left">左</div>
<div class="right">右</div>
</body>
</html>
圣杯布局双飞翼布局总结:
- 三栏全部float:left,中间栏div内容不被遮盖
- 圣杯是中间添加相对定位,并配合left和right属性
- 双飞翼是中间栏的div在嵌套一个div,对嵌套的div设置margin-left和margin-right
6 等高布局
等高布局是指子元素在父元素中高度相等的布局方式。
6.1 正值内边距+负值外边距
正值内边距+负值外边距,padding和margin相互抵消的效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>等高布局-正值内边距+负值外边距</title>
<style type="text/css">
*{
margin:0;
padding:0;
}
.left,
.right {
width:50%;
float:left;
text-align:center;
background-color:aquamarine;
/* 设置正值内边距会把背景颜色拉伸 */
padding-bottom:9999px;
/* 设置负值外边距把边框往里推 */
margin-bottom:-9999px;
}
.right{
background-color: pink;
}
.container {
width:1200px;
margin:0 auto;
/* 开启BFC限制内容 */
overflow:hidden;
}
</style>
</head>
<body>
<div class="container">
<div class="left">111111111111</div>
<div class="right">
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
</div>
</div>
</body>
</html>
6.2 table布局
弊端:使用table布局对一些属性设置有一定限制
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>等高布局-table布局</title>
<style type="text/css">
*{
margin:0;
padding:0;
}
.center,
.left,
.right {
width:33.3%;
text-align:center;
display: table-cell;
background-color:aquamarine;
}
.container {
display:table;
width:1200px;
margin:0 auto;
}
</style>
</head>
<body>
<div class="container">
<div class="left">111111111111</div>
<div class="center">22222222222222222222222222</div>
<div class="right">
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
</div>
</div>
</body>
</html>
6.3 flex布局
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>等高布局-flex布局</title>
<style type="text/css">
*{
margin:0;
padding:0;
}
.center,
.left,
.right {
text-align:center;
background-color:aquamarine;
flex:1
}
.container {
display:flex;
/* flex-direction: row; */
width:1200px;
margin:0 auto;
}
</style>
</head>
<body>
<div class="container">
<div class="left">111111111111</div>
<div class="center">22222222222222222222222222</div>
<div class="right">
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
</div>
</div>
</body>
</html>
6.4 grid布局
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>grid布局</title>
<style>
*{
margin:0;
padding:0;
}
.center,
.left,
.right {
text-align:center;
background-color:aquamarine;
flex:1
}
.container {
display:grid;
grid-auto-flow: column;
width:1200px;
margin:0 auto;
}
</style>
</head>
<body>
<div class="container">
<div class="left">111111111111</div>
<div class="center">22222222222222222222222222</div>
<div class="right">
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333
</div>
</div>
</body>
</html>
7 粘带布局
当main的高度足够长的时候,footer会跟在其后面。 当main元素比较短的时候(比如小于屏幕宽度),footer元素能够粘带在屏幕底部。
7.1 负margin-bottom
实现思路: 用一个元素将footer以外的内容包起来,设置负的margin-bottom,他正好等于footer的高度。
<html>
<head>
<meta charset="UTF-8">
<title>粘带布局-负margin-bottom</title>
<style>
/* 用一个元素将footer以外的内容包起来,设置负的margin-bottom,让他正好等于footer的高度 */
html, body {
margin: 0;
padding:0;
text-align:center;
}
#wrap{
min-height:100%;
background-color: pink;
margin-bottom: -30px;
}
#footer,#main{
height: 30px;
}
#footer{
background-color: aquamarine;
}
</style>
</head>
<body>
<div id="wrap">
<div id="main">
main<br/>
main<br/>
</div>
</div>
<div id="footer">footer</div>
</body>
</html>
7.2 footer 上用负的 margin-top
<html>
<head>
<meta charset="UTF-8">
<title>粘带布局-footer 上用负的 margin-top</title>
<style>
html, body {
height: 100%;
margin: 0;
text-align:center;
}
#wrap{
width: 100%;
min-height:100%;
background-color: pink;
}
/*内容区需要让出一部分区域,防止内容被盖住*/
#main{
padding-bottom: 30px;
}
/*wrap包裹内容的最小高度是100%,此时将footer的部分通过margin-top拉上去30px。 */
#footer{
width: 100%;
height: 30px;
background-color: aquamarine;
margin-top: -30px;
}
</style>
</head>
<body>
<div id="wrap">
<div id="main">
<p>main</p>
<p>main</p>
</div>
</div>
<div id="footer">footer</div>
</body>
</html>
7.3 flex
<html>
<head>
<meta charset="UTF-8">
<title>粘带布局-flex</title>
<style>
html, body {
margin: 0;
padding:0;
text-align:center;
}
#wrap{
height:100%;
display: flex;
flex-direction: column;
}
#main{
background-color: pink;
flex:1;
}
#footer{
background-color: aquamarine;
height: 30px;
}
</style>
</head>
<body>
<div id="wrap">
<div id="main">
<p>main</p>
<p>main</p>
</div>
<div id="footer">footer</div>
</div>
</body>
</html>
8 总结
- 网页开发基本思路:确定版心--》分析行模块--》分析列模块。
- 如果一行当中有多个模块,一定要放在同一个父模块中。
- 列模块首先可以先给宽高背景颜色,实例化盒子。
- 水平居中推荐使用方法:
justify-content:center
、absoute+translateX(-50%,0)
。 - 垂直居中最推荐方法:
align-items:center
、absolute+translateY(0,-50%)
。 - 两栏布局、三栏布局、等高布局、粘带布局优先考虑使用flex。
结语
本篇文章就到此为止啦,由于本人经验水平有限,难免会有纰漏,对此欢迎指正。如觉得本文对你有帮助的话,欢迎点赞❤❤❤,写作不易,持续输出的背后是无数个日夜的积累,您的点赞是持续写作的动力,感谢支持!