css布局

1,627 阅读40分钟

CSS布局

CSS布局在前端中占有举足轻重的地位,本篇文章会重点总结目前常用的CSS布局实现方式,例如两栏布局,三栏布局,圣杯布局等。

两栏布局

常见的两栏布局方式是一侧定宽,另一侧自适应宽度,例如左侧栏定宽,右侧自适应宽度,或者右侧栏定宽,左侧自适应宽度。

实际效果如下图所示。

​ 图1 左侧定宽,右侧自适应

实现两栏布局可以使用多种方式,这里会总结出5种方法以供学习。

方法1:float+margin

方法1的主要思想是通过给固定宽度侧使用float属性,自适应侧通过设置margin属性值控制其宽度。

通过以下的代码段可以更好的理解实现过程。

HTML代码

HTML部分代码相对简单,只需要设置一个外层容器,然后包含两个子容器,代码如下所示。

<div class="container">
    <div class="left">左侧定宽区域</div>
    <div class="right">右侧自适应宽度区域</div>
</div>

CSS代码

为了效果的呈现,将所有div的高度都设置一个值,这是下面方法2,方法3中通用的代码,如下所示。

div {
	height: 800px;
}

左侧固定宽度的div设置width和float属性,同样为了效果呈现,设置一个特定的背景色。

.left {
    width: 200px;
    float: left;
    background-color: #0ac2d2;
}

右侧自定义宽度的div设置margin-left属性,其值与左侧div的width属性相等即可。

.right {
    margin-left: 200px;
    background-color: #1b6d85;
}

将上述的HTML和CSS代码合并在一个HTML文件中运行后就可以得到图1的效果。

方法2:双浮动+calc

方法2的主要思想是通过设置左右两个div同时浮动实现,左侧div设置宽度,右侧的div通过calc方法动态计算出宽度值。

HTML代码

HTML部分代码相对简单,只需要设置一个外层容器,然后包含两个子容器,代码如下所示。

<div class="container">
    <div class="left">左侧定宽区域</div>
    <div class="right">右侧自适应宽度区域</div>
</div>

CSS代码

左侧定宽div的CSS属性同方法1一样。

.left {
    width: 200px;
    float: left;
    background-color: #0ac2d2;
}

右侧自适应div也会设置float属性,width属性则通过calc方法,将宽度最大值(100%)减去左侧定宽区占据的值。

.right {
    width: calc(100% - 200px);
    float: left;
    background-color: #1b6d85;
}

上述的代码在运行后同样可以得到图1的效果。

方法3:绝对定位

方法3的主要思想是通过给左侧定宽的div设置为绝对定位,使其脱离文档流,然后设置为宽度值,右侧的自定义宽度div只需要设置margin-left值左侧定宽div的宽度值即可。

HTML代码

HTML部分代码相对简单,只需要设置一个外层容器,然后包含两个子容器,代码如下所示。

<div class="container">
    <div class="left">左侧定宽区域</div>
    <div class="right">右侧自适应宽度区域</div>
</div>

CSS代码

左侧定宽的div通过设置position属性为absolute产生绝对定位。

.left {
    position: absolute;
    width: 200px;
    background-color: #0ac2d2;
}

右侧的div设置margin-left为左侧div的width值即可。

.right {
    margin-left: 200px;
    background-color: #1b6d85;
}

上述的代码在运行后同样可以得到图1的效果。

方法4:inline-block+calc()

方法4的主要思想是设置左右两个div的display属性为inline-block,使其处于一行显示。然后给左侧div设置固定的宽度值,右侧div通过calc方法动态计算宽度值。

HTML代码

HTML部分代码相对简单,只需要设置一个外层容器,然后包含两个子容器,代码如下所示。

<div class="container">
    <div class="left">左侧定宽区域</div>
    <div class="right">右侧自适应宽度区域</div>
</div>

CSS代码

左侧定宽的div只需要设置display: inline-block和width属性即可。

.left {
    display: inline-block;
    width: 200px;
    background-color: #0ac2d2;
}

右侧自适应的div同样设置display: inline-block,然后通过calc方法动态计算宽度值。

.right {
    display: inline-block;
    width: calc(100% - 200px);
    background-color: #1b6d85;
}

运行上述的代码后会发现,并未得到我们想要的结果,右侧自适应宽度的div在第二行显示。

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/8/30/1658a4d4fa8af53c~tplv-t2oaga2asx-image.image

在这种情况下,可以猜想的到是因为通过calc计算出的宽度大于上层右侧剩余的宽度值,所以右侧div被挤到下面,占据新的一行。

因此我们调节calc中计算的值,将其减去的值调整为206px,右侧的div会正常显示。

.right {
    display: inline-block;
    width: calc(100% - 206px);
    background-color: #1b6d85;
}

得到的效果图如下所示。

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/8/30/1658a4d4f9c03c9b~tplv-t2oaga2asx-image.image

但是从图片中可以看出左右两侧div之间出现一个小的间隙,其实这就是造成了图2中两个div并未同行展示的原因。

inline-block存在的问题

上述左右两侧div之间出现间隙主要是设置display: inline-block产生的,在不同浏览器下inline-block的元素之间产生的间隙是不一样的。上述测试的例子是在chrome浏览器下运行,其产生的间隙为6px,所以在左侧宽度设置为200px时,右侧div的calc方法中需要减去206px才能够满足条件。

那么产生这种情况的原因是什么呢?

