目录
margin: auto 0 为什么不能用于块级元素垂直居中
CSS将所有的元素都看成一个盒子,盒子组成包括:
CSS有两类盒子,分别是:
二者区别在于:

所以border-box盒子内容区的
宽度为:
content-width = width - padding-left - padding-right - border-left - border-right
高度为:
content-height = height - padding-top - padding-bottom - border-top - border-bottom
padding指的是元素的内边距,所谓内边距,即元素盒子的content内容区 和 border边框线之间的距离。

padding有四个方向上的距离,分别是padding-left,padding-right,padding-top,padding-bottom,我们可以分别设置它们

也可以使用复合写法:padding:上 右 下 左

块级元素、行内块元素,行内元素都支持四个方向上的padding设置。

对于content-box而言,padding会撑开盒子 ,内容区不变
对于border-box而言,padding不会撑开盒子,但相应的内容区变小

对于多组,文字内容长度不定的,盒子而言,我们可以将其定义为content-box,利用padding来撑开盒子,而不是找出最大宽度
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Documenttitle>
- <style>
- ul {
- list-style: none;
- border-bottom: 1px solid #000;
- cursor: pointer;
- }
-
- li {
- display: inline-block;
- padding: 10px;
- }
-
- li:hover {
- background-color: #eee;
- }
- style>
- head>
- <body>
- <ul>
- <li>首页li>
- <li>手机帅哥网li>
- <li>移动客户端li>
- <li>博客li>
- <li>微博li>
- <li>关注我li>
- ul>
- body>
- html>

border指的是元素的边框线,border是盒子模型中margin和padding的分界线。
border分别有四个方向的距离:border-left、border-right 、border-top 、border-bottom
我们可以分别设置它们

也可以使用复合写法

只是此时只能设置上右下左边框线等宽,因为要兼顾边框线样式和颜色属性设置。
块级元素、行内块元素、行内元素都支持设置四个方向的border。
对于content-box而言,border会撑开盒子
对于border-box而言,border不会撑开盒子

上下左右四个border其实互相之间由交叉区域,就是四个直角的区域,为了保证公平分配,哪个border越宽,则在直角区域占比越大,如上图。
所以理论上来说,

此时我们只要让某些border颜色变为透明,即可得到一些不同方向的三角


当然我们也可以生成一些不等边三角形


但是这种效果,我们发现其斜边不是顺滑的,此时我们可以使用另一种方式

三角的应用主要有如下:
提示框

- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Documenttitle>
- <style>
- .main {
- width: 100px;
- height: 30px;
- background-color: black;
-
- text-align: center;
- line-height: 30px;
- color: white;
- }
-
- .triangle {
- width: 0;
- height: 0;
- border-width: 5px;
- border-color: black transparent transparent transparent;
- border-style: solid;
- margin-left: 45px;
- }
- style>
- head>
- <body>
- <div class="main">提示框div>
- <div class="triangle">
- div>
- body>
- html>
对抗三角

- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Documenttitle>
- <style>
- .container {
- width: 180px;
- height: 30px;
- border: 1px solid red;
- }
-
- .left,.right,.triangle {
- display: inline-block;
- vertical-align: top;
- text-align: center;
- line-height: 30px;
- }
-
- .left,.right {
- width: 80px;
- height: 30px;
- }
-
- .left {
- background-color: red;
- color: white;
- }
-
- .right {
- color: gray;
- }
-
- .triangle {
- width: 0;
- height: 0;
- border-width: 30px 20px 0 0;
- border-style: solid;
- border-color: red transparent transparent transparent;
- }
- style>
- head>
- <body>
- <div class="container">
- <div class="left"><strong>$9.99strong>div><div class="triangle">div><div class="right"><del>$39.9del>div>
- div>
- body>
- html>
margin是盒子模型中的外边距,所谓外边距,即相对于自身盒子border的距离
margin也分为四个方向上的距离:margin-left、margin-right、margin-top、margin-bottom
我们可以分别设置它们,也可以使用复合写法:margin: 上 右 下 左
我们知道块级元素会独占一行,无论块级元素的宽度是否能够独占一行

本质上,块级元素无法占据的行的剩余宽度部分,都是被块级元素的margin占据的。
所以如果我们想要让块级元素水平居中的话,只要让块级元素的左右margin平均占据行的剩余宽度即可。
如果行宽值确定,则可以margin-left = margin-right = (行宽度 - 块级元素自身宽度) / 2
如果行宽值不确定,则可以让margin-left = margin-right = auto,让他们自动平分 (行宽度 - 块级元素自身宽度)

当然,auto也适用于行宽确定的情况。

margin还支持复合写法:

因为块级元素的特性:只有独占一行,没有独占一列的说法。
为了保证块级元素能独占一行,块级元素的margin-left、margin-right会占据行的剩余宽度。
而块级元素不会独占一列,所以对于块级元素来说,在垂直方向上不存在剩余高度的概念,所以也就不会有margin-top、margin-bottom占据剩余高度的情况。
所以margin: auto 0 无法使块级元素垂直居中。


可以发现,相邻、嵌套盒子之间水平方向的margin是互斥的,非侵入的。
相邻块级元素垂直方向margin合并现象

如果相邻的块级元素A、B中,上面的A块级元素有margin-bottom,下面的B块级元素有margin-top,则两个块级元素的垂直margin间距并非 A.margin-bottom + B.margin-top的和,而是取max(A.margin-bottom,B.margin-top)最大值。
嵌套块级元素垂直方向margin合并现象

当父子块级元素都有margin-top时,则子块级元素的margin-top会塌陷到父级元素外部
而父块级元素会以父子中最大的margin-top作为自身外间距。
可以总结出,相邻、嵌套的元素间垂直方向margin是侵入性的,即垂直方向margin会发生合并,导致margin塌陷问题。
相邻块级元素垂直方向margin合并问题 解决方案:
尽量只给一个块级元素指定垂直方向margin,不要出现相邻块级元素分别指定margin-bottom,margin-top的情况。

嵌套块级元素垂直方向margin合并问题 解决方案:
父级元素添加border-top

这种方案会增加无意义的边框线,不是最优解,只适合父级有边框线场景。
父级元素添加padding-top

这种方案会增加无意义的内边距,不是最优解,只适合父级有内边距的情况。
将父级元素变为BFC容器,如给父级元素设置overflow: auto/hidden/scroll

这种方案目前来看兼容性较好
BFC,即Block formatting context 块级格式化上下文。
BFC可以理解为一种特殊的渲染模式。
BFC容器的内部会形成独立的渲染区域,保护容器内部元素的渲染不会影响外界。
而一个元素转为BFC渲染模式的方式有如下:
由于BFC容器内部元素的渲染不会影响外界,所以BFC可以解决:
我们经常需要渲染列表,并且给列表加上border边框,此时就有可能出现相邻border堆积的情况,造成视觉上,border变粗的现象。

此时我们可以让第一个之后的列表项都margin-top:负值

此时就会发生后面列表项的border-top压住上面一个列表项border-bottom的动作,解决border堆积变粗问题。
margin-xxx负值表现为:元素向xxx方向正向移动
margin负值还有一个妙用就是结合浮动,实现圣杯布局、双飞翼布局,这个妙用我们在下一个章节中介绍。