在学 习 Web 布局 之前有一个非常重要的概念需要理解,这个概念就是盒模型。CSS 盒模型是多个不同的 CSS 规则集合,定义了如何渲染 Web 页面。这一系列的不同的属性决定了 HTML 元素在页面上的位置。到目前为止,所有 Web 页面都只是一个接一个渲染的元素。可以说盒模型是我们定制默认布局方案的工具包。
作为 Web 开发人员,大部分工作是将应用 CSS 盒模型中的规则将设计模型转换为 Web 页面(简单点说,就是 UI 还原)。接下来要介绍的 CSS 盒模型又被视为 UI 还原的重中之重,因为它定义了盒子的单独行为。特别是在以后的章节中,我们学习的各种布局都将会围绕着 HTML 的结构和 CSS 的盒模型一起来展开。
基础盒模型介绍
在 CSS 中,一切都会生成一个框。而 Web 页面的本质上是一组块和内联框。如果在浏览器中使用开发者工具查看一个HTML中的元素,就可以很好的理解这些框。而这些框却是一组 CSS 规则的集合。主要用于确定页面中每个元素的尺寸。
在 CSS 的世界中将会视 HTML 中的每个元素比作一个盒子(也被称之为元素框)。
这个框体描述了元素在 Web布局 中所占的空间。因此元素之间涉及到位置和尺寸是会相互影响的。作为 CSSer 要彻底了解这些属性规则之间是如何相互影响的话,有一些理论和概念就很有必要了解清楚。
块元素和内联元素
任何一个 Web 页面都会有很多种不同的 HTML 元素组成,这也是众所周之的。前面我们也提到过,任何一个 HTML 元素都是一个框(盒子),这些框主要有两种类型,块 和内联框。其对应的即是 HTML 中的块元素和内联元素。
- 块框 :如果不做任何的处理,其宽度会占满容器的整个宽度(或高度),而高度(或宽度)由元素内容决定,比如
div
、p
、li
等元素都是块元素,而这些块元素在Web上渲染出来的框就是块框 - 内联框 :如果不做任何的处理,其宽度和宽度都由内容来决定,比如
span
、strong
、em
等元素都是内联元素,而这些元素在Web上渲染出来的框就是内联框
用张图来描述,可能更易于理解:
这仅仅是常规的理解。
时至今日,CSS 也有了较大的变化,而渲染也有着相应的变化。在块框和内联框和书写模式(writing-mode
)有着紧密的联系。
对于块元素(块盒子)而言,如果书写模式是水平方向horizontal-tb
,那么块是从上往下流;而书写模式是垂直方向horizontal-lr
时,那么块是从左向右流。如下图所示:
对于内联元素而言,它会按照当前上下文、书写模式和方向进行布局。它们的宽度取决于它们的内容,并且在任何有空间的地方相邻放置。如下图所示:
简而言之,块元素遵循流方向,内联元素遵循写入方向:
块轴和内联轴
块元素和内联元素是 CSS 中框模式中最基本的两种。而在 Web 的世界中还有坐标轴的概念,Web 的坐标主要有两个轴,即:
x
轴:水平方向的坐标轴y
轴:垂直方向的坐标轴
页面上的内容都尚着这两个轴进行排版。其中一个轴是内联轴,它是每行文本行的轴。默认情况下,在Web页面上,如果不指定任何书写模式,内联轴是水平的,从左到右(书写模式对其会有一定的影响)。另一轴是块轴,块轴是沿着这个轴堆积。同样,默认情况下,这个轴是垂直的,从上到下。如下图所示:
- 内联轴(Inline Axis) :拿英文网站为例。阅读方向是从左到右。好比多个内联元素一样,从左向右依次排开,也类似于在块元素中使用
display: inline
。每一项都出现在同一行 - 块轴(Block Axis) :大家应该都知道,对于块元素不做任何操作的情况下,他的排列顺序是从上到下依次堆积在一起。好比对内联元素采用了
display: block
其实这两个概念理解起来比较费劲。拿 Flexbox 布局中的主轴和侧轴来说:
在书写模式默认情况下,内联轴好比 Flexbox 上的主轴(Main Axis),而块轴好比Flexbox上的侧轴(Cross Axis)。事实上,这两个概念如果我们运用到网格布局中就更易于理解。因为在网格布局中,总是使用块和内联轴。
块轴对应于在页面上布局块的顺序。比如,页面中的文本内容,每一段都在另一段下面排列,这些排列的方向是块的维度,所以在网格布局中,这是块(Block Axis)。在CSS网格布局中,块轴也称为行轴,这就是为什么块轴属性是grid-row-start
和grid-row-end
。
因此,内联轴将会穿过块轴,沿碰上词在句子中的方向分布。在英文语句中,这个轴从左到右。在网格布局中,内联轴属性是grid-column-start
和grid-column-end
。
前面也提到过,内联轴和块轴与书写模式有较大的关联,书写模式不同时,内联轴和块轴会随之改变。如下图所示:
框模式的类型
虽然在CSS中每个元素都是一个框,而这个框的模式是有所不同的,常见的模框式有:
- 块级框 :HTML中的
p
、div
等元素生成的框。在常规流动模式下,块级框在框体前后都"换行",因此块级框是缀向堆叠的 - 行内框 :HTML中的
strong
、span
等元素生成的框。行内框前后不"换行" - 行内块级框 :内部特征像块级框,外部特征像行内框。行内块级框的行为与置换元素相似,但不完全相同。比如说把一个
div
元素像行内图像那样插入一行文本
在理解框模式上有几个概念需要有一定的了解:
- 常规流动:即渲染西方语言时从左至右、从上到下的顺序,以及传统的HTML文档采用的文本布局方式(这也是大家常说的文档流)。对于非西方语言来说,流动方向可能会变。多数元素都采用常规的流动方式,除非元素浮动了、定位了,放入Flexbox容器或Grid容器中。
- 非置换元素 :内容包含在文档中的元素,例如
p
元素就是非置换元素,因为p
中的文本内容在元素自身中 - 置换元素 :为其他内容占位的元素。比如
img
元素就是一个典型的置换元素,另外,多数表单元素也是置换元素
理解这些概念对于深入学习CSS或者后面聊布局的相关知识时有较大的帮助。
其实在HTML中的任何一个元素都有其对应的框模式,但在CSS中,我们可以借助display
属性来修改元素的框模式。比如说,当你在一个div
上使用了display: flex
或display: grid
,那么该div
的框模式和display:block
并无差异,但它改为了它们子元素的框模式。当然,如果你在一个块级框的元素上使用display:inline
的话,该元素就会变成一个行内框。
CSS中的
display
属性也是CSS的重要属性之一,也是重中之中的部分。我们后面将会单独花一个章节和大家一起讨论这方面的使用。
盒模型术语
既然元素是一个框(盒子),那么就可以通过CSS属性(物理属性)来决定盒子的大小。而决定盒子大小主要由四个属性来决定:
Content
:元素中的文本、图像或其他媒体内容padding
:盒子内容格边框之间的空间border
:盒子的边框margin
:盒子与其他盒子之间的距离
如果我们用一张图来描述的话,可以类似下面这样的:
上面提到的几个属性就是浏览器渲染元素盒子所需要的一切。内容是你在HTML中编写的内容,其余部分纯粹是展示性的,主要由CSS规则来决定。而且对于CSSer来说,都喜欢用类似下图来阐述元素的盒模型:
而在浏览器调试器中"Computed"可以看到它是怎么来解释一个元素的盒模型:
拿个简单的示例来展示:
CSS
.box {
width: 200px;
height: 200px;
background-color: darkviolet;
border: 5px solid hotpink;
padding: 25px;
margin: 20px;
}
该.box
对应的盒子如下图所示:
CSS的逻辑属性对盒模型带来的变化
大家是否有留意到,在前面提到的padding
、border
和margin
等都是采用的物理特性来描述一个盒子,而且开发者讨论盒模型的时候,都习惯使用下图来阐述它:
不管是以前,还是现在,以上图来阐述CSS盒模型的概念都不存在任何的错误。不同的是,上图我们围绕着的还是以特理特性来进行阐述,但随着CSS的逻辑属性的出现。再次阐述CSS盒模型的时候,会停止物理属性*-top
、*-right
、*-bottom
和*-left
来阐述,而应该改用*-inline-start
、*-inline-end
、*-block-start
和*-block-end
来重新定义盒模型,类似下图这样的:
如此一来,根据不同的语种,盒模型中的margin
、border
和padding
对于的内联轴和块轴也不一样。拿英文网站来说:
margin
margin-block-start = margin-top
margin-block-end = margin-bottom
margin-inline-start = margin-left
margin-inline-end = margin-right
padding
padding-block-start = padding-top
padding-block-end = padding-bottom
padding-inline-start = padding-left
padding-inline-end = padding-right
border
border-block-start = border-top
border-block-end = border-bottom
border-inline-start = border-left
border-inline-end = border-right
也就是说,如果将CSS逻辑属性引入进来之后,我们将来描述一个盒模型,应该用下图来阐述,更为准确:
盒子尺寸
每个盒子都有其自己的尺寸大小。在物理属性中,通过width
和height
来描述一个盒子的大小。而在逻辑属性中会使用逻辑尺寸的属性inline-size
和block-size
来描述一个盒子的大小。
如果理解了内联和块轴的概念,就更容易理解逻辑尺寸。比如在英文网站中,inline-size
替换了width
,block-size
替换了height
。也就是说:
block-size
:定义一个元素块的水平或垂直方向的尺寸,这主要取决于它的书写模式。如果书写模式是垂直方向的,则block-size
与元素的width
有关,否则,它与元素的height
有关inline-size
:定义一个元素的块的水平或垂直尺寸,这取决于它的书写模式。其对应于任一width
或height
属性,这取决于的值writing-mode
。如果写作模式是垂直定向的,则inline-size
与元素的height
有关;否则,则与元素的width
有关
比如英文或阿拉伯语网站:
width = inline-size
height = block-size
而在日文网站中:
height = inline-size
width = block-size
在我们的理解中,除了width
和height
之外,还有min-width
、max-width
、min-height
和max-height
一说。那么在inline-size
和block-size
中同样存在,相应的也是在其前面添加min
或max
。比如:min-inline-size: 100px
或max-block-size: 100px
。
盒模型切换
上面提到了,CSS的width
和height
(或者说逻辑属性inline-size
和block-size
)可以用来计算元素盒子尺寸的大小。为了让大家更好的理解,这里还是拿物理属性来阐述。
在一般情况之下,我们所说的盒子的width
是元素内容的宽度,内距和边框的和,这也常常被称之为内盒的宽度。如果你在内盒的宽度上加外距的大小就可以计算出盒子外盒的宽度。
盒子的height
计算和width
类似。
但在布局中,盒子的宽度计算会直接影响到布局,甚至会直接打破页面的布局。比如说,一个div
元素:
CSS
div {
width: 100%;
padding: 1rem;
}
会让div
超出容器,类似下图这样:
面对这样的场景时,就需要借助CSS的box-sizing
属性,它可以更好的帮助我们控制盒子的大小:
用个实例来解释,这样更易于理解:
小结
随着我们深入的构建复杂的Web页面,将会学习更多有关于CSS盒模型的实际运用。现在,把它看作是CSS中的"工具",该"工具"可以把设计模型更好的转换为现实的Web页面。如果你还不知道如何在Web布局中更好的运用好CSS盒模型,并不重要,也不需要过于担心。在这一章节中,只需要记住:
- Web页面中任何一个元素都是一个盒子(框)
- CSS中的框可以是内联的,也可以是块级的
- CSS中的任何一个框都包含了内容、内距、边框和外距
另外,CSS的逻辑属性将会给CSS盒模型带来较大的变化,逻辑属性的使用能更好的结合书写模式,更能符合视觉上的感观。但也带来了一些新的概念。不过,在接下来的实际中,暂且不会涉及到太多有关于盒模型中的逻辑属性。