主要是由于换行符引起的,因为在开发过程中,我们通常会标签的结束符后习惯性的使用回车换行,回车符就相当于空白符,通常情况下多个连续的空白符会合并为一个空白符,从而产生了几像素的间隙。

既然出现了这个问题,那么有什么好的解决方法呢?

在这里提供一种比较方便的解决方法,设置inline-block元素的父元素的font-size属性为0,在父元素的font-size属性设置为0后,空白符占据的空间就会变成0,从而消除间隙。如果在子元素中需要展示文本内容,需要手动设置子元素的font-size属性。

外层父元素的CSS属性如下所示。

.container {
	font-size: 0;
}

左侧定宽div需要设置font-size属性。

.left {
    display: inline-block;
    width: 200px;
    font-size: 16px;
    background-color: #0ac2d2;
}

右侧自适应宽度的div可以将calc方法中减去的数值还原为左侧定宽div的width值,另外同样需要设置font-size属性值。

.right {
    display: inline-block;
    font-size: 16px;
    width: calc(100% - 200px);
    background-color: #1b6d85;
}

方法5:flex布局

方法5的主要思想是通过CSS3的新特性flex进行布局。flex又称为弹性布局,类似于calc方法,会通过设置flex-grow和flex-shrink等值,根据父元素的宽度来动态计算每个子元素占据的宽度值。

HTML代码

HTML部分代码相对简单,只需要设置一个外层容器,然后包含两个子容器,代码如下所示。

<div class="container">
    <div class="left">左侧定宽区域</div>
    <div class="right">右侧自适应宽度区域</div>
</div>

CSS代码

使用flex布局时,需要设置父元素的display属性为flex。

.container {
    display: flex;
}

左侧定宽的div只需要设置一个初始宽度值,不会在接下来的收缩或者伸展空间时占据其他额外的宽度,所以flex-grow和flex-shrink值都设置为0。

.left {
    flex: 0 0 200px;
    background-color: #0ac2d2;
}

右侧自适应宽度的div需要占据全部的剩余空间,不管是收缩或者伸展空间时都需要占据100%的宽度值,所以flex-grow和flex-shrink值都设置为1。

.right {
    flex: 1;
    background-color: #1b6d85;
}

运行上述的代码后同样可以达到图1的效果。

flex在移动端布局中起到了至关重要的作用,也是大家最需要掌握的一种方式。

方法6:display: table布局

方法6的主要思想是借助于table布局,将外层容器的display属性设置为table,对左右两个子元素按照表格列展示。当设置父容器的宽度时,只需要固定左侧单元格的宽度,右侧单元格会自动填充剩余空间,从而达到自适应的效果。

HTML代码

HTML部分代码相对简单,只需要设置一个外层容器,然后包含两个子容器,代码如下所示。

<div class="container">
    <div class="left">左侧定宽区域</div>
    <div class="right">右侧自适应宽度区域</div>
</div>

CSS代码

容器设置

外层容器需要设置其display属性为table,而且给其定一个高度值,宽度值让其占满整个页面。

.container {
    display: table;
    height: 600px;
    width: 100%;
}
左右两栏元素设置

对于左右两侧div需要充当表格列的角色,故需要设置它们的display属性为tabel-cell。左侧div是需要定宽的,只需要设置其width为固定值即可,右侧div会自动占满容器的剩余空间。

.container div {
    display: table-cell;
}

.left {
    width: 200px;
    background-color: #0ac2d2;
}

.right {
    background-color: #1b6d85;
}

运行上述的代码后同样可以达到图1的效果。

三栏布局

三栏布局类似于两栏布局,它的具体表现形式为,左侧和右侧两栏定宽,中间区域自适应宽度。

效果图如下所示。

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/8/30/1658a4d614e4b8f9~tplv-t2oaga2asx-image.image

同样我们整理出几种实现方法。

方法1: 左右两侧float+中间区margin

方法1的主要思想是设置左侧定宽区为左浮动,右侧定宽区为右浮动,中间自适应区域通过margin调整其占据的宽度。

HTML代码

因为在同一行中使用了float为left和right两个元素,同时会出现非浮动的元素,所以在HTML元素书写上并不能按照结果的展示顺序。

浮动的元素应该出现在非浮动元素之前,代码如下所示。

<div class="container">
    <div class="left">左侧宽度固定区域</div>
    <div class="right">右侧宽度固定区域</div>
    <div class="middle">中间自适应宽度区域</div>
</div>

CSS代码

首先给父元素设置基本的color和height属性,子元素占据父元素的高度。

.container {
    height: 800px;
    color: #fff;
}

.container div {
    height: 100%;
}

左侧定宽div设置float为left,设置width值。

.left {
    width: 200px;
    float: left;
    background-color: #0ac2d2;
}

右侧定宽div设置float为right,设置width值。

.right {
    width: 200px;
    float: right;
    background-color: #9C27B0;
}

中间自适应div设置margin属性,margin-left和margin-right为左右两侧定宽div的width值。

.middle {
    margin: 0 200px 0 200px;
    background-color: #2b542c;
}

运行上述代码后,即可得到图2的效果。

方法2:三个元素同时浮动+calc()

方法2的主要思想是左中右三个元素同时设置浮动,左侧和右侧定宽的元素设置width属性为固定值,中间自适应区width属性通过calc方法获取。

HTML代码

在三个元素同时使用浮动后,HTML元素的书写顺序与最终呈现的顺序是保持一致的。

