一文搞定各类前端常见布局方式
1. 水平居中布局
1.1 inline-block
text-align
优点:css2兼容性好
缺点:text-align
属性具有继承性,影响子元素文本对齐方式
<style>
#parent { width: 100%; height: 200px; background-color: #ccc; }
#child { width: 200px; height: 200px; background-color: red; }
#parent {
text-align: center;
}
#child {
/**
* block: 块级元素
* inline: 内联元素(text-align属性有效),width/height属性无效
* inline-block: 行内块元素(块级 内联)
*/
display: inline-block;
}
</style>
<div id="parent">
<div id="child">测试</div>
</div>
1.2 table/block
margin
优点:只对子元素设置即可
缺点:若子元素脱离文档流,会导致 margin 失效,如 float、absolute、fixed
代码语言:html复制<style>
#parent { width: 100%; height: 200px; background-color: #ccc; }
#child { width: 200px; height: 200px; background-color: red; }
#child {
/**
* table / block 皆可
*/
display: table;
margin: 0 auto;
}
</style>
<div id="parent">
<div id="child">测试</div>
</div>
1.3 absolute
transform
优点:父元素是否脱离文档流不影响子元素水平居中效果
缺点:transform是css3属性,可能有兼容性问题
代码语言:html复制<style>
#parent { width: 100%; height: 200px; background-color: #ccc; }
#child { width: 200px; height: 200px; background-color: red; }
#parent {
position: relative;
}
#child {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<div id="parent">
<div id="child">测试</div>
</div>
2. 垂直居中布局
2.1 table-cell
vertical-align
优点:浏览器兼容性好
缺点:vertical-align
属性具有继承性,导致父元素内的文本也居中,因此若父元素内包含除该元素外的文本将不适用
display: table
设置当前元素为 <table>
display: table-cell
设置当前元素为 <td>
,此时子元素将作为单元格内容,支持 vertical-align
vertical-align
用于设置内联元素的垂直居中,top / middle / bottom
<style>
#parent { width: 200px; height: 600px; background-color: #ccc; }
#child { width: 200px; height: 200px; background-color: red; }
#parent {
display: table-cell;
vertical-align: middle;
}
#child {
}
</style>
<div id="parent">
<div id="child">测试</div>
</div>
2.2 absolute
transform
优点:父元素是否脱离文档流不影响子元素垂直居中效果
缺点:transform是css3属性,可能有兼容性问题
代码语言:html复制<style>
#parent { width: 200px; height: 600px; background-color: #ccc; }
#child { width: 200px; height: 200px; background-color: red; }
#parent {
position: relative;
}
#child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
</style>
<div id="parent">
<div id="child">测试</div>
</div>
3. 两列布局
定义:一列定宽,一列自适应
3.1 float
margin
代码语言:html复制<style>
#left { height: 300px; background-color: red; }
#right { height: 300px; background-color: yellow; }
#left {
width: 300px;
float: left;
}
#right {
margin-left: 300px;
}
</style>
<div id="left">left</div>
<div id="right">right</div>
优点:简单
缺点:
- left-width 和 right-width 必须同时设置为相同值
- 浮动与不浮动元素混用可能存在兼容问题
- right 中若存在 clear 清除浮动,会出现布局问题
代码语言:html复制clear 属性用于指定左侧或右侧不允许浮动的元素,可选值 left / right / both / none / inherit,前三个表示左侧/右侧/两侧不允许浮动元素,默认 none 允许两侧有浮动元素
<style>
#left { height: 300px; background-color: red; }
#right { height: 300px; background-color: yellow; }
#inner { height: 300px; background-color: #ccc; }
#left {
width: 300px;
float: left;
}
#right {
margin-left: 300px;
}
#inner {
/* 右侧存在 clear 清除浮动,会出现布局问题 */
clear: both;
}
</style>
<div id="left">left</div>
<div id="right">
<div id="inner"></div>
</div>
3.1 优化上面的 float
margin
(复杂不推荐)
可以为右列自适应元素增加父级容器 right-fix
,解决上面的浮动与不浮动元素混用可能存在的兼容问题,和右列存在 clear 清除浮动出现的错误。
<style>
#left { height: 300px; background-color: red; }
#right-fix { height: 300px; background-color: #ccc; }
#right { height: 300px; background-color: yellow; }
#inner { height: 300px; background-color: green; }
#left {
width: 300px;
float: left;
/* position定位的层级高于浮动! */
position: relative;
}
#right-fix {
float: right;
/* 浮动导致默认宽度为0 */
width: 100%;
margin-left: -300px;
}
#right {
margin-left: 300px;
}
#inner {
clear: both;
}
</style>
<div id="left">left</div>
<div id="right-fix">
<div id="right">
<div id="inner">inner</div>
</div>
</div>
right-fix
元素设置浮动后,默认宽度为 0,需要设置宽度为 100%,如下图1所示,通过设置容器 margin-left: -300px;
实现图2效果,此时 right-fix
层级高于 left
,可以为 #left
添加 position: relative;
来提高层级,因为 position 定位的层级高于浮动!如图3所示。此时在 #right
中添加元素,即使包含 clear
清除浮动也没有影响。
3.3 float
overflow
左列同样使用 float
,右侧不用 margin-left
,而用 overflow: hidden;
开启 BFC
模式,将元素内部环境与外界完全隔离。
代码语言:html复制开启BFC,不仅可以通过 overflow 实现
<style>
#left { height: 300px; background-color: red; }
#right { height: 300px; background-color: yellow; }
#left {
width: 300px;
float: left;
}
#right {
/* 开启BFC模式,当前元素的内部环境与外界完全隔离 */
overflow: hidden;
}
</style>
<div id="left">left</div>
<div id="right">right</div>
优点:简单
缺点:BFC存在副作用,overflow 属性同时设置了内容溢出处理,导致一些场景下出现问题无法解决
3.4 display
(table
)
利用 table 的特性,默认宽度平分,当设置了左列宽度,右列自动占满剩余宽度
代码语言:html复制<style>
#left { height: 300px; background-color: red; }
#right { height: 300px; background-color: yellow; }
#parent {
width: 100%;
/* 表格的单元格的宽度会自动分配 */
display: table;
table-layout: fixed;
}
#left, #right {
display: table-cell;
}
#left {
width: 300px;
}
</style>
<div id="parent">
<div id="left">left</div>
<div id="right">right</div>
</div>
优点:兼容性好
缺点:将所有元素设置为 table 相关值,会受到一定制约(一些表格特性)
4. 三列布局&圣杯布局&双飞翼布局
圣杯布局和双飞翼布局是指三行三列的布局,其中中间行中间列的元素自适应,重点在于第二行的实现。
代码语言:txt复制| header |
| 定宽 | 自适应 | 定宽 |
| footer |
4.1 三列布局:float
margin
(不推荐)
圣杯布局中间行的一种实现方式如下:
代码语言:html复制<style>
#left { height: 100px; background-color: red; }
#center { height: 100px; background-color: yellow; }
#right { height: 100px; background-color: blue; }
#left, #right {
width: 100px;
}
#left {
float: left;
}
#right {
float: right;
}
#center {
margin-left: 100px;
margin-right: 100px;
}
</style>
<div id="left">left</div>
<div id="right">right</div>
<!-- 注意顺序,center放在了最后 -->
<div id="center">center</div>
采用的方式是左右两列浮动,中间使用 margin 左右自适应,但 DOM 若按照 left、center、right 的顺序,center 会占据 right 的位置导致不在一行,如下图所示:
所以只能按照 left、right、center 的顺序,核心区 center 必须放最后,这么做降低了 center 核心内容的搜索引擎抓取优先级且对开发者阅读起来不友好。
4.2 圣杯布局:添加父节点 开启定位处理覆盖
【step1】全部浮动
将 left、center、right 全部浮动,并使用 margin 将 parent 左右预留出左右列的宽度,效果如下图所示
代码语言:html复制<style>
#left, #center, #right, #parent { height: 100px; }
#left { background-color: red; }
#center { background-color: yellow; }
#right { background-color: blue; }
#header, #footer { width: 100%; height: 30px; background-color: #ccc; text-align: center; }
/* 【step1】全部浮动 */
/* 添加父节点用于处理中间行布局,左右预留位置 */
#parent {
/* 对应左列宽度 */
margin-left: 100px;
/* 对应右列宽度 */
margin-right: 100px;
}
/* 左中右全部浮动 */
#left, #center, #right {
float: left;
}
/* 左右定宽 */
#left, #right {
width: 100px;
}
/* 中间自适应 */
#center {
width: 100%;
}
/* 【step2】处理left */
#left {
/* 从当前行移动到上一行 */
margin-left: -100%;
/* 向左移动自身宽度到目标位置 */
position: relative;
left: -100px;
}
/* 【step3】处理right */
#right {
margin-left: -100px;
position: relative;
right: -100px;
}
</style>
<div id="header">header</div>
<!-- 添加的父节点 -->
<div id="parent">
<!-- 注意顺序,center作为核心内容区前置 -->
<div id="center">center</div>
<div id="left">left</div>
<div id="right">right</div>
</div>
<div id="footer">footer</div>
【step2】处理left
设置 left 的 margin-left 为 -100%,实现 left 从当前行移动到上一行,如下图所示:
代码语言:css复制#left {
/* 从当前行上移一行 */
margin-left: -100%;
}
此时只能借助 position 定位来将 left 继续向左移动自身宽度
代码语言:css复制#left {
position: relative;
left: -100px;
}
【step3】处理right
处理方式与 left 相似,通过设置 right 的 margin-left 为自身宽度,实现 right 从当前行上移到上行行尾,如图所示:
再借助 position 定位移动到目标位置
【step4】添加header/footer
最后添加 header、footer,完成的圣杯布局如下图所示:
4.3 双飞翼布局:添加子节点处理左右覆盖
双飞翼布局最早由淘宝团队提出,是针对圣杯布局的优化方案,主要优化了圣杯布局开启定位的问题。
代码语言:html复制<style>
#left, #center, #inner, #right { height: 100px; }
#left { background-color: red; }
#center { background-color: yellow; }
#inner { background-color: green; }
#right { background-color: blue; }
/* 【step1】全部浮动 */
#left, #right {
width: 100px;
}
#left, #center, #right {
float: left;
}
#center {
width: 100%;
}
/* 【step2】left、right上移 */
#left {
margin-left: -100%;
}
#right {
margin-left: -100px;
}
/* 【step3】处理center左右覆盖问题 */
#inner {
margin-left: 100px;
margin-right: 100px;
}
</style>
<div id="center">
<!-- 添加子节点处理左右两列覆盖问题 -->
<div id="inner">inner</div>
</div>
<div id="left">left</div>
<div id="right">right</div>
4.4 对比
圣杯布局和双飞翼布局的差异点在于左右两列重叠部分的处理方式,圣杯布局通过增加父结点并开启左右两列定位的方式实现,而双飞翼通过在 center 添加子节点实现,更加简洁。
6. 等分布局(栅格布局)
等分布局指一行被分成若干宽度相等的列。比如 bootstrap 会将一行分为 12 列。
6.1 float
代码语言:html复制<style>
.col1 { background-color: red; }
.col2 { background-color: yellow; }
.col3 { background-color: blue; }
.col4 { background-color: green; }
.col1, .col2, .col3, .col4 {
float: left;
/* 计算宽度 */
width: 25%;
height: 100px;
}
</style>
<div id="parent">
<div class="col1"></div>
<div class="col2"></div>
<div class="col3"></div>
<div class="col4"></div>
</div>
6.2 display(table)
借助表格特性实现等分,需要注意,div 变 table 后,默认宽度从 100% 变为 0,需要设置父节点宽度为 100%
代码语言:html复制<style>
.col1 { background-color: red; }
.col2 { background-color: yellow; }
.col3 { background-color: blue; }
.col4 { background-color: green; }
#parent {
/* div变成table后,默认宽度从 100% 变为 0 */
width: 100%;
display: table;
}
.col1, .col2, .col3, .col4 {
height: 100px;
display: table-cell;
}
</style>
<div id="parent">
<div class="col1"></div>
<div class="col2"></div>
<div class="col3"></div>
<div class="col4"></div>
</div>
6.3 float
列间空白间距的实现
空白间距可以使用 padding-left
实现,为了能看出间距存在,需要给每列添加 inner 子节点,为子节点设置背景色。还需要设置 box-sizing: border-box;
否则默认的 content-box
计算方式会导致折行。针对第一列左侧多余的空白间距,可以在容器 parent 上设置 margin-left
。最后,由于 #parent
的宽度会比最外层的 #parent-fix
多出一个间距 10px,因此推荐设置 overflow 避免内容溢出。
<style>
.col1 .inner { height: 100px; background-color: red; }
.col2 .inner { height: 100px; background-color: yellow; }
.col3 .inner { height: 100px; background-color: blue; }
.col4 .inner { height: 100px; background-color: green; }
.col1, .col2, .col3, .col4 {
height: 100px;
width: 25%;
float: left;
/* 空出间距 */
padding-left: 10px;
/* 重要,尺寸计算方式,默认 content-box 会导致换行 */
box-sizing: border-box;
}
#parent {
height: 100px;
/* 解决第一列前多余的间距 */
margin-left: -10px;
}
#parent-fix {
overflow: hidden;
}
</style>
<div id="parent-fix">
<div id="parent">
<div class="col1"><div class="inner"></div></div>
<div class="col2"><div class="inner"></div></div>
<div class="col3"><div class="inner"></div></div>
<div class="col4"><div class="inner"></div></div>
</div>
</div>
6.4 display(table)
列间空白间距的实现
方法与 float
相似,不同的是,由于 table 的特性,默认 #parent
宽度和 #parent-fix
相同,在 #parent
设置了 margin-left
后,整体 #parent
向左便宜,导致右侧行尾多出一个间距的空白,所以要设置 #parent
宽度为 #parent-fix
一个间距。
<style>
.col1 .inner { height: 100px; background-color: red; }
.col2 .inner { height: 100px; background-color: yellow; }
.col3 .inner { height: 100px; background-color: blue; }
.col4 .inner { height: 100px; background-color: green; }
#parent {
display: table;
margin-left: -10px;
/* 重要,解决 margin-left 后行尾多出一个间距的问题 */
width: calc(100% 10px);
}
.col1, .col2, .col3, .col4 {
height: 100px;
display: table-cell;
padding-left: 10px;
box-sizing: border-box;
}
.parent-fix {
overflow: hidden;
}
</style>
<div id="parent-fix">
<div id="parent">
<div class="col1"><div class="inner"></div></div>
<div class="col2"><div class="inner"></div></div>
<div class="col3"><div class="inner"></div></div>
<div class="col4"><div class="inner"></div></div>
</div>
</div>
7. 等高布局
等高布局是指一行中每列高度相同的布局。
7.1 display(table)
利用表格单元格默认等高的特性,轻松实现等高布局。
代码语言:html复制<style>
#left { background-color: red; }
#right { background-color: yellow; }
#parent {
display: table;
}
#left, #right {
/* div默认高度0,宽度100% */
width: 300px;
display: table-cell;
}
</style>
<div id="parent">
<div id="left">left</div>
<div id="right">right<br>right<br>right</div>
</div>
7.2 padding
margin
伪等高布局,仅视觉上效果为等高布局。通过设置 padding-bottom
为极大值,设置 margin-bottom
为极小值进行对冲,最后通过 parent
上的 overflow: hidden;
解决容器高度塌陷问题并遮挡多余部分实现等高布局。
<style>
#left { background-color: red; }
#right { background-color: yellow; }
#left, #right {
width: 300px;
/* 浮动起来,从垂直布局变为水平布局 */
float: left;
/* 对冲 */
padding-bottom: 9999px;
margin-bottom: -9999px;
}
#parent {
/* 关键,用于解决 parent 高度塌陷问题 */
overflow: hidden;
}
</style>
<div id="parent">
<div id="left">left</div>
<div id="right">right<br>right<br>right</div>
</div>
8. 全屏布局
页面铺满整个页面,没有滚动条,会随浏览器大小变化,使用 fixed 定位可以轻松实现。
代码语言:html复制<style>
html, body { margin: 0; overflow: hidden; }
header, footer {
/* width: 100%; */
height: 50px;
position: fixed;
left: 0;
right: 0;
background-color: #ccc;
}
header {
top: 0;
}
footer {
bottom: 0;
}
.content {
position: fixed;
left: 0;
right: 0;
top: 50px;
bottom: 50px;
/* 内容超出后出现滚动条 */
overflow: auto;
}
.content .left {
width: 200px;
height: 100%;
position: fixed;
left: 0;
top: 50px;
bottom: 50px;
background-color: aqua;
}
.content .right {
height: 100%;
margin-left: 200px;
background-color: antiquewhite;
}
</style>
<header>header定高 fixed</header>
<div class="content">
<div class="left">left定宽,高度自适应</div>
<div class="right">right宽高自适应</div>
</div>
<footer>footer定高 fixed</footer>
9. 响应式布局
9.1 flex弹性盒模型布局
flex 布局是 css3中最好用的布局方式。通过在父元素上设置 flex-direction
、flex-wrap
、justify-content
、align-items
、align-content
属性实现主轴方向、换行、主轴和交叉轴对齐方式等,在子元素上设置 order
、align-self
、flex-grow
、flex-shrink
、flex-basis
属性实现排序、重写子元素align-items
交叉轴对齐方式、空间分配等。
更多flex布局的内容将会单独写一篇进行讲解。
9.2 vw/vh
css3 新单位 vw/vh,对应视图宽高的百分比,如 1vw = 视图宽度1%
比百分比布局更好用
9.3 rem
rem 值表示相对<html>
根元素的比例,默认 html 元素 font-size 为 16px,即 1rem=16px
,一般会动态设置 1rem = 100px,方便按照设计稿尺寸计算。如设计稿宽度为 750px,一个设计稿宽 25px 的 div,设置 width: 0.25rem;
即可
10.3 @media 媒体查询
针对不同屏幕分辨率定义不同样式,从而达到自适应效果,例如移动端和PC端通过媒体查询设置不同背景图片,但开发繁琐
10.4 %百分比
css属性通过设置百分比值替代固定值,从而实现响应式效果。不推荐,因为计算麻烦,如在css中:
- width、height 属性的百分比值依赖父标签的数据;
- padding、margin 设置百分比值,无论垂直还是水平方向,都相对于父元素的
width
,与父元素的height
无关; - border-radius 设置百分比值,则是相对于元素自身宽度
10. CSS3多列布局 — column
css3 提供了设置多列布局的属性,column-count
定义列的数量,column-width
定义列的宽度,columns
为简写,并支持设置列间距、列边框、横跨多列、列填充。
<style>
.col1, .col6 { background-color: red; }
.col2, .col7 { background-color: yellow; }
.col3, .col8 { background-color: blue; }
.col4, .col9 { background-color: green; }
.col5 { background-color: pink; }
.col1, .col2, .col3, .col4, .col5 { height: 100px; }
#parent1, #parent2 {
column-count: 4; /* 列数量 auto/number */
column-width: 100px; /* 列宽度 auto/length */
/* columns: 4 100px; */
/* 列间距 */
column-gap: 16px; /* noraml/length 默认值 noraml 表示 1em */
/* 列边框 */
column-rule-width: 5px;
column-rule-color: red;
column-rule-style: double;
/* column-rule: 5px red double; */
}
.col5 {
/* 横跨多列 */
column-span: all; /* 定义一个列元素是否跨列,none(默认不跨列)/all(跨所有列) */
}
.col6, .col7, .col8, .col9 {
/* 列填充 */
column-fill: balance; /* 定义列的高度由内容决定还是统一设置,auto(默认由内容决定)/balance(列高按内容最多的一列) */
}
</style>
<div id="parent1">
<div class="col1">col1</div>
<div class="col2">col2</div>
<div class="col3">col3</div>
<div class="col4">col4</div>
<div class="col5">col5</div>
</div>
<div id="parent2">
<div class="col6">col6<br>col6</div>
<div class="col7">col7<br>col7<br>col7</div>
<div class="col8">col8</div>
<div class="col9">col9</div>
</div>
11. 网格布局 — grid
网格布局是强大的 css 布局方案。grid 布局 api 比较多,会单独写一篇进行讲解。