margin塌陷是css中比较重要的知识点,在业务开发中常常会带来意想不到的问题,为了彻底解决这些问题,css2中引入了bfc的概念。本文不深入bfc概念,只介绍bfc及其他解决body元素margin塌陷的方案
body元素的margin塌陷
在html页面中,html,body元素的默认高度height:auto,这是自适应高度,取决于子元素高度,常常会造成高度塌陷,所以我们常常会将页面的html,body标签设置为height:100%,代码如下所示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="app">
body子元素没有margin
</div>
<style>
html,body{
height:100%;
margin:0;
}
.app{
height:100px;
background-color: lightcoral;
}
</style>
</body>
</html>
当我们将body中第一个子元素设置margin时,就造成margin塌陷,则页面出现了滚动条,具体原因是:我们对子元素设置margin,是希望子元素和body之间有间隔,但如果body元素塌陷,则子元素的margin就顶上去了,整个页面的高度就是body元素的100%+子元素的margin,这个页面高度大于视图高度,所以出现了滚动条,显然这不是我们期望的结果。代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="app">
body元素的margin塌陷
</div>
<style>
html,body{
height:100%;
margin:0;
}
.app{
height:100px;
background-color: lightcoral;
margin:20px;
}
</style>
</body>
</html>
css1中margin塌陷解决方案-padding/border
在bfc出现之前,对于margin塌陷有一些常见的解决方案,比如body元素设置padding/border,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="app">
margin塌陷css1解决方案:padding
</div>
<style>
html, body {
height: 100%;
margin: 0;
}
.app {
height: 100px;
background-color: lightcoral;
margin: 20px;
}
body {
padding: 1px;
}
</style>
</body>
</html>
这种解决思路会引入1px的高度,在部分场景下可以解决margin塌陷问题,但在本场景下,1px的偏差也会导致滚动条的出现。所以在css1中,margin塌陷问题并不能得到根本的解决,因此才有必要在css2中引入bfc的概念,彻底解决此类问题。
css2中margin塌陷解决方案-bfc
css2中引入bfc的概念,即为某个元素创建一个独立的渲染区域。在本例中,为body创建bfc,则子元素的margin不会影响到body外区域,所以页面高度就是body的height:100%,而不会多出其他部分,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="app">
margin塌陷css2解决方案:bfc
</div>
<style>
html, body {
height: 100%;
margin: 0;
}
.app {
height: 100px;
background-color: lightcoral;
margin: 20px;
}
html,body {
overflow:auto;
}
</style>
</body>
</html>
css3中margin塌陷解决方案-盒模型
虽然css2中的bfc可以很好的解决margin塌陷的问题,但随着css3的发布,也可以找到另一种完美解决方案。
回顾css1的解决方案,为什么引入padding:1px会导致滚动条的出现?因为html中默认的盒模型为标准模型,即body的height只是content的高度,而不包括padding/border高度,所以padding就是在页面100%高度之外加1px,导致超出视图高度,则出现滚动条。
如果我们能够将padding添加的1px包括在body的height中,则页面高度就不会超过视图高度,幸运的是css3中的box-sizing属性给我们提供了解决思路,通过设置box-sizing:border-box,则将标准盒模型转化成IE盒模型,body高度就包括了padding/border的值,完美解决我们的问题,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="app">
margin塌陷css3解决方案:box-sizing
</div>
<style>
html, body {
height: 100%;
margin: 0;
}
.app {
height: 100px;
background-color: lightcoral;
margin: 20px;
}
body {
padding: 1px;
box-sizing: border-box;
}
</style>
</body>
</html>
总结
css1中对于margin塌陷问题,没有彻底的解决方案,因此在css2中引入bfc概念,通过创建独立渲染区域完美解决。在css3中,box-sizing属性可以切换盒模型,将padding/border的1px偏差引入到body的height内,也可以完美解决。