盒 ( Box )
讲到排版,我们需要引入的第一个概念就是 “”。之前我们在《模拟浏览器》和之前的一些 CSS 的文章中都讲到了排版相关的概念。
而我们真正去讲到排版的时候,我们需要用到的单位一定就是 “”。
在真正进入详细了解 “盒” 的概念之前,我们先来做认识一下 3 个比较容易混交的概念。
- 标签 ( Tag ) —— 源代码
- 元素 (Element) —— 语义
- 盒 ( Box ) —— 表现
HTML 代码中可以书写开始,结束,和自封闭。
标签是一个源代码的概念,所以方式我们提到在 HTML 代码中写的肯定都是标签。
一对起止,表示一个。
元素是存在我们脑子里的一个概念,它是语义领域的一个概念,所以一对起止标签它一定是表示一个我们脑子里面的概念。
DOM 树中存储的是和其他类型的节点 ( Node )。
DOM 树中存储的不全是元素,因为DOM 树中存储的东西叫节点 ,所以元素只是是节点的一种。
比如说我们的文本节点也是节点,但他并不是元素。再比如我们的注释节点,它也是节点但是它也不是元素。当然还有 CDATA 节点,还有 processing-instruction,DTD等这些都是会存入 DOM 树的,当时它们都并不是元素。
很多同学的理解,DOM 树中存储的都是元素,不过这样也没有错。因为其他的节点相对来说都没有那么重要。
CSS 选择器中的是。
其实这里还可以加一个 “或”,在《CSS 选择器》中讲到的,CSS 选择器选中的是元素或者是。
CSS 选择器中的,在排版时可能产生多个。
这个地方是大家需要注意到的一个概念,CSS 选择器选中的元素,它不一定和盒是一一对应的关系。它有可能是一对多的关系的。但是有盒一般来说必定是有对应的元素的。我们不可能无中生有产生一个元素,即使是 称是无中生有的伪元素也是依附于一个选中的元素产生的。
排版和渲染的基本单位是
在我们的《模拟浏览器》的实现过程中,我们的排版盒渲染都是直接拿元素当盒去用了。但是这是一个很粗糙的做法,在实际上我们很多元素都会产生多个盒。
比如说 元素就会因为分行而产生多个盒。又比如说带有伪元素,被伪元素选择器选中的元素也会生成多个盒。所以我们排版盒渲染的基本单位都是盒。
- padding 主要影响的是盒内的空间 —— 主要决定盒内的空间排布,也就是 content 区域的大小
- margin 主要影响的是盒外的空间 —— 决定了盒周围空白区域的大小
盒模型里面的 宽 (width) 是有讲究的,盒子的宽度是有可能被 属性所影响的。最常见的两个值就是:
content-box
设置的 属性只包含 的内容的空间。也就是说:
= + + +
border-box
使用,我们的 width 就包含了 padding 和 border 的尺寸了。回去看看我们盒模型的图,我们可以看到的黄色线括着的区域,它所占据的空间和范围。
这样当我们给一个盒,padding 和 border 的时候,就不会影响我们给予盒子的 width。这样我们就可以保证我们盒子在没有 margin 的时候它所占据的空间就是与我们 width 一致的。
呈现出来的效果就是 padding 和 border 都会往内挤压空间,而不会影响盒子的宽度。
这里我们就讲完盒模型了,我们就发现它所影响的属性就是 ,,,这几个属性。这些都是影响我们盒模型的总体尺寸,在排版中会影响着这个盒模型所占据的范围。
如果我们看到上面这个图,可能有一些同学知道是什么,有一些同学完全不知道他在干什么。其实这个就是 80 年代印刷厂工人在进行排版工作。
这个传统的排版技术,其实与我们现在 页的是息息相关的。在很多文章中,我们会把翻译成,有时候也会翻译成。但是我个人也觉得翻译成是最贴切的。因为 CSS 当中的是源自于传统的排版技术。
传统的排版方式,我们需要先把字版放入一个一个字框里面,按照文字的顺序排列 ,然后再把这些字框一个一个的排列进我们的排版框里面。
所以所谓排版就给我们所有可见的东西放到正确的位置上去。而在 HTML 里面,我们是有 “盒” 这样一个东西,在 CSS 的排版里我们。
- 盒
- 文字
一切 CSS 的排版,都不会逃出这与这样两东西。所以我们的排版就是给每一个文字安排到正确的位置上,然后给每一个盒安排到正确的位置上。
在不考虑盒模型的情况下,我们需要关注的就是位置和尺寸,所以排版中并没有什么特殊的内容。
字排版
很负责任的告诉大家,其实一点都不奇怪。如果我们知道前端的 HTML 和 CSS 的排版概念都是源自于专业排版知识,而这些排版使用方式如果出现在我们的书籍里面,我们都会觉得挺自然的。但是真正让我们去理解这些知识,我们都会觉得很困难。
这个就可以追溯到 HTML 最早期整个的排版设计,都是从文字出版行业过来的专家所做的。所以它使用的思路都是那个时代的一个专业的思路。跟我们自然人脑子里面的理解,可能就会有一些差异了。
正常流排版
接下来我们就正式进入正常流的排版讲解。
正常流排版的整个过程,与实现 flex 的过程比较类似,有这几个步骤:
- 收集盒与文字进行
- 计算盒与文字在行中的排布
- 计算行与行之间的排布
我们发现其实这个与我们 flex 的排版非常的像。其实我们会发现所有的排版算法,基本上都是差不多的。不论是哪个软件,哪个规则,它们都是这么几个步骤。
接下来我们来看看具体的一个排布规则:
- 块级排布的我们就叫 —— Block level formatting context (块级格式化上下文)
- 行内排布的我们就叫 —— Inline level formatting context (行内级格式化上下文)
很多在比较早期学习前端,甚至在一些 “0 基础” 的班里面学前端的同学,都会听说过 “块级元素” 和 “行内元素” 两种说法。其实与我们讲到的 BFC 和 IFC 就是这个概念最原本的意思。
行级排布
首先我们看到 ,也就是一个字体的原点。而原点标识的位置就是我们文字的基线的位置,而这个文字都是以基线作为原点的坐标,然后再用这个坐标来定义这个文字的位置。
所以说基线就是在 这个横向的坐标,然后这个文字就会有一个 和一个 , 就是文字最尾端的坐标位置,而 就是文字最顶端的位置。
然后文字也有相反的两个值 和 ,而这两个值就是刚好相反,是文字开始的位置和底部的位置。
也可以理解为从底缘的基线到文字的最顶端的距离,这就是 。而底缘的基线到文字的最底端的距离就是 。而 到 ,从原点到文字开始和文字结束的距离。
最后这里面的 就是整个字占用的空间。
以上讲的就是横向排版的时候,而纵排又有另外一套的逻辑:
我们大致了解了这个文字在字体里面是如何定义之后,我们就可以来讲讲 CSS 里面的行模型了。这里我们重点讲 5 条线,其他还有一些线和位置例如 和 这种我们就不去讲了。
这个 base-line 和文字的顶原和底缘,分别叫做 、 和 。就是图中的一条黄线和两条绿线。
结合刚刚讲到的, 就是用来与英文字母对齐的。然后这里面有一个 和一个 ,如果我们的字体大小不变,这两个线是不会变得。
如果我们使用多个文字的字体混排的话,这个 和 是由 最大的一个字体决定的。然后这个文字的上缘和下缘可以理解为两条固定的线。
如果行高是大于文字的高度的时候,我们就会有 和 ,就是在图中的两条白色的线。
好!如果我们只有文字的话,这个行模型就这样子排布的。但是我们一旦涉及到跟盒的混排,就会涉及到一个 和 的偏移问题。
最后呈现出来的效果如下:
这里我们会发现盒子的对齐的位置发生了变化。盒的基线变成了它里面文字的最后一行的基线。也就是说,当一个盒子里面有文字的时候,这个盒子的对齐就会基于里面文字的基线做对齐。
这里如果我们在 的下一行加一个文字 ,我们又会发现另一种现象。

这个是特别需要注意的问题,行内盒 的基线是随着自己里面的文字去变化的。所以说大部分情况下是不建议大家给行内盒使用基线对齐的。
所以我们在使用的时候就需要给一个 ,属性值我们可以给 ,或者是都是可以的。
我们先看看 —— 顶缘对齐
div class="wrapper"> div class="base-line"> div>div> div> span class="
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!