盒模型的box-sizing
属性:
在网页设计开发中,盒模型是掌握布局和格式化网页内容的最先需要了解的基本概念。
而每个HTML元素都可以被视为一个矩形的盒子(盒模型),一般由4个部分组成,即:内容区域(content)、内边距(padding)、边框(border)和外边距(margin)。这些部分共同决定了元素在页面上的尺寸和空间分布,并且每个盒子都有其单独的样式。
但是盒模型却有两种不同的box-sizing
(计算方式):标准盒模型与IE盒模型(也称为怪异盒模型)。
举这两种模型最简单的例子:
创建三个简单的盒模型,并且设置其基本的宽高、背景颜色与边跨颜色。但是第一个盒子不指定其box-sizing
属性(计算方式),而另外两个分别指定为标准盒模型 (content-box
)与IE盒模型 (border-box
),不妨来看看有何区别。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Box</title>
<style>
*{ /* 通用选择器(*) */
margin: 0;
padding: 0;
}
.box1, .box2, .box3 {
width: 100px;
height: 100px;
padding: 10px;
border: 1px solid red;
background-color: green;
}
.box2 {
/* IE盒模型 */
box-sizing: border-box;
}
.box3 {
/* 标准盒模型 */
box-sizing: content-box;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>
很明显,box1与box3的大小是一样的,而box2明显较小,这也就体现两种计算方式的差距。
- 标准盒模型:在常态下是默认值,设置的
width
和height
仅应用于内容区域,也就是box1和box3的content
为100px(显示的总宽还需要包含额外设置的padding,border,margin) - IE盒模型: 设置的
width
和height
包含了padding,border,margin部分,所以图中box2的content
为100px (w/h) - 10px * 2 (padding) - 1px * 2 (border) = 78px
display
属性:
默认状态下是由标签来决定元素的类型与其在页面上的布局,但是有没有一个属性能直接改变其标签类型呢?有的兄弟,有的!那就是display
属性了。
举两个最简单的例子:
比较常用的两种元素类型就是块级元素 (block)与行内元素(inline)了。
- 块级元素:默认占据父容器的整个宽度,每个块级元素从上到下独占一行,可以修改宽度、高度、内边距和边框等属性。
- 行内元素:只占据内容所需的宽度,每个行内元素从左到右排列,不能直接设置宽高。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
div {
width: 100px;
height: 100px;
border: 1px solid red;
padding: 10px 20px;
/* 将其转换为行内元素 */
display: inline;
}
span {
width: 100px;
height: 100px;
/* 将其转换为块级元素 */
display: block;
background-color: green;
}
</style>
</head>
<body>
<div>123</div>
<span>11</span><span>222</span>
</body>
</html>
由于元素类型的转换,也就导致了虽然为<div>
容器设置了宽高,但是其只占据了其内容123
所需大小。而由于文档流导致<span>
容器紧跟在<div>
容器后,但是<div>
的padding
和border
仍然会对周围环境造成影响,所以产生了容器交集。
BFC(块级格式化上下文)详解:
什么是BFC?
BFC(Block Formatting Context,块级格式化上下文)是 CSS 中的一个独立渲染区域 ,其不受外界影响,同样也不影响外界,并且决定了如何布局块级盒子以及它们之间的相互作用。
HTML 和 Body 的 BFC
- HTML 元素:HTML元素作为根元素,构成了整个页面的基础布局环境,所以其是页面的第一个也是最顶级的 BFC。而其他元素是镶嵌在根元素内,并且受到BFC影响(Body元素也包括在内)
- Body 元素 :其在默认情况下是包含在HTML元素内的,但是通过一些特定的CSS属性(例如:
overflow
、float
)来创建自己的BFC,并且独立于HTML元素布局。
触发新的 BFC
这里举例以下几种情况会创建新的 BFC:
position
值为absolute
或fixed
。display
值为inline-block
,table-cell
,table-caption
,flex
,inline-flex
,grid
,inline-grid
。overflow
值不是visible
(如hidden
,auto
,scroll
)。
BFC 的特性
- 在一个 BFC 内,块级元素会从上到下依次排列,并且默认宽度为 100%。
- 同一个 BFC 中盒子的垂直方向的距离由
margin
决定,相邻盒子的margin
会发生重叠(塌陷),较大的margin
值生效。 - 每个元素的
margin-left
与包含块的border-left
相接触,即使存在浮动也是如此。 - BFC 是一个独立的渲染区域,其内部布局不会受到外部元素的影响。
- 当计算 BFC 的高度时,浮动元素的高度也会被考虑在内,并且阻止其他元素与浮动元素重叠。
BFC 特性有何用处
解决外边距重叠:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BFC</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 200px;
height: 200px;
background-color: lightblue;
border: 1px solid #000;
}
.box1 {
margin-bottom: 50px;
}
.box2 {
margin-top: 30px;
}
</style>
</head>
<body>
<div class="box box1">Box1</div>
<div>
<div class="box box2" >Box2</div>
</div>
</body>
</html>
如果没有创建新的 BFC,.box1
和 .box2
之间的实际间距将是 50px(较大的外边距值),而不是 80px(50px + 30px),如图:
修改:
但是对.box2
外部的div
进行设置就可以解决这个问题。
html
<div style="overflow:hidden;">
<div class="box box2" >Box2</div>
</div>
由于 .box2
被包裹在一个设置了 overflow: hidden;
的父元素中,这创建了一个新的 BFC,阻止了外边距重叠。
清除float而导致的高度坍缩:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Float Example</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
border: 2px solid black;
padding: 10px;
width: 300px;
/* overflow: hidden; */
}
.float-left {
float: left;
width: 100px;
height: 100px;
background-color: lightblue;
margin: 10px;
}
</style>
</head>
<body>
<div class="container">
<div class="float-left">浮动元素</div>
</div>
</body>
</html>
上述代码中设置了<float-left>
转换为浮动元素,而浮动元素会脱离正常的文档流,从而导致了父元素高度坍缩。但是如果在<container>
中添加了overflow: hidden
(清除浮动),父元素计算高度就会包括浮动元素。如图:
解决浮动元素带来的布局问题:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
border: 2px solid black;
padding: 10px;
}
.float-box {
float: left;
width: 150px;
height: 100px;
background-color: lightblue;
margin: 10px;
}
.bfc-box {
width: 300px;
height: 100px;
background-color: lightgreen;
/* overflow: auto; */
}
</style>
</head>
<body>
<div class="container">
<div class="float-box">这是一个左浮动的盒子</div>
<div class="bfc-box">这是一个创建了 BFC 的盒子</div>
</div>
</body>
</html>
由于浮动元素脱离了原本的文档流,所以会导致bfc-box
和float-box
,发生重叠,样式如图:
而为了使浮动元素不再影响父元素中的其他子元素,就可以为其他子元素添加overflow: auto
等使其创建自身的 BFC,这样就使其形成一个独立的渲染区域,不会与浮动元素相互干扰。例如在上述代码中重新启用overflow: auto
。如图:
注:如果
bfc-box
位于float-box
下方也是正常的,因为当页面宽度不足以支撑这两个盒子水平放置时,由于float-box
的浮动特性导致bfc-box
会根据可用空间调节自身位置。
当然如果再在bfc-box
中创建新的块级元素或行内元素都不会被float-box
影响。
格式上下文(Formatting Context)
常见的格式上下文包括:
- BFC(块级格式化上下文)
- IFC(行内格式化上下文)
- FFC(弹性格式化上下文)
- GFC(网格格式化上下文)
弹性布局和网格布局
弹性布局(Flexbox)
弹性布局通过 display: flex;
或 display: inline-flex;
创建了一个新的 BFC(准确地说是 FFC,即 Flex Formatting Context)。这意味着:
- FFC(Flex Formatting Context) :在弹性容器中,子元素按照
flex-direction
的定义进行排列(默认是row
,即从左到右)。 - 独立渲染区域:弹性容器中的布局完全独立于外部的 BFC,不会受到外界元素的影响。
举个例子:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 100px;
height: 100px;
background-color: green;
}
.box:nth-child(odd) {
background-color: red;
}
</style>
</head>
<body>
<div class="flex">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
</body>
</html>
而当在<style>
中添加对flex
的编辑后
css
.flex {
display: flex;
}
.flex
容器就被设置为 Flex 容器,使它的直接子元素(.box
元素)成为 Flex 项目。而在默认情况下,Flex 项目的排列方向是由 flex-direction
属性决定的,默认值为 row
,这意味着子元素会在水平方向上从左到右排列。即:
网格布局(Grid)
网格布局通过 display: grid;
或 display: inline-grid;
创建了一个新的 GFC(Grid Formatting Context)。类似于弹性布局,网格布局也是一个独立的渲染区域。
css
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 三列等宽 */
gap: 10px; /* 单元格之间的间隔 */
padding: 10px; /* 网格容器的内边距 */
}
结语:
本文用于分享学习,如有错误或需要补充的麻烦在评论区补充,感谢。