写点什么

关于 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:494258

评论

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

霸榜Git!2021年阿里巴巴Java面试权威指南(泰山版)

Java架构之路

Java 程序员 架构 面试 编程语言

霸榜Git!2021年阿里巴巴Java面试权威指南(全彩版)

Java 程序员 面试 架构师

2021年新兴的十大区块链技术趋势

CECBC

数字技术

一周信创舆情观察(3.8~3.14)

统小信uos

科技进化的终点,与荣耀全场景的起点

脑极体

打卡学习VBA和PYTHON week01

小怪兽

IT蜗壳教学

如何评估需求优先级?

石云升

项目管理 28天写作 职场经验 管理经验 3月日更

uni-app跨端开发H5、小程序、IOS、Android(二):开发工具HBuilderX使用技巧

黑马腾云

微信小程序 uni-app App 3月日更 Hbuilderx

全球案例 | Infobip :这家估值十亿美元的公司像初创企业一样规模化发展,像大型企业一样标准化

Atlassian

DevOps Agile Atlassian Jira ITSM

直击面试!阿里技术官手码12W字面试小册在Github上爆火

Java架构之路

Java 程序员 架构 面试 编程语言

声网Agora发布创业支持计划:聚合50+合作伙伴、11项资源扶持创业者

ToB行业头条

声网 Agora

低代码/无代码,作为IT开发界的“新英雄”它究竟有何神技?

优秀

低代码 无代码开发

朱嘉明:比特币开创人类新型财富实验

CECBC

数字货币

php 再上热搜!swoole 创始人投出反对票,质疑 php 协程最新提案

薇薇

php 编程 新特性 php扩展

DCache 分布式存储系统|Set, ZSet 缓存模块的创建与使用

TARS基金会

nosql 缓存 分布式 MySQL 高可用 TARS

filecoin云算力软件开发|filecoin云算力APP系统开发

系统开发

发布两小时,霸榜GitHub!Spring Boot实战文档

Java 编程 程序员 架构师

图解垃圾算法,No,捡垃圾算法

叫练

GC算法 引用计数法 标记清除法

炸裂,IBM系统架构师居然把自己15年Java经验整合成一本小说?

Java架构师迁哥

收藏!这些IDE使用技巧,你都知道吗

xcbeyond

IDEA 技巧 3月日更

"无密码时代"已经来临!

龙归科技

身份认证

全凭阿里大牛总结的Java面试笔记,首战成功拿蚂蚁offer

Java架构之路

Java 程序员 架构 面试 编程语言

filecoin挖矿软件开发|filecoin挖矿APP系统开发

系统开发

经典排序算法分析

roseduan

算法 排序算法

寻找被遗忘的勇气(十八)

Changing Lin

3月日更

epoll源码分析以及在Redis中的实现

Linux服务器开发

redis 后端 epoll web服务器 Linux服务器开发

JDBC—往MySQL中写入Blob数据时,出现错误:com.mysql.jdbc.PacketTooBigException: Packet for query is too large (5724349 > 1048576)

打工人!

Java MySQL JDBC Blob

以数字人民币为契机 推动人民币国际化进程

CECBC

金融

filecoin矿机系统开发|filecoin矿机软件APP开发

系统开发

聊聊 Python 自动化脚本部署服务器全流程(详细)

星安果

Python 自动化 服务器 部署

趋势预测:2021年五大流行的编程语言

薇薇

Java c php JavaScript Python PEP

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