盒模型
简介
在CSS中,元素都是被一个个的盒子(box)包围着,理解这些盒子的基本原理,是我们使用CSS实现准确布局,处理元素排列的关键。在CSS中有 块级盒子
、内联盒子
两种,它们在页面流和元素之间的关系方面表现出不同的行为:
块级盒子
- 默认占据其父元素(容器)的整个水平空间,垂直空间等于其内容高度。
- 自动换行。
width
和height
属性可以生效。- 内边距(padding), 外边距(margin)和 边框(border)会将其他元素从当前盒子周围“推开”。
内联盒子
- 不换行
width
和height
属性不会生效。- 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于
inline
状态的盒子推开。 - 水平方向的内边距、外边距以及边框会被应用且会把其他处于
inline
状态的盒子推开。
什么是盒模型
完整的盒模型包含以下属性:margin(外边距)、border(边框)、padding(内边距)、content(内容),块级盒子具有完整盒模型属性,内联盒子支持部分属性。
- Content box:内容盒子,这个区域用来显示内容,可以通过
width
和height
设置大小。 - Padding box:内边距盒子,包围在内容盒子外的空白区域,可以通过
padding
相关属性设置。 - Border box:边框盒子,包裹内容和内边距的区域,可以通过
border
相关属性设置。 - Margin box:外边距盒子,这是最外面的区域,是元素与其它元素之间的空白区域,可以通过
margin
相关属性设置。
空间计算
将下面的示例代码用浏览器(谷歌、火狐、Edge)打开,我们可以使用浏览器自带的开发者工具来观测一个元素经过浏览器计算之后的盒模型各个部分的值。
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.parent {
width: 200px;
height: 200px;
background-color:antiquewhite;
}
.child {
width: 100px;
height: 100px;
background-color:beige;
margin: 10px 20px 30px 40px;
padding: 15px 25px 35px 45px;
border: 5px solid black;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">我是内容</div>
</div>
</body>
</html>
标准盒模型
在标准模型中,如果你给盒设置 width
和 height
,实际设置的是 Content box
。设置的宽和高加上Padding box
和 Border box
一起决定整个盒子的大小。
在标准模型中,上面示例中的div实际占用空间:宽180px(100+45+25+5+5),高160px(100+15+35+5+5),margin不计入实际大小,虽然它会影响盒子在页面所占空间,但是影响的是盒子的外部空间,盒子的范围到边框为止,不会延申到margin。
非标准盒模型
如果你感觉标准盒模型的计算太麻烦,那么CSS还提供了另一种替代盒模型。使用这个模型,设置的宽度就是可见宽度,内容宽度是设置的宽度减去 Padding box
和 Border box
部分。
浏览器默认使用标准模型,如果需要使用替代模型,可以通过设置属性值 box-sizing: border-box
实现。如果你经常使用替代模式或者希望所有元素都使用替代模式,那么可以设置 <html>
元素的 box-sizing
,并让所有元素继承该属性。
<style>
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
</style>
Internet Explorer 默认使用替代盒模型,并且在IE8之前没有可用的机制来切换,IE8+ 支持使用
box-sizing
进行切换。2021年5月19日微软官方发布消息,宣布服役了25年之久的Internet Explorer(IE) 浏览器将于2022年6月15日正式「退役」。IE的替代品Microsoft Edge使用了盒谷歌浏览器相同的chromium内核。随着前端技术的迭代浏览器的兼容难题有望得到解决。
测试盒模型
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.box {
border: 5px solid rebeccapurple;
background-color: lightgray;
padding: 40px;
margin: 40px;
width: 300px;
height: 150px;
}
.alternate {
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="box">标注盒模型.</div>
<div class="box alternate">替代盒模型</div>
</body>
</html>
- 相同的
width
、height
替代盒模型比标准模型要小,因为替代模型的width
、height
就是盒子大小,会向内压缩内容区域大小。
外边距重叠
外边距重叠是理解外边距的关键,如果两个元素的外边距相接,那么它们的外边距会合并为一个外边距, 合并规则是采用最大的那个外边距值。
在下面的例子中,我们创建两个div。上面div的 margin-bottom
为50px,下面div的margin-top
为30px。因为外边距折叠,所以两个div之间的实际外边距是50px,而不是两个外边距的总和。
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.container{
width: 500px;
height: 150px;
background-color: rgb(207,232,220);
border: 2px solid rgb(79,185,227);
}
.content{
border: 0px solid rebeccapurple;
background-color: lightgray;
}
.one {
margin-bottom: 50px;
height: 50px;
}
.two {
margin-top: 30px;
height: 50px;
}
</style>
</head>
<body>
<div class="container">
<div class="one content">我是div</div>
<div class="two content">我也是div</div>
</div>
</body>
</html>
- 运行上面的代码,我们可以看出两个content DIV的高度加上重叠后的外边距刚好等于container DIV的高度(150px=50px+50px+50px)。
- 由于两个
content DIV
没有设置内边距和边框,所以它们的实际高等于它们的内容高度。 - 可以通过设置
content DIV
的border
来观测位置变化,会发现two DIV
被顶下去了。
- 由于两个
有三种情况会形成外边距重叠
-
同一层相邻元素之间,相邻的两个元素之间的外边距重叠。
<html lang="en-US" prefix="og: https://ogp.me/ns#"> <head> <meta charset="utf-8"/> <meta property="og:locale" content="zh-CN"/> <title>盒模型</title> <style> p:nth-child(1){ margin-bottom: 13px; } p:nth-child(2){ margin-top: 87px; } </style> </head> <body> <p>下边界范围会...</p> <p>...会跟这个元素的上边界范围重叠。</p> </body> </html>
- 上述示例代码会发生外边距重叠。
-
嵌套元素,没有内容将父元素和后代元素分开。
<html lang="en-US" prefix="og: https://ogp.me/ns#"> <head> <meta charset="utf-8"/> <meta property="og:locale" content="zh-CN"/> <title>盒模型</title> <style> section { margin-top: 13px; margin-bottom: 13px; } header { margin-top: 80px; } footer { margin-bottom: 80px; } .anchor{ border: 1px solid rgb(79,185,227); padding: 0px; } </style> </head> <body> <div class="anchor">锚定点1</div> <section> <header>上边界与父容器重叠</header> <main></main> <footer>下边界与父容器重叠</footer> </section> <div class="anchor">锚定点2</div> </body> </html>
- 上述代码示例中,
header
与section
的上边距,footer
与section
的下边界发生了重叠,变成了section
与anchor
的边距。也就是这种情况的重叠部分溢出到父元素外面了。 - 可以测试下给
section
设置了边框或内边距的情况,会发现设置之后,重叠现象消失了,子元素的外边距变成了与父元素边框或内边距之间的距离。
- 上述代码示例中,
-
空的块级元素。
<html lang="en-US" prefix="og: https://ogp.me/ns#"> <head> <meta charset="utf-8"/> <meta property="og:locale" content="zh-CN"/> <title>盒模型</title> <style> p { margin: 0; } div { margin-top: 13px; margin-bottom: 87px; } </style> </head> <body> <p>上边界范围是 87 ...</p> <div></div> <p>... 上边界范围是 87</p> </body> </html>
div
是一个空的块级元素,她的上边距和下边距会发生折叠。- 当
div
设置了边框、内边距、高、最小高度、最大高度时这种折叠情况就不会发生。
外边距重叠的特殊说明
- 重叠是发生在块级元素之间,设置为浮动或粘性定位的元素不需要担心边界重叠问题。
- 上个段落中的重叠情况如果组合在一起,可能会发生更复杂的重叠情况。
- 如果所有参与折叠的外边距都为负,折叠后的外边距的值为最小的负边距的值。这一规则适用于相邻元素和嵌套元素。
- 如果参与折叠的外边距中包含负值,折叠后的外边距的值为最大的正边距与最小的负边距(即绝对值最大的负边距)的和,;也就是说如果有 -13px 8px 100px 叠在一起,边界范围的技术就是 100px -13px 的 87px。
元素边框
在上个章节我们知道了边框会影响盒子的大小,本小节我们对边框的样式设置做一些说明,例如分别设置上下左右四个边框的颜色、样式、大小。
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
div {
width: 200px;
height: 200px;
/* 上边界样式 */
border-top-width: 5px;
border-top-style: solid;
border-top-color: black;
/* 下边界样式 */
border-bottom-width: 5px;
border-bottom-style: dashed;
border-bottom-color: red;
/* 左边界样式 */
border-left-width: 5px;
border-left-style: double;
border-left-color:antiquewhite;
/* 右边界样式 */
border-right-width: 5px;
border-right-style: dotted;
border-right-color:aqua;
}
</style>
</head>
<body>
<div>我是个div</div>
</body>
</html>
- border-style:solid(实线)、double(双实线)、ridge(浮雕效果)、groove(雕刻效果)、dashed(虚线-方框)、dotted(圆点)、inset(陷入效果)、outset(突出效果)、none(不显示边框)、hidden(不显示边框)。
- 可以简写成
border-style
、border
。
元素背景
CSS属性 background
是一个简写属性,用于一次性定义背景的各种属性,包括background-color
、background-image
、background-repeat
、background-attachment
、background-position
、background-size
、background-clip
、background-origin
等等。
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.parent {
width: 300px;
height: 300px;
/*
* background-color :red
* background-image :url(/资源/椰树.png)
* background-repeat :no-repeat
* background-attachment :fixed
* background-position :10% 10%
* background-size :200px 100px;
* background-clip :padding-box
*/
background:red url(/资源/椰树.png) no-repeat fixed 10% 10%/50px 40px padding-box;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>
- 可以设置以下一个或多个属性,并且顺序也是可以调整的。
- 未设置的简写属性,会被设置为它们的初始值。
background-size
需要跟在background-position
之后并用/
分割。- 可以使用逗号设置多个背景层,background-color只能包含在最后一层。
属性介绍
background-repeat
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.border{
border: 15px dotted;
}
.parent {
width: 300px;
height: 300px;
background:red url(/资源/椰树.png);
/**
* repeat-x(x轴重复)
* repeat-y(y轴重复)
* repeat(x轴和y轴重复)
* space(均匀分布)
* round(缩放)
* no-repeat(不重复)
*/
background-repeat: no-repeat;
}
</style>
</head>
<body>
<div class="parent border">
</div>
</body>
</html>
background-attachment
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.grandpa{
width: 350px;
height: 200px;
overflow-y: scroll;
overflow-x: hidden;
}
.parent {
width: 300px;
height: 300px;
border: 15px dotted;
overflow-y: scroll;
overflow-x: hidden;
background:red url(/资源/椰树.png);
background-repeat: no-repeat;
/**
* fixed:grandpa和parent滚动条滚动时图片位置不变。
* scroll:parent滚动条滚动时位置不变,grandpa滚动时滚动。
* local:grandpa和parent滚动时,位置跟随滚动。
*/
background-attachment: local;
}
.child {
width: 300px;
height: 600px;
}
</style>
</head>
<body>
<div class="grandpa">
<div class="parent">
<div class="child"></div>
</div>
</div>
</body>
</html>
background-origin
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.border{
width: 300px;
height: 300px;
border: 15px dotted;
padding: 50px;
}
.parent {
background:red url(/资源/椰树.png);
background-repeat: no-repeat;
/**
* 设置背景在内容区域中心(以内容区域为参照距离左边界上边界一半的区域)
* border-box:背景图片的摆放以 border 区域为参考
* padding-box:背景图片的摆放以 padding 区域为参考
* content-box:背景图片的摆放以 content 区域为参考
*/
background-origin: content-box;
/**
* 单个值:center、top、left、bottom、right
* 两个值:一个定义 x 坐标,另一个定义 y 坐标。
* 默认值: left top(0% 0%)
*/
background-position: 50% 50%;
}
</style>
</head>
<body>
<div class="parent border">
</div>
</body>
</html>
- 当 background-attachment 属性值是 fixed 的时候,background-origin属性会被忽略。
- background-position属性相对于background-origin设置的属性值来进行定位。
background-clip
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.border{
border: 15px dotted;
}
.parent {
width: 300px;
height: 300px;
background:red url(/资源/椰树.png) repeat fixed 10% 10%/50px 40px border-box border-box;
/**
* content-box:延申至内容区域,背景区域最小
* padding-box:延申至内边距
* border-box:延申至边框,背景区域最大
*/
background-clip: border-box;
}
</style>
</head>
<body>
<div class="parent border">
</div>
</body>
</html>
- 设置元素的背景(图片或颜色)是否延申到边框、内边距、内容盒子下面。
透明背景
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.parent {
width: 300px;
height: 300px;
border: 15px dotted;
background:red url(/资源/椰树.png);
}
.child {
width: 150px;
height: 150px;
background: yellowgreen;
opacity: 0.5;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>
- opacity 属性指定了一个元素的不透明度,取值范围时0~1从小到大效果依次从完全透明到完全不透明,当值不在合理范围时会取一个接近的范围。
- opacity属性会将一个元素包括它的子孙元素当成一个整体看待,即使这个值没有被子元素继承。因此父元素和它的子元素的透明度是一样的,哪怕父元素和资源的opacity 属性值不同。
滚动条
<!doctype html>
<html lang="en-US" prefix="og: https://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta property="og:locale" content="zh-CN"/>
<title>盒模型</title>
<style>
.child {
border: 1px red solid;
margin: 10px;
background: url(/资源/椰树.png);
background-repeat: no-repeat;
}
.parent {
width: 400px;
height: 450px;
border: 2px black solid;
/**
* visible :不显示滚动条,超出部分直接渲染在父元素外部。
* hidden :不显示滚动条,超出部分被裁剪隐藏进父元素,可以通过scrollLeft属性或 scrollTo()方法滚动(父元素仍然是一个滚动容器)
* clip :与hidden类似,不同的是clip禁止通过编程的方式进行滚动。
* scroll :强制显示滚动条,不管内容是否超过高度。
*/
overflow: scroll;
}
/*
* 通过伪类的方式调整滚动条样式
*/
::-webkit-scrollbar,::-webkit-scrollbar-track {
background-color: transparent;
}
::-webkit-scrollbar:horizontal {
height: 8px
}
::-webkit-scrollbar:vertical {
width: 8px
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: red;
}
</style>
<script type="text/javascript">
/**
* 父容器滚动条设置为hidden时滚动位置
* document.getElementsByClassName('parent')[0].scrollTo(0,500)
*/
</script>
</head>
<body>
<div class="parent">
<div class="child">
<p style="height: 540px; width: 100%;"></p>
<p style="margin-left: 120px;">你能看到我吗?</p>
</div>
</div>
</body>
</html>