HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

关于 CSS 排版,其实从毕升开始,我们就开始用正常流了

  • 2019-04-17
  • 本文字数:2063 字

    阅读完需:约 7 分钟

关于CSS排版,其实从毕升开始,我们就开始用正常流了

你好,我是 winter。这是我在极客时间《重学前端》专栏的第 24 篇文章「CSS的正常流」,今天分享给你。


我想,在 CSS 中,大家最讨厌的大概就是排版部分了。因为早年的 CSS 设计上不能够很好地支持软件排版需求,导致大家需要使用很多黑科技,让很多新人望而却步。现在 CSS 提供了很多种排版方式,我们有很多选项可以选择自己适合的那一种,然而,正常流却是我们绕不开的一种排版。


我们能够在网上看到关于正常流的各种资料,比如:块级格式化上下文、margin 折叠等等……这一系列的概念光是听起来就令人非常头痛。


很多同学一定会奇怪:正常流到底正常在哪里。事实上,正常流本身是简单和符合直觉的东西。我们之所以会觉得它奇怪,是因为如果我们从严苛的 CSS 标准角度去理解正常流,规定排版的算法,就需要引入上述那些复杂的概念。但是,如果我们单纯地从感性认知的层面去理解正常流,它其实是简单的。


下面,就让我们先抛弃掉所有的已知概念,从感性认知的角度出发,一起去理解一下正常流。

正常流的行为

首先,我们先从词源来讲一讲排版这件事。


在毕昇发明活字印刷之前,排版这项工作是不存在的,相应的操作叫做“雕版”。人们要想印刷书籍,就需要依靠雕版工人去手工雕刻印版。


活字印刷的出现,将排版这个词引入进来,排版是活字印刷的 15 道工序之一,不论是古代的木质活字印刷,还是近代的铅质活字印刷,排版的过程是由排版工人一个字一个字从字架捡出,再排入版框中。实际上,这个过程就是一个流式处理的过程。


从古代活字印刷开始,到现代的出版行业,再到今天的 Web,排版过程其实并没有什么本质的变化,只不过,今天在我们的 CSS 中,排版需要处理的内容,不再是简单的大小相同的木字或者铅字,而是有着不同字体和字号的富文本,以及插入在富文本中大小不等的盒。


并且,在这些过程中,都会有一个正常流的存在。那么,正常流是什么样的呢?


我们可以用一句话来描述正常流的排版行为,那就是:依次排列,排不下了换行。这个操作很简单吧,我想,任何一个不懂排版的人都会将其作为排版时的第一反应。


理解了正常流的基本概念,剩下的功能只需要在它的基础上延伸一下就好。


在正常流基础上,我们有 float 相关规则,使得一些盒占据了正常流需要的空间,我们可以把 float 理解为“文字环绕”。



我们又有 vertical-align 相关规则,规定了如何在垂直方向对齐盒。vertical-align 相关规则看起来复杂,但是实际上,基线、文字顶/底、行顶/底都是我们正常书写文字时需要用到的概念,只是我们平时不一定会总结它们。


除此之外,margin 折叠是很多人非常不理解的一种设计,但是实际上我们可以把 margin 理解为“一个元素规定了自身周围至少需要的空间”,这样,我们就非常容易理解为什么 margin 需要折叠了。

正常流的原理

我们前面描述了正常流的行为,接下来我们要切换一下模式,用比较严谨的姿势来理解一下正常流。


在 CSS 标准中,规定了如何排布每一个文字或者盒的算法,这个算法依赖一个排版的“当前状态”,CSS 把这个当前状态称为“格式化上下文(formatting context)”。


我们可以认为排版过程是这样的:


格式化上下文 + 盒/文字 = 位置


formatting context + boxes/charater = positions


我们需要排版的盒,是分为块级盒和行内级盒的,所以排版需要分别为它们规定了块级格式化上下文和行内级格式化上下文。


与正常流一样,如果我们单纯地看格式化上下文,规则其实是非常简单的。


块级格式化上下文顺次排列元素:



行内级格式化上下文顺次排列元素:



注意,块级和行内级元素的排版,受文字书写方向的影响,这里我们讲上下左右只是为了方便你直观理解。


当我们要把正常流中的一个盒或者文字排版,需要分成三种情况处理。


  • 一、当遇到块级盒:排入块级格式化上下文。

  • 二、当遇到行内级盒或者文字:首先尝试排入行内级格式化上下文,如果排不下,那么创建一个行盒,先将行盒排版(行盒是块级,所以到第一种情况),行盒会创建一个行内级格式化上下文。

  • 三、遇到 float 盒:把盒的顶部跟当前行内级上下文上边缘对齐,然后根据 float 的方向把盒的对应边缘对到块级格式化上下文的边缘,之后重排当前行盒。