<div class="container">
    <div class="left">左侧宽度固定区域</div>
    <div class="middle">中间自适应宽度区域</div>
    <div class="right">右侧宽度固定区域</div>
</div>

CSS代码

对于父元素的基本属性同方法1一样,这里不做赘述。

左侧定宽区域设置float为left和width属性。

.left {
    width: 200px;
    float: left;
    background-color: #0ac2d2;
}

右侧定宽区域同样设置float为left和width属性。

.right {
    width: 200px;
    float: left;
    background-color: #9C27B0;
}

中间自适应区域设置float为left,width通过calc方法动态计算。

.middle {
    width: calc(100% - 400px);
    background-color: #2b542c;
    float: left;
}

运行以上代码后,即可得到图2的效果。

方法3:绝对定位+margin

方法3的主要思想是将左右两侧定宽区域设置为绝对定位,然后给中间自适应区设置margin属性调整其占用的空间。

采取绝对定位后,HTML元素书写和最后页面呈现顺序是保持一致的,所以HTML部分代码与方法2是一样的。

HTML代码

HTML元素的书写顺序与最终呈现的顺序保持一致。

<div class="container">
    <div class="left">左侧宽度固定区域</div>
    <div class="middle">中间自适应宽度区域</div>
    <div class="right">右侧宽度固定区域</div>
</div>

CSS代码

在设置绝对定位时通常会设置top,left,right等属性为0,这样绝对定位区布局会从浏览器的左上角开始布局,但是浏览器的默认行为下,会有margin值,元素实际不是从左上角开始布局,如下图所示。

所以为了让中间区域在设置margin属性不会存在间隙的情况,需要将页面body元素的margin属性设置为0。

body {
    margin: 0;
}

左侧定宽区,设置绝对定位与宽度值,将其left与top属性设置为0。

.left {
    position: absolute;
    top: 0;
    left: 0;
    width: 200px;
    background-color: #0ac2d2;
}

右侧定宽区,设置绝对定位与宽度值,因为区域位置要靠右侧,故将其right值设置为0。

.right {
    position: absolute;
    top: 0;
    right: 0;
    width: 200px;
    background-color: #9C27B0;
}

中间自适应区设置margin-left和margin-right属性为左右侧区的width属性。

.middle {
    margin: 0 200px 0 200px;
    background-color: #2b542c;
}

运行以上代码后,即可得到图2的效果。

方法4:flex布局

方法4的主要思想是通过CSS3的flex新特性进行布局。左侧和右侧定宽区域只需要设置一个初始值宽度即可,中间自适应区域通过flex-grow和flex-shrink属性占据剩余空间的全部。

HTML代码

HTML元素的书写顺序与最终呈现的顺序保持一致。

<div class="container">
    <div class="left">左侧宽度固定区域</div>
    <div class="middle">中间自适应宽度区域</div>
    <div class="right">右侧宽度固定区域</div>
</div>

CSS代码

首先是设置外层父元素的属性,需要将其display属性设置为flex。

.container {
    display: flex;
    height: 800px;
    color: #fff;
}
.container div {
    height: 100%;
}

左侧定宽div与右侧定宽div,都只需要设置flex属性中的flex-basis值即可,flex-grow和flex-shrink值为0。

.left {
    flex: 0 0 200px;
    background-color: #0ac2d2;
}
.right {
    flex: 0 0 200px;
    background-color: #9C27B0;
}

中间自适应区因为占据全部的剩余空间,所以将其flex-grow和flex-shrink值都设置为1即可,采用缩写的写法即flex: 1。

.middle {
    flex: 1;
    background-color: #2b542c;
}

运行以上代码后,即可得到图2的效果。

方法5:display:table进行布局

方法5的主要思想是将外层容器的display设置为table,以表格的样式呈现。表格在默认情况下,处于同一行中的所有列会平均分得表格占据的空间。如果给某些行设置了固定的宽度,那么剩余的空间会被其他列平均分配。

针对左中右三列的表格布局,只需要给左侧和右侧设置固定宽度,中间middle就会自动占据剩余的全部宽度,轻松达到左右固定宽度,中间自适应宽度的效果。

HTML代码

HTML元素的书写顺序与最终呈现的顺序是保持一致。

<div class="container">
    <div class="left">左侧宽度固定区域</div>
    <div class="middle">中间自适应宽度区域</div>
    <div class="right">右侧宽度固定区域</div>
</div>

CSS代码

  • body通用设置

body的margin和padding均设置为0。

body {
    margin: 0;
    padding: 0;
}
  • container容器设置

为了让container容器能成表格类型的展示,需要对container容器的display属性设置为table;同时为了让容器占满整个屏幕空间,需要设置其width和height属性设置为100%。

.container {
    display: table;
    width: 100%;
    height: 100%;
    text-align: center;
}
  • left,middle和right重要设置

在外层容器设置为table类型布局后,为了能让left,middle,right呈现三列展示形式,需要设置它们的display属性为table-cell。

.container > div {
    display: table-cell;
}
  • 左侧left和右侧right设置

如果不对左侧left和右侧right区进行定宽设置,那么left,middle和right三列将平均分布在容器中,达不到左右定高,中间自适应宽度的效果,因此需要对左侧left和右侧right进行宽度的设置。

.left {
    background-color: #0ac2d2;
    width: 200px;
}

