东亚银行、岚图汽车带你解锁 AIGC 时代的数字化人才培养各赛道新模式! 了解详情
写点什么

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

评论

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

【设计模式系列17】中介者模式原理及其在JDK源码中的体现

Java 程序员 后端

现代APaaS产品的5C特点

明道云

七年阿里升级路,熬到P7,想给正在成长的Java程序员一点建议

Java 程序员 后端

【设计模式系列14】组合模式及其在JDK和MyBatis源码中的运用

Java 程序员 后端

【设计模式系列24】GoF23种设计模式总结及软件设计7大原则

Java 程序员 后端

【面试准备】Spring框架面试题

Java 程序员 后端

一个简单的字符串,为什么-Redis-要设计的如此特别?

Java 程序员 后端

Java程序媛的秋招历程(附字节,阿里,百度,网易,美团等面经)

Java spring 程序员 面试 大厂

一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官

Java 程序员 后端

JDK16的新特性

程序那些事

Java 程序那些事 java16 11月日更 JDK16

【源码分析设计模式 10】SpringMVC中的适配器模式

Java 程序员 后端

《黑客之道》-- 网络安全之利用0day双杀-java环境-宏感染渗透

学神来啦

网络安全 漏洞 渗透 kali

一周4大厂Java开发岗面试日记(已拿offer)

Java 程序员 后端

一文看懂mybatis底层运行原理解析

Java 程序员 后端

【玩转Linux】史上最详细的Linux命令大全和线上问题排查手册

Java 程序员 后端

【程序人生】为什么Java开发人员在简历上不敢轻易写精通Java(1)

Java 程序员 后端

一个CURD三年的Java程序员刷完这份《阿里面试指南(恒山版)》

Java 程序员 后端

一文看懂 Redis 的持久化

Java 程序员 后端

万字长文!从底层开始带你了解并发编程,彻底帮你搞懂Java锁!

Java 程序员 后端

【消息队列最佳实践】消息恰好被消费一次

Java 程序员 后端

一文彻底帮你打通SpringAOP的任督二脉,大厂高薪指日可待,建议收藏!!!

Java 程序员 后端

学会了axios封装,世界都是你的

CRMEB

外包学生管理系统详细架构设计

stars

架构训练营

音频 AI 算法在 RTC 中的实践

网易云信

人工智能 算法 音视频

【程序人生】为什么Java开发人员在简历上不敢轻易写精通Java

Java 程序员 后端

存储大师班 | 浅谈 RDMA 与无损网络

QingStor分布式存储

网络 分布式存储

一文参透:缓存一致性策略以及雪崩、穿透等问题

Java 程序员 后端

一文快速搞懂Redis的几种数据类型

Java 程序员 后端

【消息队列最佳实践】消息恰好被消费一次(1)

Java 程序员 后端

一文带你快速搞懂动态字符串SDS,面试不再懵逼

Java 程序员 后端

【源码分析设计模式 9】SpringIOC中的模板方法模式

Java 程序员 后端

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