盒模型可是 CSS 的重中之重,不理解这个,你的页面可能就会在视觉上出现各种“百思不得其解”现象,这篇文章可以带你了解什么是盒模型、盒模型的基本应用场景
盒模型
盒模型(box model)定义了页面上元素的表现形式,每个元素都将以“盒子”的形式显示在页面上。
盒模型分为 Block Box (块级元素)和 Inline Box(行内元素);一个盒子,从外到里包括了:margin(外边距)、border(边框)、padding(内边距)、content(内容)
标准盒模型
box-sizing属性定义了浏览器如何计算一个元素的总宽度和总高度。
在标准盒模型(box-sizing:content-box)中,如果给盒子设置 width 和 height,实际设置的是 content box 的高度和宽度,也就是对一个元素所设置的 width 与 height 只会应用到这个元素的内容区(content 部分)
如果这个元素有任何的 border 或 padding ,渲染到 HTML 页面上时,盒子的 width 和 height 除了要包含 content,还要额外加上你设置的 margin 、padding 或 border。
例如,当你定义了一个宽度与父容器相同的子元素,运行后你会发现子元素看上去溢出了父容器——父容器装不下子元素了。这就产生了一个问题——盒子的实际大小超过了你设定的大小:
#container{
width: 300px;
border: 5px solid rgb(100, 100, 100);
}
#container div{
width: 300px;
height:90px;
border: 10px solid rgb(86, 134, 189);
font-size: 24px;
}
<div id="container">
<div id="b1">子元素</div>
<div id="b2">子元素</div>
<div id="b3">子元素</div>
</div>
IE 盒模型
像上面子元素溢出父容器的情况,通过设置box-sizing:border-box就能解决,这表示启用 IE 盒模型。
在 IE 盒模型中,盒子的大小为 content + border + padding,这样,你设置的盒子为 100px,即使你再加上 5px 的 border 和 10px 的 padding,盒子的实际大小就会是你原本设置的 100px,这样其实更符合直觉,且不需要手动计算盒子的大小
我们让父容器的宽度为 300px ,边框为 5px ,然后启用 IE 盒模型:
#container{
width: 300px;
box-sizing: border-box;
border: 5px solid rgb(100, 100, 100);
}
#container div{
width: 290px; // 这里要减去两边的父容器的 border
box-sizing: border-box;
height:90px;
border: 10px solid rgb(86, 134, 189);
font-size: 24px;
}
块级盒子
首先,我们来定义一个父元素和三个子元素:
<style>
#container{
border: 5px solid rgb(100, 100, 100);
padding: 30px;
}
#container div{
height: 80px;
border: 10px solid rgb(86, 134, 189);
font-size: 22px;
}
</style>
<body>
<div id="container">
<div id="b1">块级盒子 1</div>
<div id="b2">块级盒子 2</div>
<div id="b3">块级盒子 3</div>
</div>
</body>
块级元素的特性如下:
- 元素的宽度会铺满父容器
- 元素会自动换行,每个元素独占一行
width和height属性生效padding、margin、border会将其他元素从当前元素周围“推开”
常见的块级元素有:<div>、<p>、<ul>、<ol>、<h1> ~ <h6>。
行内盒子
<style>
#container{
height: 300px;
border: 5px solid rgb(100, 100, 100);
padding: 30px;
}
#container div{
display: inline;
border: 10px solid rgb(86, 134, 189);
font-size: 22px;
}
</style>
<body>
<h1>行内元素</h1>
<div id="container">
<div id="b1">行内盒子 1</div>
<div id="b2">行内盒子 2</div>
<div id="b3">行内盒子 3</div>
</div>
</body>
行内元素的特性如下:
- 元素不会自动换行,除非溢出父容器才会换到下一行
width和height属性不生效- 垂直方向的
padding 、margin、border会生效,但是不会把其他处于inline-block状态的元素推开 - 水平方向的
padding 、margin、border会生效,且会把其他处于inline-block状态的元素推开。
常见的行内元素有:<a> 、<span>、 <i>、<b> 。
元素显示类型
display属性定义了元素在文档流中显示的性质,默认情况下,div 元素:display:block,span元素:display:inline。
display 属性有以下可选值:
block:块级元素 ,会独占一行,默认带有换行符inline:行内元素,不会独占一行,如果一行排不下才会换行inline-block:行内块元素,会以 inline 的方式排列在父容器中,但同时具有块级元素的特点,例如可以设置width和height属性并生效none:设置元素为不显示,且元素也不会存在于DOM节点中flex:设置元素内部的布局为 flex 布局grid:设置元素内部的布局为 grid 布局
外边距折叠
外边距折叠在 CSS 给元素布局的过程中非常常见,有必要弄清楚。首先,外边距折叠指的是:盒子的上外边距(margin-top)和下外边距(margin-bottom)有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个)
下面的情况会形成外边距重叠:
- 相邻的两个同层级元素
<style>
.container {
border: 3px solid grey;
}
.top {
background: red;
width: 500px;
height: 100px;
margin: 20px; // 较小外边距
border: 2px solid black;
}
.bottom {
background: green;
margin: 50px; // 较大外边距
width: 500px;
height: 100px;
border: 2px solid black;
}
</style>
<body>
<div class='container'>
<div class='top'>盒子一</div>
<div class='bottom'>盒子二</div>
</div>
</body>
- 没有内容将父元素和后代元素分开时
如果一个父元素,没有border、padding、行内内容,也没有开启 BFC 来分开一个块级元素的上边距margin-top 与其后代块级元素的上边距margin-top;或者,没有border、padding、行内内容、height,min-height、max-height 来分开一个块级元素的下边距margin-bottom与其后代块元素的下边距margin-bottom,就会出现父元素和后代块元素外边框重叠,重叠部分最终会溢出到父级块元素外面
<style>
.container {
background-color: grey;
}
.top {
background: red;
width: 500px;
height: 100px;
margin: 50px;
border: 2px solid black;
}
.bottom {
background: green;
margin: 50px;
width: 500px;
height: 100px;
border: 2px solid black;
}
</style>
<body>
<div class='container'>
<div class='top'>盒子一</div>
<div class='bottom'>盒子二</div>
</div>
</body>
BFC
BFC 指的是块级格式化上下文(Block Formatting Context )。BFC 是 CSS2.1 规范中的一个概念,它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性 。通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
应用场景
高度塌陷
通常情况下,如果一个元素浮动,那么这个元素的父容器的高度,就不会再包括它本身的高度了,也就是高度塌陷
<style>
body{
padding: 50px;
}
.left {
background: red;
opacity: 0.7;
border: 3px solid black;
width: 200px;
height: 200px;
float: left;
}
.right {
background: green;
opacity: 0.7;
border: 3px solid black;
width: 400px;
height: 100px;
}
/* 父元素 */
.container {
background: grey;
padding: 20px;
}
</style>
<body>
<div class='container'>
<div class='left'> </div>
<div class='right'> </div>
</div>
</body>
可以看到,父元素的高度并没有将红色子元素的高度计算在内,因为红色子元素浮动了。父元素可以通过触发 BFC 来解决高度塌陷的问题:
/* 父元素 */
.container {
background: grey;
padding: 20px;
overflow: hidden
}
元素重叠
上面的例子中,红色子元素与绿色子元素发生了重叠,这是因为红色子元素float: left的原因,现在,我们需要避免绿色子元素发生重叠的话,可以触发它的 BFC:
.right {
background: green;
opacity: 0.7;
border: 3px solid black;
width: 400px;
height: 100px;
overflow: hidden; // 触发 BFC
}
外边距折叠
默认情况下,两个相邻元素的上下边距的值不是它们各自边距值的合,而是两者之间的最大值。
<style>
body{
padding: 50px;
}
.container {
background: grey;
}
.top {
background: red;
height: 100px;
margin: 50px;
border: 2px solid black;
}
.bottom {
background: green;
margin: 50px;
height: 100px;
border: 2px solid black;
}
</style>
<body>
<div class='container'>
<div class='top'> </div>
<div class='bottom'> </div>
</div>
</body>
可以看到,两个子元素的margin都是 50px,但是红色元素下边与绿色元素的上边的间隔距离,很明显不是直觉上认为的 50px+50px = 100px,这就是发生了外边距折叠。可以通过触发 BFC 来解决这个问题,我们需要给其中一个子元素再套上一个父元素,然后在这个父元素上面开启 BFC
<style>
body {
padding: 50px;
}
.container {
background: grey;
overflow: hidden;
}
.top {
background: red;
height: 100px;
margin: 50px;
border: 2px solid black;
}
.bottom {
background: green;
margin: 50px;
height: 100px;
border: 2px solid black;
}
.bfc {
overflow: hidden;
}
</style>
<div class='container'>
<div class="bfc">
<div class='top'> </div>
</div>
<div class='bottom'> </div>
</div>
现在上下两个元素之间的边距就是它们的合啦
触发BFC
只要元素满足下面任一条件即可触发 BFC 特性:
- 浮动元素:
float属性除none以外的值 - 绝对定位元素:
position属性为absolute或fixed - 元素的
display属性为:inline-block、table-cell、flex、inline-flex、table-caption overflow属性除了visible以外的值(hidden、auto、scroll)
元素层叠
z-index用来设置元素在z轴上面的堆叠顺序。z-index必须和定位元素position:absollute|relative|fixed一起使用,否则无效。
通常情况下,z-index的数值越高,层级就越高,但是也有特殊情况:
- 相同 z-index:
- 如果两个元素都没有定位且发生位置重合现象,或者两个元素已定位且
z-index相同发生且位置重合现象,那么按文档流顺序,后面的覆盖前面的。 - 如果两个元素都没有设置
z-index,使用默认值;如果一个已定位,一个没有定位,那么定位元素覆盖未定位元素。
- 如果两个元素都没有定位且发生位置重合现象,或者两个元素已定位且
- 父子 z-index:
- 如果父元素
z-index有效,那么子元素无论是否设置z-index都和父元素一致,在父元素上方 - 如果父元素
z-index失效(未定位或者使用默认值),那么已定位子元素的z-index设置生效
- 如果父元素
参考链接: