CSS专题之盒模型

前言

石匠敲击石头的第 6 次

CSS 盒模型是前端面试常问的知识点,所以打算写一篇文章来好好梳理一下,如果哪里写的有问题欢迎指出。

什么是盒模型

CSS 盒模型用于描述 HTML 元素尺寸的计算方式和布局规则,决定了浏览器如何计算元素总大小和其在页面中的位置,网页中的任何元素都可以看做是一个盒子。

一个盒模型的实际大小主要由以下三个属性来决定:

  • content(内容): 元素的实际内容,如元素中的文本、图像或其他媒体内容。
  • padding(内边距): 盒子内容与边框之间的空白区域。
  • border(边框): 盒子的边框大小。

⚠️ 注意:margin 外边距不影响盒子的实际大小,但会影响盒子在页面上的占位空间。

盒模型的类型

盒模型分为两种,分别是标准盒模型和替代盒模型。

标准盒模型

W3C 规范制定的标准盒模型,也叫 W3C 盒模型,如果不指定元素是什么盒模型,默认就是标准盒模型(box-sizing: content-box)。

在标准盒模型中,widthheight 设置的是盒子内容区域(content)的大小,盒子最终的实际大小需要加上内边距(padding)和边框(border)的大小

盒子实际宽度 = 元素内容宽度 + 左右内边距大小 + 左右边框大小

盒子实际高度 = 元素内容高度 + 上下内边距大小 + 上下边框大小

举个例子

css 复制代码
.box {
  width: 100px;
  height: 100px;
  border: 1px solid #ccc;
  padding: 10px;
}

上述代码盒子实际宽度和高度都为 122px

  • 总宽度 = 内容宽度 + 左右 padding + 左右 border

    = 100px + 10px + 10px + 1px + 1px = 122px

  • 总高度 = 内容高度 + 上下 padding + 上下 border

    = 100px + 10px + 10px + 1px + 1px = 122px

替代盒模型

也叫IE盒模型(怪异盒模型),之所以叫 IE 盒模型,因为该盒模型最早 Internet Explorer(IE)浏览器引入的,并且在 IE5 及更早版本中是默认行为。

后来在 IE6 中允许在标准模式下使用 W3C 盒模型,但在怪异模式(Quirks Mode)中仍然使用 IE 盒模型,所以也叫怪异盒模型。

如今替代盒模型已经是 W3C 规范的一部分,给元素设置 box-sizing: border-box; 即可改变元素的盒模型。

在替代盒模型中 widthheight 设置的是盒子最终的实际大小 ,内容区域(content)的大小会根据内边距(padding)和边框(border)的大小自动收缩,以此来保证盒子最终的实际大小不变。

盒子实际宽度 = 设定的 width = (收缩的元素内容宽度 + 左右内边距大小 + 左右边框大小

盒子实际高度 = 设定的 height = (收缩的元素内容高度 + 上下内边距大小 + 上下边框大小

举个例子

css 复制代码
.box {
  width: 100px;
  height: 100px;
  border: 1px solid #ccc;
  padding: 10px;
  box-sizing: border-box;
}

上述代码盒子实际宽度和高度都为 100px

块级盒子与行内盒子

盒模型定义了每个 HTML 元素的结构(包括 content、padding、border、margin),但是这些盒子在页面中如何进行排列,还需要看它是块级盒子(Block Box)还是行内盒子(Inline Box)。

块级盒子

浏览器会将块级元素(如 divph1section 等这些默认 display: block 的元素)在页面中渲染为一个块级盒子(Block box)。

块级盒子有以下几个特点:

  • 单独占一行,上下排列,即使宽度没有占满当前行
  • 可以通过 CSS 明确指定 widthheight
  • 如果不设置 width默认宽度为父容器的 100%
  • 盒模型完整生效,marginpaddingborder垂直和水平方向都能影响布局
  • 垂直方向相邻的 margin 可能发生外边距合并(margin collapse)

行内盒子

浏览器会将行内元素(如 spanastrong 等这些默认 display: inline 的元素)在页面中渲染为一个行内盒子(Inline box)。

行内盒子有以下几个特点:

  • 不会单独占一行 ,而是与其它行内元素共享一行,在水平方向上排列
  • 无法设置 widthheight,这些属性对行内元素无效,元素的宽度由内容决定
  • 上下的 marginpadding 不会影响布局,但上下的 padding 会影响视觉效果 。左右的 marginpadding 会生效,影响元素间的间距
  • 垂直方向相邻的 margin 不会发生外边距合并(margin collapse)

⚠️ 注意: 这里说的上下的 padding 会影响视觉效果,是指如下情况。

css 复制代码
.inline-padding {
  /* 给行内盒子添加四周的内边距 */
  padding: 10px;
  background-color: yellow;
}
html 复制代码
<p>
  这是一段文本,其中有一个<span class="inline-padding">带内边距的行内元素</span>。
</p>

上述代码似乎看起来没什么问题,但是当文字换行时会出现被遮挡的问题。

这就是所说的上下的 padding 会影响视觉效果。

实践建议

想象一个场景,假设你根据设计稿给页面中的元素(已经设置了 wdithheight )添加了内边距,默认情况下,元素的最终大小比你预期要大,然后为了元素不变大你需要自己进行计算来减少内容区域的大小。

但其实你只需要给元素 box-sizing: border-box; 就可以解决这个问题,省去了自己计算的麻烦。

我们在实际开发中页面会有很多的元素,如果一个一个添加 box-sizing: border-box; 也是个麻烦事,所以在开发中建议将如下代码放在样式表的开头,以此调整全局元素的盒模型为替代盒模型。

css 复制代码
:root {
  box-sizing: border-box;
}

*,
::before,
::after {
  box-sizing: inherit;
}

⚠️ 注意:

  • * 选择器不会选中伪元素,所以这里需要加上 ::before::after 选择器。

  • 这里之所以使用 inherit 继承的方式是便于调整第三方组件的盒子模型。

    如果使用的第三方组件的盒子模型不是替代盒模型 ,会导致第三方组件的所有元素都是 border-box,大小出现问题,如果不使用继承的方式想要调整第三方组件的盒子模型非常麻烦(需要将所有组件元素的 box-sizing 都设置为 content-box),而使用继承的方式,只需要修改第三方组件根元素的盒模型即可

    css 复制代码
    /* 调整第三方组件根元素的盒子模型 */
    .third-party-component {
      box-sizing: content-box;
    }

总结

  • 盒模型决定了 HTML 元素的尺寸计算方式,影响元素在页面中的布局,主要包括:内容区域(content)、内边距(padding)、边框(border)和外边距(margin)。
  • 盒模型的类型
    • 标准盒模型box-sizing: content-boxwidthheight 只设置内容区域的大小,内边距和边框会额外增加到总尺寸。
    • 替代盒模型box-sizing: border-boxwidthheight 设置元素的总尺寸,内容区域 (content)的大小会根据内边距(padding)和边框(border)的大小自动收缩,以此来保证盒子最终的实际大小不变。
  • 块级盒子与行内盒子
    • 块级盒子 :占一整行,可以设置宽度和高度,垂直方向的 margin 可能会合并。
    • 行内盒子 :不会占用一整行,宽度和高度由内容决定,只有左右的 paddingmargin 会影响布局。
  • 实践建议:将全局元素的盒模型调整为替代盒模型,省去了自己计算的麻烦。

参考文章

博客地址:github.com/wjw020206/b...

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom12 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom12 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试