關於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會報錯?
一個瀏覽器是如何工作的?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章