【CSS】CSS布局解决方案(终结版)

7,116 阅读10分钟

前言

在我们前端开发时,经常会遇到不同的场景页面布局问题,页面框架搭建是前端开发基础。本文先是对页面开发基本流程思路进行了总结,在此基础上对CSS布局常见方案进行梳理,涉及水平垂直居中、单列布局、两栏布局、圣杯布局、双飞翼布局等。

全文概要

image.png

1 页面开发流程布局思路

1.1 确定页面版心

常见的版心宽度:

  • 知乎 960px
  • 淘宝 1000px
  • 网易 1200px
  • 京东 1210px
  • 腾讯 1400

1.2 页面整体布局

  1. 先分析行模块再分析列模块。
  2. 如果一行当中有多个模块,一定要放在同一个父模块中。列模块一般都用浮动或者flex。具体坐标,有层叠概念的一般是通过定位方式实现。

1.3 单个模块布局

  1. 先给模块宽高(高度最终完成是要去除的)背景颜色,实例化这个盒子。
  2. 然后再分析模块的文本属性背景其他属性

CSS书写顺序:

  • 位置属性(position, top, right, z-index, display, float等)
  • 大小(width, height, padding, margin)
  • 文本(font, line-height, letter-spacing, color- text-align等)
  • 背景(background, border等)
  • 其他(animation, transition等)
  1. 一般模块是由标题内容两个部分组成。
  2. 如果盒子本身有宽高,使用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 普通布局

头部、内容、底部

普通布局.png

<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实现水平居中

内容居中.png

<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)和浮动元素不会产生交集,顺着浮动元素形成自己的封闭上下文。

image.png

<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

image.png

<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 什么是三栏布局

  • 左右固定,中间自适应
  • 中间栏放在文档流前面,保证优先加载

image.png

  • 实现方案有三种:flex布局、圣杯布局、双飞翼布局
  • 圣杯起源于a list part的一篇文章,双飞翼起源于淘宝UED,灵感来源于页面渲染。

5.2 flex布局

  • 将中间盒子放置html最开始,保证优先加载
  • 使用flex order属性决定三个盒子顺序,左,中,右
  • 左盒子和右盒子固定宽度,中间盒子flex:1

flex布局.png

<!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 圣杯布局

  • 三个盒子都设置浮动 image.png

  • 左盒子走负margin-left:100%,右盒子走负自身的宽度 image.png

  • 大盒子padding left和right左右盒子宽度 image.png

  • 左右盒子相对定位,left,right-往回走

image.png

<!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 双飞翼布局

  • 三个盒子都设置浮动 image.png
  • 左盒子走负margin-left:100%,右盒子走负自身的宽度 image.png
  • 调整中间盒子margin image.png
<!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 等高布局

等高布局是指子元素父元素中高度相等的布局方式。

image.png

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元素能够粘带在屏幕底部。

20210429160149788.jpg

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>

image.png

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:centerabsoute+translateX(-50%,0)
  • 垂直居中最推荐方法:align-items:centerabsolute+translateY(0,-50%)
  • 两栏布局、三栏布局、等高布局、粘带布局优先考虑使用flex。

结语

本篇文章就到此为止啦,由于本人经验水平有限,难免会有纰漏,对此欢迎指正。如觉得本文对你有帮助的话,欢迎点赞❤❤❤,写作不易,持续输出的背后是无数个日夜的积累,您的点赞是持续写作的动力,感谢支持!