.right {
    background-color: #9C27B0;
    width: 200px;
}
  • middle

对middle不需要进行额外的display设置,只需要设置一个背景色即可。

.middle {
    background-color: #2b542c;
}

运行以上代码后,即可得到图2的效果。

flex实现圣杯布局

圣杯布局

首先我们来看看,什么是圣杯布局呢?

圣杯布局是一种左中右三栏布局的情况,左侧,右侧定宽或者自适应,中间内容栏自适应。在PC端页面足够宽时,会呈现水平三栏布局,而在移动端页面宽度较小的时候,自动转换为垂直三栏布局。

圣杯布局的优势是,只需要写一套CSS代码就可以让页面兼容PC端和移动端两套环境。

效果图

我们以目前常见的网站布局为例,包括顶部网站简介区,中间内容区,下部网站协议许可区,中间内容区再分为左侧菜单栏区,中间文章区,右侧广告栏区。

根据上面的描述,首先将整个页面分为上中下三个区域,顶部为header区,下部为footer区,中间为main区,main区再分为左侧nav区,中间article区,右侧aside区。

在页面宽度足够时,整个页面按照上中下三栏布局,中间层再分为左中右三栏布局。

当页面宽度减小到一定的阈值时,便会呈现从上到下5栏布局。

以上布局会随着页面的宽度大小而动态改变。

实现过程

接下来我们会通过详细的讲解看看整个实现过程。

HTML代码

通过效果图能够看出,header区和footer区所处的位置都是固定的,只有中间三个区域会动态变化。为了更好的展示效果,我们使用HTML5语义化标签,header部分使用

标签,footer部分使用标签,中间div层包含,以及标签。

<header>header</header>
<div class='main'>
    <nav>nav</nav>
    <article>article</article>
    <aside>aside</aside>
</div>
<footer>footer</footer>

CSS代码

CSS代码是整个实现的重点,这里我们采用的是flex布局。

body

首先设置body的通用属性,例如背景色和字体大小。

body {
    font: 24px Helvetica;
    background-color: #999999;
}

因为我们需要兼容PC和移动端两套环境,在某些特定的样式上需要特定的处理,我们可以先处理完PC端布局再去考虑移动端布局实现。

header和footer

header区和footer区在表现上是一样的,因此可以设置成相同的样式,重要的是设置height属性。

header, footer {
    display: block;
    margin: 4px;
    padding: 5px;
    min-height: 100px;
    border: 1px solid #eebb55;
    border-radius: 7pt;
    background-color: #ffeebb;
}

真正的flex其实是针对中间main区以及内部的nav区,article区以及aside区,因此需要设置main区的display属性为flex,同样设置一个最小高度值。

还有一点需要注意的是flex-direction值的设置,默认情况下flex-direction为row,即表示横向从左到右排列,满足在PC端布局宽度足够时的情况。我们可以手动写上这个值,主要是便于在移动端布局时对这个值修改的理解。

.main {
    min-height: 480px;
    margin: 0;
    padding: 0;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-flow: row;
    flex-flow: row;
}
nav区

左侧的nav区,设置其初始宽度为父元素宽度的20%,即flex-basis值为20%。

在页面可视区域增大时,其扩大的区域值为1,即flex-grow为1,相比于article区的值要小,表示在可视区变宽时,nav区占用的可视空间比例要比article区小。

在页面区域缩小时,其收缩的区域值为6,即flex-shrink为6,相比于article区的值要大,表示在可视区变窄时,nav区缩小的空间比例要比article区大。

然后设置nav区普通的margin,padding等属性值,得到的CSS代码如下。

.main > nav {
    margin: 4px;
    padding: 5px;
    border: 1px solid #8888bb;
    border-radius: 7pt;
    background-color: #ccccff;
    -webkit-flex: 1 6 20%;
    flex: 1 6 20%;
}
aside区

aside区同nav区的表现形式一样,包括flex-grow和flex-shrink值,因此得到的CSS代码如下。

.main > aside {
    margin: 4px;
    padding: 5px;
    border: 1px solid #8888bb;
    border-radius: 7pt;
    background-color: #ccccff;
    -webkit-flex: 1 6 20%;
    flex: 1 6 20%;
}
article区

中间的article区,设置其初始宽度为父元素的60%,即flex-basis值为60%。

在页面可视区域增大时,其占用的区域要比nav和aside大,所以设置其flex-grow值为3。

在页面可视区域减小时,其缩小的空间比例要比nav和aside小,所以设置其flex-shrink值为1。

然后设置article区的普通padding,margin等属性,得到的CSS代码如下。

.main > article {
    margin: 4px;
    padding: 5px;
    border: 1px solid #cccc33;
    border-radius: 7pt;
    background-color: #dddd88;
    -webkit-flex: 3 1 60%;
    flex: 3 1 60%;
}

以上的代码运行完后,就可以达到图3的效果。

根据图3的效果,如果页面可视区减小到一定的阈值时,需要改变main区的布局方式,这个该如何实现呢?

适配移动端

在CSS中提供了@media属性,可以专门用作对移动端的样式处理。

在这里我们假设当页面宽度小于640px时,就不能装载下三栏的内容,即将640px当做对移动端的判断。

在这种情况下,我们需要将main区中的nav,article和aside区按照从上到下排列,代码的唯一修改的就是flex-direction值,将其设置为column。

在移动端小屏幕上,修改nav,aside,header和footer区占据的高度值,缩小到50px。

