https://juejin.cn/post/6844903510933258247
https://juejin.cn/post/6844904121862979597#heading-22
https://juejin.cn/post/6844903510933258247
一、水平居中
- 子元素绝对定位+top+transform/margin-left
父元素:relative、absolute、fixed
都可以,但不能是``static。如果没有经过定位的父元素,则是相对于body
。
tansform
是CSS3属性,有兼容性问题。margin-left
需要知道子元素宽度。
<style>
.wrap {
position: relative;
width: 100%;//定宽
height: 200px;
background-color: aqua;
}
.content {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 200px;//定宽
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
- 子元素设置为行内元素(inline-block)+text-align
注意:text-align
具有继承性
此方法可以将多个子元素进行水平居中
<style>
.wrap {
width: 100%;
height: 200px;
background-color: aqua;
text-align: center;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
display: inline-block;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
- 子元素设置为块级元素(block、table)+margin
- 必须定宽!
- 子元素如果脱离文档流,会使得
margin
无效
<style>
.wrap {
width: 100%;
height: 200px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
display: table;
margin: 0 auto;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
- flex:justify-content
二、垂直居中
- 绝对定位+left+transfrom
- 父元素设置为table-cell+vertical-align
table-cell内部元素具有类似文本元素的属性
vertical-align具有继承性
<style>
.wrap {
display: table-cell;
vertical-align: middle;
width: 200px;
height: 600px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
- line-height=height
只适用于行内元素
只适用于单行内容
若想要用于多行,需要设置文字高度为总高度除以行数
#parent{
height: 150px;
line-height: 150px; /*与height等值*/
}
- 设置padding
- flex:align-items/align-content
三、水平垂直居中
四、两列布局
1、左列定宽,右列自适应
- 绝对定位实现
#parent{
position: relative; /*子绝父相*/
}
#left {
position: absolute;
top: 0;
left: 0;
background-color: #f00;
width: 100px;
height: 500px;
}
#right {
position: absolute;
top: 0;
left: 100px; /*值大于等于#left的宽度*/
right: 0;
background-color: #0f0;
height: 500px;
}
<body>
<div id="parent">
<div id="left">左列定宽</div>
<div id="right">右列自适应</div>
</div>
</body>
- 左边元素浮动,定宽,右边元素设置margin-left
<style>
.l, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.r {
background-color: blueviolet;
margin-left: 400px;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">自适应</div>
</body>
- 左边元素浮动,定宽,右边元素设置overflow:hidden
右边元素由于设置overflow:hidden开启BFC,与外界隔离,所以能实现效果
浮动脱离文档流,需要手动清除浮动,否则会产生高度塌陷
<style>
.l, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.r {
background-color: blueviolet;
overflow: hidden;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">自适应</div>
</body>
- 将左右元素用一个display:table的元素包裹,左右元素设置为display: table-cell
margin失效;设置间隔比较麻烦;不支持ie8-
<style>
.w {
display: table;
table-layout: fixed;
width: 100%;
}
.l, .r {
display: table-cell;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.r {
background-color: blueviolet;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="r">自适应</div>
</div>
</body>
- flex布局
<style>
.p {
display: flex;
height: 600px;
}
.l {
background-color: aqua;
width: 400px;
}
.r {
flex: 1;
background-color: blueviolet;
}
</style>
<body>
<div class="p">
<div class="l">定宽</div>
<div class="r">自适应</div>
</div>
</body>
2、左列自适应,右列定宽
- 使用绝对定位实现
#parent{
position: relative; /*子绝父相*/
}
#left {
position: absolute;
top: 0;
left: 0;
right: 100px; /*大于等于#rigth的宽度*/
background-color: #f00;
height: 500px;
}
#right {
position: absolute;
top: 0;
right: 0;
background-color: #0f0;
width: 100px;
height: 500px;
}
<body>
<div id="parent">
<div id="left">左列自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
- 右边元素浮动,定宽,左边元素设置margin-right
#parent {
height: 500px;
}
#left {
width: 100%;
height: 500px;
margin-right: 100px;
background-color: #f00;
}
#right {
height: 500px;
width: 100px;
float: right;
background-color: #0f0;
}
<body>
<div id="parent">
<div id="right">右列定宽</div>
<div id="left">左列自适应</div>
</div>
</body>
#parent{
height: 500px;
padding-left: 100px; /*抵消#left的margin-left以达到#parent水平居中*/
}
#left {
width: 100%;
height: 500px;
float: left;
margin-left: -100px; /*正值等于#right的宽度*/
background-color: #f00;
}
#right {
height: 500px;
width: 100px;
float: right;
background-color: #0f0;
}
<body>
<div id="parent">
<div id="left">左列自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
- 右边元素浮动,定宽,左边元素设置overflow:hidden
#left {
overflow: hidden; /*触发bfc*/
height: 500px;
background-color: #f00;
}
#right {
margin-left: 10px; /*margin需要定义在#right中*/
float: right;
width: 100px;
height: 500px;
background-color: #0f0;
}
<body>
<div id="parent">
<div id="right">右列定宽</div>
<div id="left">左列自适应</div> <!--顺序要换一下-->
</div>
</body>
- 将左右元素用一个display:table的元素包裹,左右元素设置为display: table-cell
#parent{
width: 100%;
height: 500px;
display: table;
}
#left {
background-color: #f00;
display: table-cell;
}
#right {
width: 100px;
background-color: #0f0;
display: table-cell;
}
<body>
<div id="parent">
<div id="left">左列自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
- 使用flex实现
#parent{
height: 500px;
display: flex;
}
#left {
flex: 1;
background-color: #f00;
}
#right {
width: 100px;
background-color: #0f0;
}
<body>
<div id="parent">
<div id="left">左列自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
3、左列不定,右列自适应
把左列的宽度设置删掉即可。
五、三列布局
1、普通三列布局
方法与两列布局相同
2、中间固定宽度,两边自适应
- 绝对定位实现
<body>
<div id="parent">
<div id="left">左列定宽</div>
<div id="center">中间自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
#parent {
position: relative; /*子绝父相*/
}
#left {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 500px;
background-color: #f00;
}
#center {
height: 500px;
margin-left: 100px; /*大于等于#left的宽度,或者给#parent添加同样大小的padding-left*/
margin-right: 200px; /*大于等于#right的宽度,或者给#parent添加同样大小的padding-right*/
background-color: #eeff2b;
}
#right {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 500px;
background-color: #0f0;
}
- 左边右边元素浮动,定宽,中间元素设置margin-left、 margin-right
注意:这种方式,需要在书写html结构时,将右侧元素写在中间元素的前面,因为如果右侧元素在中间元素后面,由于浮动元素位置上不能高于(或平级)前面的非浮动元素,导致右侧元素会下沉。但是,中间元素一般都是页面的核心部分,放在比较后面的位置,不利于SEO。
<style>
.l, .c, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.c {
background-color: blueviolet;
margin-left: 400px;
margin-right: 400px;
}
.r {
width: 400px;
background-color: brown;
float: right;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">定宽</div>
<div class="c">自适应</div>
</body>
- 左边右边元素浮动,定宽,中间元素设置overflow: hidden
<style>
.l, .c, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.c {
background-color: blueviolet;
overflow: hidden;
}
.r {
width: 400px;
background-color: brown;
float: right;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">定宽</div>
<div class="c">自适应</div>
</body>
- 将左右元素用一个display:table的元素包裹,左右元素设置为display: table-cell
margin失效,采用border-spacing表格两边的间隔无法消除;不支持ie8-
<body>
<div id="parent">
<div id="left">左列定宽</div>
<div id="center">中间自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
#parent {
width: 100%;
height: 500px;
display: table;
}
#left {
display: table-cell;
width: 100px;
background-color: #f00;
}
#center {
display: table-cell;
background-color: #eeff2b;
}
#right {
display: table-cell;
width: 200px;
background-color: #0f0;
}
- flex布局
<body>
<div id="parent">
<div id="left">左列定宽</div>
<div id="center">中间自适应</div>
<div id="right">右列定宽</div>
</div>
</body>
#parent {
height: 500px;
display: flex;
}
#left {
width: 100px;
background-color: #f00;
}
#center {
flex: 1; /*均分#parent剩余的部分*/
background-color: #eeff2b;
}
#right {
width: 200px;
background-color: #0f0;
}
3、圣杯布局
这种方法将中间元素放置在最前面,有利于SEO。
<template>
<header>header</header>
<section class="wrapper">
<section class="col main">main</section>
<aside class="col left">left</aside>
<aside class="col right">right</aside>
</section>
<footer>footer</footer>
</template>
<style>
/* 以下为简码,仅保留关键部分 */
header,footer {height: 50px;}
.wrapper {padding: 0 100px 0 100px; overflow:hidden;}
.col {position: relative; float: left;}
.main {width: 100%;height: 200px;}
.left {width: 100px; height: 200px; margin-left: -100%;left: -100px;}
.right {width: 100px; height: 200px; margin-left: -100px; right: -100px;}
</style>
使用了 relative 相对定位、float(需要请浮动,此处使用 overflow:hidden; 方法)和 负值 margin ,将 left 和 right 部分「安装」到 wrapper 的两侧,顾名「圣杯」。
正常情况下是没有问题的,但是特殊情况下就会暴露此方案的弊端,如果将浏览器无限变窄,「圣杯」将会「破碎」掉。如图,当 main 部分的宽小于 left 部分时就会发生布局混乱。
4、双飞翼布局
这种方法将中间元素放置在最前面,有利于SEO。
<template>
<header>header</header>
<section class="wrapper">
<section class="col main">
<section class="main-wrap">main</section>
</section>
<aside class="col left">left</aside>
<aside class="col right">right</aside>
</section>
<footer>footer</footer>
</template>
<style>
/* 以下为简码,仅保留关键部分 */
header,footer {height: 50px;}
.wrapper {padding: 0; overflow:hidden;}
.col {float: left;}
.main {width: 100%;}
.main-wrap {margin: 0 100px 0 100px;height: 200px;}
.left {width: 100px; height: 200px; margin-left: -100%;}
.right {width: 100px; height: 200px; margin-left: -100px;}
</style>
同样使用了 float 和 负值 margin,不同的是,并没有使用 relative 相对定位 而是增加了 dom 结构,增加了一个层级。确实解决了圣杯布局的缺陷。