盒模型
在CSS中,所有元素被“ 盒子 ”所包围,利用盒模型的基本原理来实现CSS准确布局,元素排列等处理
块级盒子(block box)与内联盒子(inline box)
CSS广泛使用的两种盒子,其在页面流和元素之间的关系表现为不同的行为:
对于定义为块级盒子(block)的元素会表现出以下行为:
- 盒子会在内联的方向上扩展并占据父容器在该方向上的所有可用空间,在绝大数情况下意味着盒子会和父容器一样宽(width :100%)
- 每个盒子之间都会进行换行处理
- width 和 height 属性可以发挥作用
- 内边距(padding), 外边距(margin) 和 边框(border) 会将其他元素从当前盒子周围“推开”
eg:<h1> , <p> , <div> , <section> , <header>等
对于定义为内联盒子(inline)的元素会表现出以下行为:
- 盒子不会产生换行
- width 和 height 属性将不起作用
- 垂直方向的内边距、外边距以及边框会被应用但是不会把其他处于 inline 状态的盒子推开
- 水平方向的内边距、外边距以及边框会被应用且会把其他处于 inline 状态的盒子推开
eg:<a> , <span> , <em> , <strong>
显示类型
通过对盒子设置display的属性值,来控制盒子的外部显示类型
外部显示类型与内部显示类型
外部显示类型:决定盒子是块级还是内联,即决定了盒子之间的布局方式
内部显示类型:决定了盒子内部的元素是如何布局的,默认情况是按照正常文档流布局,也可以通过设置display值为flex和grid来改变内部元素之间的布局方式
不同显示类型的例子
block:
图中段落里的<span> word </span>
被设置为display:block
因此其独占一行,宽度填满整个父元素
flex:
图中的列表被设置为display:block
,每个列表是一个块级元素 —— 像段落一样 —— 会充满整个容器的宽度并且换行
inline-flex与inline
图中的列表被设置为display:inline-flex
,使得在一些flex元素外创建一个内联框
最后设置两个段落为 display: inline
, inline flex 容器和两个段落在同一行上,而不是像块级元素一样换行
盒模型的组成部分
CSS组成一个盒模型需要以下几个部分:
- Content box: 这个区域是用来显示内容,大小可以通过设置 width 和 height 来控制
- Padding box: 包围在内容区域外部的空白区域; 大小通过 padding 相关属性设置
- Border box: 边框盒包裹内容和内边距,大小通过 border 相关属性设置
-
Margin box: 这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过 margin 相关属性设置
image.png
标准盒模型与替代盒模型
在标准模型中,如果你给盒设置 width 和 height,实际设置的是 content box。 padding 和 border 再加上设置的宽高一起决定整个盒子的大小
.box {
width: 350px;
height: 150px;
margin: 25px;
padding: 25px;
border: 5px solid black;
}
image.png
如果使用标准模型宽度 = 410px (350 + 25 + 25 + 5 + 5),高度 = 210px (150 + 25 + 25 + 5 + 5),padding 加 border 再加 content box
如果使用替代模型,一切都将变得简单很多,此时的 width 和 height 就是盒子可见的宽度与高度,无论怎么改变 padding 或 border 的值,都会通过压缩 conten box 的大小来保持 width 和 height 的值不变
image.png如需使用,只需要声明以下CSS样式:
.box {
box-sizing: border-box;
}
外边距
外边距是盒子周围一圈看不到的空间。它会把其他元素从盒子旁边推开。 外边距属性值可以为正也可以为负。设置负值会导致和其他内容重叠。无论使用标准模型还是替代模型,外边距总是在计算可见部分后额外添加
CSS:
.box {
margin-top: -40px;
margin-right: 30px;
margin-bottom: 40px;
margin-left: 4em;
}
html:
<div class="container">
<div class="box">Change my margin.</div>
</div>
结果如下:因为上外边距设置为负值,所以两个边框会重叠
image.png
外边距折叠
理解外边距的一个关键是外边距折叠的概念。如果你有两个外边距相接的元素,这些外边距将合并为一个外边距,即最大的单个外边距的大小
.one {
margin-bottom: 50px;
}
.two {
margin-top: 30px;
}
结果如下,中间间隔的部分为50px
image.png
内联盒子
如下图所示,对内联盒子设置 width 和 height 都不会生效,虽然margin,padding和border会生效,但不会改变与其它内联盒子的关系,因此其内边距和边框会与段落的其它元素重叠
image.png
display属性的inline-block
要避免上述情况,只需要将内联盒子的display值设置为inline-block即可
设置之后的效果为:
- 设置width和height属性会生效
- padding,margin 和 border 会推开其它元素
但因其保留有inline的特征,所以它不会跳转到新行
image.png浮动(float)
什么是浮动
float可以使得当前元素脱离正常文本流,并吸附到父元素的左边(left)或者右边(right)正常布局中位于该浮动元素之下的内容,此时会围绕着浮动元素进行排列
基本的常见用途在于图片与文字环绕排版以及首字母下沉:
image.png image.png
浮动规则
重点是这个,元素浮动具有一定的规则与限制
设置如下三个盒子(均以块级元素方式呈现):
<body>
<p class="box1">box1</p>
<p class="box2">box2</p>
<p class="box3">box3</p>
</body>
image.png
将box1设置为向右浮动:
.box1{
float: right;
}
image.png
因为box1脱离正常文档流,所以box2和box3会向上填补box1的空位,box1浮动到父元素(body)的最右边
设置box1向左浮动:
.box1{
float: left;
}
image.png
同理,box1脱离正常文档流,box2与box3向上填补box1的空位,此时box1浮动到父元素(body)的最左边,所以会覆盖掉box2(浮动元素在正常流文档的上方)
设置box2向左浮动:
.box2{
float: left;
}
image.png
可以看到box3因为box2脱离正常文档流而向上填充其空位,box2因为浮动到左边覆盖了box3,然而box1仍处于正常文档流中,并且在html文件中最先声明,所以box2只能在box1的下方进行浮动(即使box2设置为向右浮动也是一样)
设置box1、box2与box3都向左浮动:
.box1{
float: left;
}
.box2{
float: left;
}
.box3{
float: left;
}
image.png
可以看到三个盒子均向左浮动,直到碰到前一个浮动框的边缘为止(对于box1来说是碰到父元素的边缘),因此呈现如此的排列状况
如果当父元素太窄,无法包含三个盒子的宽度,则无法容纳的元素向下移动,直到有足够的空间使得其能向某个方向浮动,如下图所示:
image.png
如果浮动元素的高度不同,那么当它们向下移动时可能被其它浮动元素“卡住”
image.png
相关参考:
https://zhuanlan.zhihu.com/p/21286019?refer=miaomiaoji
https://www.jianshu.com/p/fe1052f1a8b6
浮动的规则先讨论到此
清除浮动
高度塌陷
在父元素container内设置一个盒子box1,此时没有设置浮动,box1会撑起父元素container的高度
<div class="container">
<p class="child">box1</p>
<p>未设置float,盒子会撑起父元素的高度</p>
</div>
image.png
如果此时设置box1浮动,因为其脱离了正常文档流,无法撑起盒子的高度,所以将发生高度塌陷:
image.png
为了解决这个问题,在此提供三种方法:
1. 添加额外标签
首先在父元素内添加空白内容的额外标签clearfix
<div class="container">
<p class="child">box1</p>
<p>现在可以清除浮动啦!</p>
<div class="clearfix"></div>
</div>
然后再CSS规则中添加以下内容:
.clearfix{
clear: both;
}
通过清除父元素内空白元素的浮动,使得父元素边框重新包含浮动内容
image.png
2. 父级元素添加overflow属性
直接在父元素内添加overflow属性:
.container{
border: black solid 2px;
overflow: auto;
}
同样可以清除浮动,结果如下:
image.png
3. after伪元素
html文档改为:
<div class="clearfix">
<p class="child">box1</p>
<p>现在可以清除浮动啦!</p>
</div>
在CSS规则里添加:
.clearfix:after{
content: "";
display: block;
height: 0;
visibility: hidden
clear:both;
}
- :after 在被选择元素之后插入一个元素,实际上是在.clearfix块级元素后面添加了一个空白元素(因为content属性没有添加任何内容)
- 因为添加了内容(即使是空白的,而且还将其display值设置为块级元素),也会出现高度,所以这里设置高度为0
-
visibility: hidden 可以将该元素设置为隐藏
image.png
网友评论