我们以上讲的都是一个块级格式化上下文中的排版规则,实际上,页面中的布局没有那么简单,一些元素会在其内部创建新的块级格式化上下文,这些元素有:


  • 浮动元素;

  • 绝对定位元素;

  • 非块级但仍能包含块级元素的容器(如 inline-blocks, table-cells, table-captions);

  • 块级的能包含块级元素的容器,且属性 overflow 不为 visible。


这里的最后一条比较绕,实际上,我个人喜欢用另一种思路去理解它:


自身为块级,且 overflow 为 visible 的块级元素容器,它的块级格式化上下文和外部的块级格式化上下文发生了融合,也就是说,如果不考虑盒模型相关的属性,这样的元素从排版的角度就好像根本不存在。


好了,到这里我们已经讲完了正常流的排版详细规则,但是理解规则仅仅是基础,我们还需要掌握一些技巧。我在《重学前端》的第24讲,对正常流的使用技巧,给出了详细的解答。


拓展阅读:


JavaScript词法:为什么12.toString会报错?


一个浏览器是如何工作的?


2019-04-17 15:494124

评论

发布
暂无评论
发现更多内容

记线上服务 cpu 爆表 问题解决

常清静

性能优化 压测分析 CPU问题

你必须知道的Java17新特性-密封类(Sealed Classes)

蜜糖的代码注释

Java 开发 后端开发

实时渲染大赛太卷了!来看大佬提前交卷的优秀参赛作品

3DCAT实时渲染

3D 实时渲染

AI+遥感:释放每个像元价值

百度大脑

人工智能 AI

开源机器学习数据库OpenMLDB v0.4.0产品介绍

第四范式开发者社区

人工智能 机器学习 大数据 OpenMLDB

模块六

撿破爛ぃ

架构训练营

回顾明道云的2021(文末互动有奖)

明道云

如何优雅地解决平台字体适应问题

编程三昧

CSS 前端开发 HTML5, CSS3 1月月更

Go 语言快速入门指南:Go 函数

宇宙之一粟

函数 Go 语言 1月月更

openLooKeng1.5.0新版本正式上线

openLooKeng

开发postgreSQL connector支持update/delete操作的代码

openLooKeng

11张图深入理解分布式锁原理

慕枫技术笔记

微服务 后端 1月月更

夜莺系统调研报告

苍狼

(1-23/23)Transformer依然很强

mtfelix

300天创作 2022Y300P

ReactNative进阶(三十七):应用 SectionList 实现分组列表

No Silver Bullet

1月月更 ReactNative sectionList

知名身份安全厂商九州云腾加入龙蜥社区

OpenAnolis小助手

Linux 开源 互联网

🏆【Alibaba微服务技术系列】「Dubbo3.0技术专题」(1)Dubbo3新特性概览的介绍说明

洛神灬殇

dubbo Dubbo3 Alibaba技术 1月日更 Apache alibaba

ABAP 和 Java 里的单例模式攻击

汪子熙

Java abap 1月月更

一文聊透Netty核心引擎Reactor的运转架构

bin的技术小屋

网络编程 nio 中间件 jdk8 netty

左手2021, 右手2022 | 社区征文

soolaugust

技术 云原生 新春征文

Python Qt GUI设计:做一款串口调试助手(实战篇—1)

不脱发的程序猿

PyQt Python Qt Python Qt GUI设计 串口调试助手

区块链赋能民生“第一单”:200多套房源试水,“链宜租”租房系统上线

CECBC

记 服务 内存飙升压测 - 分析总结

常清静

压测分析 内存问题 排查工具

模块 6 作业

miliving

MyBatis3源码解析(1)探索准备

Java mybatis

【架构师训练营】模块六作业

樰巳-堕~Horry

架构实战营 「架构实战营」

云智慧智能研究院:2022年智能运维发展八大趋势

云智慧AIOps社区

趋势 AIOPS 智能运维 云智慧 运维发展

AI贺新年,开发者的虎年这样过才有意思

华为云开发者联盟

AI 华为云

Hive SQL底层执行过程 | 社区征文

五分钟学大数据

hive 新春征文

对GO切片的理解

CRMEB

虎虎生威新春大吉,2月更文挑战来袭!

InfoQ写作社区官方

2月月更 热门活动

关于CSS排版,其实从毕升开始,我们就开始用正常流了_大前端_程劭非_InfoQ精选文章