根据以上的分析,得到以下的CSS代码。

/* 窄到已不足以支持三栏 */
@media all and (max-width: 640px) {
    .main {
        -webkit-flex-flow: column;
        flex-direction: column;
    }
    .main > nav, .main > aside, header, footer {
        height: 50px;
    }
}

将以上代码完整运行,即可看到圣杯布局的动态转变过程。

上下固定,中间自适应

上下固定,中间自适应的布局方式,主要是将页面划分为上中下三个部分,上层和下层固定高度,中间层自适应页面高度。

其呈现方式如下图所示。

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/8/30/1658a4d5665dafb4~tplv-t2oaga2asx-image.image

在拖动浏览器时,头部header和底部footer占据的高度不变,中间main区占据的高度在动态变化。接下来我们来看看几种不同的实现方式。

方法1:position:absolute;绝对定位

方法1的主要思想是利用绝对定位,头部header和底部footer分别位于浏览器顶部和底部,再设置绝对定位后,只需要设置top和bottom分别为0即可。中间middle同样先设置绝对定位,然后将它的top和buttom值分别设置为头部header和底部bottom的height值即可。

接下来,我们看看具体的代码实现。

HTML代码

为了让标签更容易检索,我们使用HTML5语义化标签。整个页面会分为三个部分,所以设置三个元素即可。

<header>header</header>
<div class="middle">middle</div>
<footer>footer</footer>

CSS代码

body通用设置

为了让各元素之间可以无缝连接在一起,需要将body的margin和padding设置为0,同时设置文字居中展示。

body {
    margin: 0;
    padding: 0;
    text-align: center;
}
头部header与底部footer

header和footer部分设置position为absolute;由于这两个区域会定高,需要设置height属性;然后分别设置top与bottom属性来处于顶部和底部。

还有很重要的一点是,需要设置width为100%,由此得到以下CSS代码。

header {
    position: absolute;
    top: 0;
    left: 0;
    height: 60px;
    width: 100%;
    background-color: #0ac2d2;
}

footer {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 60px;
    width: 100%;
    background-color: #ffd500;
}
中间middle

中间middle同样需要设置position为absolute,然后其top与bottom属性值等于header和footer的height值,超出的部分自动滚动。

需要注意的是其width值也需要设置为100%,由此得到以下的CSS代码。

.middle {
    position: absolute;
    top: 60px;
    bottom: 60px;
    width: 100%;
    background-color: #e3e3e3;
    overflow: auto;
}

将以上代码运行后,即可得到图所示效果。

方法2:设置display: table

方法2的主要思想是将外层容器的display设置为table,以表格的样式呈现。表格在默认情况下,所有行会平均分得表格占据的空间。如果给某些行设置了固定的高度,那么剩余的空间会被其他行平均分配。

针对上中下三行的表格布局,只需要给顶部header和底部footer设置固定高度,中间middle就会自动占据剩余全部的高度,轻松达到上下固定高度,中间自适应的效果。

HTML部分的代码与上述方法1相同,这里就不做赘述。

CSS代码

body通用设置

body同样需要设置通用样式,margin与padding均为0,还有很重要的一点是设置容器高度为100%,已达到中间自适应的目的。

body {
    margin: 0;
    padding: 0;
    height: 100%;
}
body容器重要设置

我们直接将body设置为外层的容器,充当表格的角色,故需要设置其display为table;表格在默认情况下只能由表格的内容撑起其宽度,所以我们需要设置其宽度值,这里直接设置width为100%。

body {
    display: table;
    width: 100%;
    text-align: center;
}
header,middle,footer通用样式

在设置完外层容器的样式后,需要设置内部子元素的通用样式,在表格内部头部header,中间middle和底部footer需要充当行的角色。故需要设置它们的display为table-row。

因为元素标签名的不同,我们使用通配符来表示。

body > * {
    display: table-cell;
}
header和footer定高设置

如果不对header和footer进行定高设置,那么header,middle和footer三栏将平均分布在容器中,达不到上下定高,中间自适应高度的效果,因此需要对header和footer进行高度的设置。

header {
    background-color: #0ac2d2;
    height: 50px;
}

footer {
    background-color: #ffd500;
    height: 50px;
}

至此,运行以上的代码,即可得到图所示的效果。

方法3:flex布局

方法3的主要思想是通过flex布局实现,思路如下:

  • 将外层容器设置为flex布局;
  • 由于需要设置上中下三列布局,容器内元素排列方向设置为column;
  • 头部header和底部footer设置初始固定高度值,在页面收缩和扩展时不占用剩余空间;
  • 中间middle区占据剩余全部空间。

接下来我们看看具体的HTML和CSS代码。

HTML代码

HTML部分的代码同方法1和方法2一致,如下所示。

<header>header</header>
<div class="middle">middle</div>
<footer>footer</footer>

CSS代码

body通用设置

如方法2所示,需要对body进行通用的设置。

body {
    margin: 0;
    padding: 0;
    height: 100%;
}
body容器设置

body容器需要设置为flex布局方式,故其display属性设置为flex;由于容器内元素呈现列式分布,故其flex-direction属性需要设置为column。然后设置容器的高度和宽度为100%,充满整个页面。

body {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    text-align: center;
}
头部header和底部footer

header和footer区只需要设置一个初始高度值即可,在收缩和伸展页面的时候不需要占据剩余空间,所以只需要设置flex-basis值为固定高度值即可。

