盒子模型
CSS 中的所有内容都包含在一个框中,理解这些框是能够使用 CSS 创建更复杂的布局或将项目与其他项目对齐的关键。在本课中,我们将了解 CSS 盒子模型。您将了解其工作原理以及相关的术语。
块级盒子和内联盒子
在 CSS 中,我们有几种类型的盒子,通常分为块级盒子和内联盒子。类型指的是盒子在页面流中以及相对于页面上其他盒子的行为方式。盒子具有内部显示类型和外部显示类型。
通常,您可以使用display
属性设置显示类型的各种值,该属性可以具有各种值。
外部显示类型
内部显示类型
盒子还具有内部显示类型,它决定该盒子内部的元素如何排列。
块级和内联布局是网页上内容默认的行为方式。默认情况下,如果没有其他指令,盒子内的元素也会以正常流方式排列,并表现为块级或内联盒子。
例如,您可以通过设置display: flex;
来更改内部显示类型。该元素将继续使用外部显示类型block
,但这会将内部显示类型更改为flex
。该盒子的所有直接子元素将成为弹性项目,并根据Flexbox规范进行操作。
当您继续学习有关 CSS 布局的更多详细信息时,您将遇到flex
,以及盒子的各种其他内部值,例如grid
。
注意:要了解更多关于 display 的值以及盒子在块级和内联布局中的工作方式,请查看 MDN 指南块级和内联布局。
不同显示类型的示例
以下示例包含三个不同的 HTML 元素,它们都具有外部显示类型block
。
- 一个添加了 CSS 边框的段落。浏览器将其呈现为块级盒子。段落从新行开始,并扩展到整个可用宽度。
- 一个列表,它使用
display: flex
进行布局。这为容器的子元素(即弹性项目)建立了弹性布局。列表本身是一个块级盒子,与段落一样,扩展到整个容器宽度,并在新行换行。 - 一个块级段落,其中包含两个
<span>
元素。这些元素通常是inline
,但是,其中一个元素具有类名 "block",它被设置为display: block
。
在接下来的示例中,我们可以看到inline
元素的行为方式。
- 第一个段落中的
<span>
元素默认是内联的,因此不会强制换行。 - 设置为
display: inline-flex
的<ul>
元素创建一个包含一些弹性项目的内联盒子。 - 这两个段落都被设置为
display: inline
。内联弹性容器和段落都在一行上运行,而不是换行(如果它们作为块级元素显示,则会换行)。
要切换显示模式,您可以将display: inline
更改为display: block
,或将display: inline-flex
更改为display: flex
。
现在要记住的关键是:更改display
属性的值可以更改盒子的外部显示类型是块级还是内联。这会更改它在布局中与其他元素一起显示的方式。
什么是 CSS 盒子模型?
CSS 盒子模型整体上适用于块级盒子,并定义了盒子不同部分(边距、边框、填充和内容)如何协同工作以创建一个您可以在页面上看到的盒子。内联盒子仅使用盒子模型中定义的某些行为。
为了增加复杂性,存在标准盒子模型和备用盒子模型。默认情况下,浏览器使用标准盒子模型。
盒子的组成部分
构成 CSS 中的块级盒子的是
- 内容盒子:显示内容的区域;使用像
inline-size
和block-size
或width
和height
这样的属性对其进行大小调整。 - 填充盒子:填充作为空白空间位于内容周围;使用
padding
及其相关属性对其进行大小调整。 - 边框盒子:边框盒子包裹内容和任何填充;使用
border
及其相关属性对其进行大小调整。 - 边距盒子:边距是最外层,包裹内容、填充和边框,作为该盒子与其他元素之间的空白空间;使用
margin
及其相关属性对其进行大小调整。
下图显示了这些层
标准 CSS 盒子模型
在标准盒子模型中,如果您在盒子中设置inline-size
和block-size
(或width
和height
)属性值,这些值将定义内容盒子的inline-size
和block-size
(在水平语言中为width
和height
)。然后将任何填充和边框添加到这些维度中,以获得盒子占用的总大小(参见下图)。
如果我们假设一个盒子具有以下 CSS
.box {
width: 350px;
height: 150px;
margin: 10px;
padding: 25px;
border: 5px solid black;
}
盒子实际占用的空间将是 410px 宽(350 + 25 + 25 + 5 + 5)和 210px 高(150 + 25 + 25 + 5 + 5)。
注意:边距不计入盒子的实际大小——当然,它会影响盒子在页面上占用的总空间,但只影响盒子外部的空间。盒子的区域在边框处停止——它不会扩展到边距。
备用 CSS 盒子模型
在备用盒子模型中,任何宽度都是页面上可见盒子的宽度。内容区域宽度是该宽度减去填充和边框的宽度(参见下图)。无需将边框和填充加起来以获得盒子的实际大小。
要在元素上启用备用模型,请在其上设置box-sizing: border-box
.box {
box-sizing: border-box;
}
如果我们假设盒子具有与上面相同的 CSS
.box {
width: 350px;
inline-size: 350px;
height: 150px;
block-size: 150px;
margin: 10px;
padding: 25px;
border: 5px solid black;
}
现在,盒子实际占用的空间将在内联方向上为 350px,在块级方向上为 150px。
要对所有元素使用备用盒子模型(这是开发人员中的常见选择),请在<html>
元素上设置box-sizing
属性,并将所有其他元素设置为继承该值
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
要了解基本思想,您可以阅读CSS Tricks 上关于 box-sizing 的文章。
玩转盒子模型
在以下示例中,您可以看到两个盒子。它们都具有.box
类,这使它们具有相同的width
、height
、margin
、border
和padding
。唯一的区别是第二个盒子被设置为使用备用盒子模型。
您可以更改第二个盒子的大小(通过将 CSS 添加到.alternate
类中)使其在宽度和高度上与第一个盒子匹配吗?
注意:您可以在此处找到此任务的解决方案。
使用浏览器开发者工具查看盒子模型
您的浏览器开发者工具可以使理解盒子模型变得更加容易。如果您在 Firefox 的开发者工具中检查元素,您可以看到元素的大小及其边距、填充和边框。以这种方式检查元素是了解您的盒子是否真的如您所想的那样大小的绝佳方法!
边距、填充和边框
边距
边距是盒子周围的不可见空间。它将其他元素推离盒子。边距可以具有正值或负值。在盒子的某一边设置负边距会导致它与页面上的其他内容重叠。无论您使用的是标准盒子模型还是备用盒子模型,边距始终是在计算可见盒子大小之后添加的。
我们可以使用margin
属性一次控制元素的所有边距,或者使用等效的完整属性分别控制每个边
在以下示例中,尝试更改边距值以查看盒子如何由于边距创建或移除空间(如果是负边距)而被推到周围,在该元素与其包含元素之间创建或移除空间。
边距折叠
根据两个边距接触的元素的边距是正值还是负值,结果将有所不同
- 两个正边距将合并为一个边距。其大小将等于最大的单个边距。
- 两个负边距将折叠,并将使用最小的(最远离零)值。
- 如果一个边距为负值,则其值将从总数中减去。
在下面的例子中,我们有两个段落。顶部的段落有一个margin-bottom
为50像素,另一个段落有一个margin-top
为30像素。这些边距合并在一起,因此盒子之间的实际边距是50像素,而不是两个边距的总和。
你可以通过将第二个段落的margin-top
设置为0来测试这一点。两个段落之间可见的边距不会改变,它将保持第一个段落margin-bottom
中设置的50像素。如果将其设置为-10px,你会发现总边距变为40px,它从50px中减去。
许多规则决定了何时边距会合并或不会合并。有关更多信息,请参阅有关掌握边距合并的详细页面。需要记住的最重要的一点是,如果使用边距创建空间,但没有获得预期的空间,则会发生边距合并。
边框
边框绘制在盒子的边距和填充之间。如果你使用的是标准盒子模型,边框的大小将添加到内容盒子的width
和height
中。如果你使用的是备用盒子模型,那么边框越大,内容盒就越小,因为边框会占用元素盒子可用width
和height
的一部分。
对于样式化边框,有很多属性——有四个边框,每个边框都有一个样式、宽度和颜色,我们可能需要操作。
可以使用border
属性一次性设置所有四个边框的宽度、样式或颜色。
要分别设置每个边的属性,请使用
要设置所有边的宽度、样式或颜色,请使用
要设置单个边的宽度、样式或颜色,请使用更细粒度的长手属性
border-top-width
border-top-style
border-top-color
border-right-width
border-right-style
border-right-color
border-bottom-width
border-bottom-style
border-bottom-color
border-left-width
border-left-style
border-left-color
在下面的例子中,我们使用了各种简写和长手来创建边框。尝试使用不同的属性,确保你理解它们的工作原理。边框属性的MDN页面提供了有关不同可用边框样式的信息。
填充
填充位于边框和内容区域之间,用于将内容推离边框。与边距不同,你不能使用负填充。应用于元素的任何背景都会显示在填充后面。
padding
属性控制元素所有边的填充。要分别控制每边,请使用这些长手属性
在下面的例子中,你可以更改类.box
上的填充值,以查看这会如何改变文本相对于盒子的起始位置。你也可以更改类.container
上的填充,在容器和盒子之间创建空间。你可以更改任何元素上的填充,在元素的边框与其内部的内容之间创建空间。
盒子模型和内联盒子
以上所有内容都完全适用于块盒子。一些属性也可能适用于内联盒子,例如由<span>
元素创建的那些。
在下面的例子中,我们有一个<span>
在段落内。我们对其应用了width
、height
、margin
、border
和padding
。你可以看到宽度和高度被忽略了。顶部和底部的边距、填充和边框被尊重,但不会改变其他内容与内联盒子的关系。填充和边框与段落中的其他单词重叠。左右填充、边距和边框会将其他内容从盒子中移开。
使用 display: inline-block
display: inline-block
是display
的一个特殊值,它提供了inline
和block
之间的中间地带。如果你不希望项目换行,但希望它尊重width
和height
,并避免上述重叠,请使用它。
具有display: inline-block
的元素执行我们已经知道的一些块操作
width
和height
属性被尊重。padding
、margin
和border
会导致其他元素被推离盒子。
但是,它不会换行,并且只有在你显式添加width
和height
属性时才会变得比其内容更大。
在下一个例子中,我们已将display: inline-block
添加到我们的<span>
元素中。尝试将其更改为display: block
或完全删除该行以查看显示模型的差异。
当你想通过添加padding
来使链接具有更大的点击区域时,这将非常有用。<a>
是一个内联元素,类似于<span>
;你可以使用display: inline-block
来允许对其设置填充,从而使用户更容易点击链接。
你经常在导航栏中看到这种方式。下面的导航使用flexbox在一行中显示,并且我们已向<a>
元素添加了填充,因为我们希望能够在鼠标悬停在<a>
上时更改background-color
。填充似乎与<ul>
元素上的边框重叠。这是因为<a>
是一个内联元素。
将display: inline-block
添加到具有.links-list a
选择器的规则中,你将看到它如何通过使其他元素尊重填充来解决这个问题。
测试您的技能!
你已经阅读完本文的结尾,但你能记住最重要的信息吗?在你继续之前,你可以找到一些进一步的测试来验证你是否保留了这些信息——请参阅测试你的技能:盒子模型.