header {
    flex: 0 0 60px;
    background-color: #0ac2d2;
}
footer {
    flex: 0 0 60px;
    background-color: #ffd500;
}
中间middle区

中间middle区占据除了header和footer以外的全部剩余空间,所以在header和footer的flex-grow和flex-shrink均为0的时候,middle的flex-grow和flex-shrink设置为1即可。

.middle {
    flex: 1;
    background-color: #e3e3e3;
}

至此,运行以上的代码,即可得到图所示的效果。

方法4:怪异盒模型

方法4的主要思想是设置页面的整体布局方式为怪异盒模型,即设置box-sizing属性为border-box。

在怪异盒模型下,对象的实际高度等于设置的height值,其中包括border和padding属性,可以简单理解为:

ElementWidth = contentWidth + border + padding

接下来我们将详细的看看代码实现。

HTML代码

HTML代码与上述其他方法一致,只需设置上中下三个子元素即可。

<header>header</header>
<div class="middle">middle</div>
<footer>footer</footer>

CSS代码

通用设置

设置margin和padding均为0。

body {
    margin: 0;
    padding: 0;
}
html,body容器的设置

body作为装载上中下三个子元素的容器,它的高度也需要由html这个最外层容器决定,所以我们需要对html和body的高度做设置。

html, body {
    height: 100%;
    text-align: center;
}
body容器设置

首先需要对body容器的box-sizing属性设置为border-box,以达到怪异盒模型;然后设置padding-top和padding-bottom属性值,方便头部header和底部footer的定位。

body {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 60px 0;
    overflow: hidden;
}
头部header与底部footer设置

头部header区和底部footer区设置相对定位,然后分别设置height高度值。header区需要向上偏移,偏移的值为负数,绝对值刚好与body容器的padding-top值相等;footer区同样需要向上偏移,偏移的值为负数,绝对值刚好与body容器的padding-bottom值相等。

header {
     position: relative;
     top: -60px;
     height: 60px;
     background-color: #0ac2d2;
}

footer {
    position: relative;
    top: -60px;
    height: 60px;
    background-color: #ffd500;
    clear: both;
}
中间middle区设置

中间middle区占据全部的高度值,并且需要向上偏移header占据的高度,因为如果不偏移的话,middle区会从原本header占据的区域下开始布局,这样就会产生一个header高度的空隙区。

.middle {
    position: relative;
    top: -60px;
    height: 100%;
    background-color: #e3e3e3;
    overflow: auto;
    margin-right: 0 !important;
}

至此,运行以上的代码,即可得到图所示的效果。

并排等高布局

在实际的开发中经常会遇到这样的场景:左右两侧有两个div元素,两个div的内容占据的高度不定,需要让这两个div呈现等高布局。

具体表现形式如下图所示。

如上图所示,左侧div的内容通过一系列的br标签增加了其高度,右侧div内容只有一行字符,很明显可以看出左侧div的高度要比右侧div的高度要高很多,但是最终在呈现上两侧是等高的。

接下来我们一起看看几种不同的实现方案吧。

方法1:table布局

方法1的主要思想是设置容器为table布局,将左右两侧div设置为表格的两列,在默认情况下表格同一行的两列是等高的。

接下来我们看看具体的代码实现。

HTML代码

在页面布局时,增加一个wrap容器,wrap容器内有左右两个div元素,左侧div元素内部有很多个br标签以增加左侧div的高度,右侧div则只有一行文本值。

<div class="wrap">
    <div class="left">
        left div
        <br/><br/><br/><br/><br/><br/><br/><br/>
        <br/><br/><br/><br/><br/><br/>
        左侧div的内容很多
    </div>
    <div class="right">right div</div>
</div>

CSS代码

通用设置

设置margin和padding均为0。

body {
    margin: 0;
    padding: 0;
}
wrap容器的设置

外层容器增加类wrap,一方面设置其布局方式为table,另一方面设置其宽度和居中属性。

.wrap {
    display: table;
    width: 500px;
    margin: 0 auto;
}
左侧left和右侧right设置

左侧left和右侧right设置为单元格列展示,简单设置下其各占据50%宽度,为了更好的区分度,分别设置不同的背景色。

.left,
.right {
    width: 50%;
    padding: 10px;
    display: table-cell;
}

.left {
    background-color: #83e8f1;
}

.right {
    background-color: #fbf64b;
}

至此,运行以上的代码,即可得到图所示的效果。

方法2:flex布局

方法2的主要思想是通过对容器设置flex布局,容器内元素按从左至右排列,它们会自动占据相同的高度值。

HTML代码

HTML代码与方法1中的一样,这里不做赘述。

<div class="wrap">
    <div class="left">
        left div
        <br/><br/><br/><br/><br/><br/><br/><br/>
        <br/><br/><br/><br/><br/><br/>
        左侧div的内容很多
    </div>
    <div class="right">right div</div>
</div>

CSS代码

通用设置

设置margin和padding均为0。

body {
    margin: 0;
    padding: 0;
}

wrap容器的设置

外层容器增加类wrap,首先设置其布局方式为flex,flex容器的展示方式为默认的从左至右,即flex-direction属性设置为row。然后设置其占据的宽度值和居中展示,根据以上分析得到以下代码。

.wrap {
    padding: 20px;
    display: flex;
    flex-direction: row;
    margin: 0 auto;
    width: 500px;
}
左侧left和右侧right设置

左侧left和右侧right区,设置它们占据的初始宽度都是50%,在页面收缩和扩展时,分别缩小和扩大50%的剩余空间。然后设置不同的背景色,得到的CSS代码如下。

.left,
.right {
    flex: 1 1 50%;
}

.left {
    background-color: #83e8f1;
}

.right {
    background-color: #fbf64b;
}

至此,运行以上的代码,即可得到图所示的效果。

方法3:设置很大的margin和padding

方法3的主要思想是给左右两侧div设置一个很大的margin-bottom和padding-bottom值。

padding-bottom值的增大会撑开元素占据的空间,而margin-bottom设置为负值,则会向上缩小元素占据的空间,两者配合可以很好的实现这种场景。

当我们同时给左右两侧div同时设置一个非常大的padding-bottom值,两侧div的高度会同时撑开很大。这时我们再设置margin-bottom为负值,元素占据的空间会向上偏移,只需要保证padding-bottom和margin-bottom的绝对值相等,就可以让左侧div高度刚好和内容高度一致,而右侧div因为很大的margin-bottom和padding-bottom值,使其占据的高度值得以拉伸和左侧div一致。

HTML代码

HTML代码与方法1中的一样,这里不做赘述。

<div class="wrap">
    <div class="left">
        left div
        <br/><br/><br/><br/><br/><br/><br/><br/>
        <br/><br/><br/><br/><br/><br/>
        左侧div的内容很多
    </div>
    <div class="right">right div</div>
</div>

CSS代码

通用设置

设置margin和padding均为0。

body {
    margin: 0;
    padding: 0;
}


wrap容器的设置

外层容器增加类wrap,只需要简单的设置容器宽度与居中显示即可。

.wrap {
    width: 500px;
    margin: 0 auto;
    overflow: hidden;
}
左侧left和右侧right设置

左侧left和右侧right区,设置它们占据的宽度都是50%,分别置于左浮动和右浮动,然后同时设置一个很大的margin-bottom和padding-bottom值。

.left,
.right {
    margin-bottom: -100000px; /*数值随便设置,越大越好,也就是(-padding-bottom值)*/
    padding-bottom: 100000px; /*数值随便设置,越大越好*/
}

.left {
    width: 50%;
    float: left;
    background-color: #83e8f1;
}

.right {
    width: 50%;
    float: right;
    background-color: #fbf64b;
}

至此,运行以上的代码,即可得到图所示的效果。

水平垂直居中

水平垂直居中应该是前端CSS布局中最经典的一个问题了,不仅涉及到水平居中还有垂直居中,具体表现如下图所示。

如上图所示,蓝色背景为父元素,褐色背景为子元素,子元素在父元素中间水平垂直居中显示。

接下来我们会详细的看到几种不同的方法实现。

方法1:绝对定位,margin: auto;

方法1的主要思想是对子元素设置绝对定位,在已知子元素高度和宽度的情况下,设置上下左右全部为0,通过margin: auto;浏览器会自动计算外边距使得元素水平垂直居中显示。

接下来我们会详细看下代码实现。

HTML代码

页面的HTML代码相对简单,只有父子两个div元素。

<div class="parent">
    <div class="child"></div>
</div>

CSS代码

通用设置

设置body元素的margin和padding属性为0。

body {
    margin: 0;
    padding: 0;
}
父元素设置

对父元素设置相对定位,然后设定一个宽度和高度。

.parent {
    position: relative;
    width: 500px;
    height: 400px;
    background-color: #0ac2d2;
}
子元素设置
  • 子元素需要设置宽度和高度值,要不然在绝对定位时无法确定位置;
  • 子元素需要设置为绝对定位,距上下左右值都为0,然后通过设置margin: auto;来实现居中。
.child {
    width: 200px;
    height: 100px;
    background-color: #761c19;
}
.child {
    position: absolute;
    margin: auto;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

至此,运行以上的代码,即可得到图所示的效果。

方法2:绝对定位,margin负边距

方法2的主要思想是对元素设置绝对定位,在已知子元素高度和宽度的情况下,分别设置left和top值为50%,这时子元素会稍微靠右下侧,然后通过设置margin-top和margin-bottom为子元素本身高度和宽度一半的负值,就可以让子元素向左上侧移动,从而让子元素呈现水平垂直居中。

接下来我们看看详细的代码实现。

HTML代码

页面的HTML代码相对简单,只有父子两个div元素。

<div class="parent">
    <div class="child"></div>
</div>

CSS代码

通用设置

设置body元素的margin和padding属性为0。

body {
    margin: 0;
    padding: 0;
}
父元素设置

对父元素设置相对定位,然后设定一个宽度和高度。

.parent {
    position: relative;
    width: 500px;
    height: 400px;
    background-color: #0ac2d2;
}
子元素设置
  • 子元素需要设置宽度和高度值,要不然在绝对定位时无法确定位置;
  • 子元素需要设置为绝对定位,距top和left均为50%,然后通过设置margin-left和margin-top为负值,它们的值分别为子元素本身宽度和高度的一半。
.child {
    width: 200px;
    height: 100px;
    background-color: #761c19;
}
.child {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-left: -100px;
    margin-top: -50px;
}

至此,运行以上的代码,即可得到图所示的效果。

方法3:绝对定位,transform变换

方法3与方法2类似,都是对子元素设置为绝对定位,区别在于方法2中通过设置margin-left和margin-bottom为自身宽度和高度一半的负值来实现,方法3中通过设置transform值为translate,沿着x轴和y轴向负方向移动元素自身宽度和高度的一半值。

关于HTML代码和CSS通用设置和父元素设置代码都与方法2相同,接下来只重点展示子元素的CSS代码。

CSS代码-子元素设置
  • 子元素需要设置宽度和高度值,要不然在绝对定位时无法确定位置;
  • 子元素需要设置为绝对定位,距top和left均为50%,然后设置transform属性为translate,它的值都为-50%,表示分别向左和向上移动自身宽高的一半值。
.child {
    width: 200px;
    height: 100px;
    background-color: #761c19;
}

.child {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

配合方法2中的HTML和其他CSS代码运行,即可得到图所示的效果。

方法4:flex布局

方法4的主要思想是利用flex布局,只需要设置父元素的display属性为flex,让子元素不管是从横轴还是侧轴方向都向中间对齐即可。

以下是具体的代码实现。

HTML代码

页面的HTML代码相对简单,只有父子两个div元素。

<div class="parent">
    <div class="child"></div>
</div>

CSS代码

通用设置

设置body元素的margin和padding属性为0。

body {
    margin: 0;
    padding: 0;
}

父元素设置

首先是对父元素的基本设置,为了和上述其他方法实现的效果一样,给父元素设置宽度和高度值。在使用flex布局的时候即使不设置宽度依然可以实现水平垂直居中。

然后是对父元素的重要设置,包括设置display为flex;横轴内容布局方向为居中展示,即justify-content设置为center;纵轴内容同样采用居中布局,即align-items设置为center。

.parent {
    height: 500px;
    width: 400px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #0ac2d2;
}
子元素设置

子元素在不用进行任何设置的情况下,就可以满足水平垂直居中,页面展示效果如下。

但是为了保证和其他方法产生同样的效果,对子元素设置宽度,高度和背景色。

.child {
    width: 200px;
    height: 100px;
    background-color: #761c19;
}

至此,运行以上的代码,即可得到图所示的效果。

方法5:table-cell布局

方法5的主要思想是利用table-cell布局,相当于表格的td元素,因为td是行内元素无法设置宽度和高度,所以在实现上需要多嵌套一层元素。

被设置为table-cell的元素,通过设置text-align为center和vertical-align为middle,来使得子元素呈现水平垂直居中。因为内部的子元素本身是块级元素,对于text-align为center并不生效,所以需要设置其display为inline-block。

接下来将详细的讲解代码实现。

HTML代码

因为会在整个元素外部多嵌套一层,所以HTML部分的代码有两层嵌套,分别是外部容器,父元素和子元素。

<div class="box">
    <div class="parent">
        <div class="child"></div>
    </div>
</div>

CSS代码

通用设置

设置body元素的margin和padding属性为0。

body {
    margin: 0;
    padding: 0;
}

容器元素设置

容器元素即类为box的元素,首先将其设置为table布局,然后设置宽度和高度即可。

.box {
    width: 500px;
    height: 400px;
    display: table;
    background-color: #f00;
}

在上面的代码中,虽然对box设置了背景色,但是在只有一行一列的情况下,设置为table-cell的元素会默认占据全部的高度和宽度,所以对table-cell的元素设置的背景色会覆盖掉box的元素。

父元素设置

父元素首先需设置为table-cell,然后通过text-align和vertical-align属性控制子元素的水平垂直居中显示。

.parent {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
    background-color: #0ac2d2;
}

如容器元素设置部分的描述,parent元素设置的背景色会覆盖掉box容器设置的背景色。

子元素设置

对父元素设置了text-align为center,但是其只会对内联元素生效,而子元素因为是块级元素,需要设置宽度和高度,因此需要子元素既有块元素也有内联元素的特征,最终对子元素设置display为inline-block。

.child {
    width: 200px;
    height: 100px;
    background-color: #761c19;
    display: inline-block;
}

至此,运行以上的代码,即可得到图所示的效果。

方法6:借助其他元素

方法6的主要思想是增加一个和子元素并列的div元素,设置其高度值为父元素的50%。如果不对这个元素做其他设置的话,那么子元素的布局是从父元素高度的一半开始,明显是不能垂直居中的,因此需要对并列的div元素做向上的偏移,偏移的量为子元素高度值的一半。

对于子元素水平居中,只需要设置margin: 0 auto;

接下来将详细的看下代码实现。

HTML代码

因为这个方法会借助其他元素,需要增加一个和子元素同级的div元素。

<div class="parent">
    <div class="extra"></div>
    <div class="content"></div>
</div>

CSS代码

通用设置

设置body元素的margin和padding属性为0。

body {
    margin: 0;
    padding: 0;
}

容器元素设置

对父元素设置高度,宽度与背景色即可。

.parent {
    position: relative;
    width: 500px;
    height: 400px;
    background-color: #0ac2d2;
}
额外元素设置

对额外的元素设置高度值为父元素的50%,而且设置margin-bottom为子元素高度的一半的负值。

.extra {
    height: 50%;
    margin-bottom: -50px;
}
子元素设置

子元素通过设置margin为0 auto;来居中展示,因为额外元素的设置,直接设置高度和宽度就可以达到垂直居中的状态。

.content {
    clear: both;
    height: 100px;
    width: 200px;
    margin: 0 auto;
    background-color: #761c19;
}

至此,运行以上的代码,即可得到图所示的效果。