- 做者:陳大魚頭
- github: KRISACHAN
在上一篇【Hello CSS】
的第一章CSS的語法與工做流中介紹了CSS
的語法規則以及基本的渲染流程。本篇則會分享CSS
的邏輯屬性以及盒子模型。javascript
首先開篇以前先提個問題:css
爲何Flex box
跟Grid box
的是以start
、end
爲排列規則,而不是常規的top
、right
、bottom
跟left
?html
先不要急着往下翻,你們先思考一下。前端
這個問題的答案,魚頭會在文章中給出,歡迎你們帶着這個問題往下翻閱,若是已經知道答案,也能夠看看跟你們所知道的答案是否一致。java
2017年5月18日,W3C的 CSS工做組(CSS Working Group) 發佈了 CSS邏輯屬性和值(CSS Logical Properties and Values Level 1) 的首份工做草案(First Public Working Draft)。不一樣的書寫模式(writing mode)中,能夠抽取出共性的抽象概念(如開始位置,或行),這些邏輯抽象概念須要在不一樣書寫模式下映射到左或右、上或下等物理的概念上。一些CSS佈局可能依賴這些共性的邏輯概念。該 CSS 模塊給出了用於經過邏輯方式(而不是基於物理座標、書寫方向和維映射等)控制佈局的邏輯屬性和取值(logical properties and values)。這個模塊來源於CSS21中關於邏輯屬性和值的特性。
上面複製粘貼了W3C 中國裏的內容。git
對於前端來講,咱們一直習慣於使用top
、 right
、 bottom
、 left
來定義咱們的HTML
元素,這跟咱們物理上的概念是一致的。可是對於CSS
這個本來是爲了服務於圖文展現才誕生的語言來講,實際上是不匹配的,爲何這麼說?github
writing-mode:定義了文本水平或垂直排布以及在塊級元素中文本的行進方向。
writing-mode
一共有如下5個改變HTML
文本書寫規則的值(還有幾個是用在SVG
上的,本文不予討論):算法
writing-mode: horizontal-tb
定義了內容從左到右水平流動,從上到下垂直流動。下一條水平線位於上一條線下方。segmentfault
writing-mode: vertical-rl
定義了內容從上到下垂直流動,從右到左水平流動。下一條垂直線位於上一行的左側。瀏覽器
writing-mode: vertical-lr
定義了內容從上到下垂直流動,從左到右水平流動。下一條垂直線位於上一行的右側。
writing-mode: sideways-rl
定義了內容從上到下垂直流動,全部字形,甚至是垂直腳本中的字形,都設置在右側。
writing-mode: sideways-lr
內容從上到下垂直流動,全部字形,甚至是垂直腳本中的字形,都設置在左側。
上述效果請看DEMO
源碼以下:
.wm-htb { writing-mode: horizontal-tb; } .wm-vrl { writing-mode: vertical-rl; } .wm-vlr { writing-mode: vertical-lr; } .wm-srl { writing-mode: sideways-rl; } .wm-slr { writing-mode: sideways-lr; } .text-content { width: 200px; padding: 20px; border: 1px solid; display: inline-block; vertical-align: top; padding-right: 100px; } <div class="text-content wm-htb">writing-mode: horizontal-tb;</div> <div class="text-content wm-vrl">writing-mode: vertical-rl;</div> <div class="text-content wm-vlr">writing-mode: vertical-lr;</div> <div class="text-content wm-srl">writing-mode: sideways-rl;</div> <div class="text-content wm-slr">writing-mode: sideways-lr;</div>
圖示以下:
從上圖能夠發現,當咱們設置了padding-right: 100px;
的時候,不一樣的書寫規則,展現效果是不同的。
在最開始的時候,HTML
與CSS
只服務於英語國家,可是隨着互聯網的發展,逐漸各個不一樣書寫規則的國家也開始流行了起來。
咱們原來的CSS
邏輯屬性是按照物理邏輯,從上(top)、右(right)、下(bottom)、左(left)劃分的。
那麼按着這個規則去修改文本屬性時,就會出現上述這種不符合語法規則的狀態。
大概也是基於這個緣由,因此W3C發佈了新的邏輯屬性與值。
CSS新舊邏輯屬性是徹底不一樣的兩種模型。
咱們首先來看看新舊有的邏輯屬性的對比圖示(圖片來自medium):
左舊右新
經過上圖能夠得知新舊邏輯屬性對應關係以下:
舊的邏輯屬性 | 新的邏輯屬性 |
---|---|
margin-top | margin-block-start |
margin-right | margin-inline-end |
margin-bottom | margin-block-end |
margin-left | margin-inline-start |
border-top | border-block-start |
border-right | border-inline-end |
border-bottom | border-block-end |
border-left | border-inline-start |
padding-top | padding-block-start |
padding-right | padding-inline-end |
padding-bottom | padding-block-end |
padding-left | padding-inline-start |
width | inline-size |
height | block-size |
由上表能夠得知,把Y軸方向的屬性都改成了block,X軸方向的屬性都改成了inline。
對於不一樣語系的國家,書寫順序會可能有很大的差別,意思就是block
跟inline
的方向不一樣。例如:
padding-inline-start
= padding-left
padding-inline-start
= padding-right
padding-inline-start
= padding-top
這就意味着舊的邏輯屬性,在某些國家裏會變得不合常理。
CSS
的定位屬性變化以下:
舊的邏輯屬性 | 新的邏輯屬性 |
---|---|
top | inset-block-start |
bottom | inset-block-end |
left | inset-inline-start |
right | inset-inline-end |
例子以下:
/* 舊的邏輯屬性 */ .popup{ position:fixed; top:0; bottom:0; left:0; right:0; } /* 新的邏輯屬性 */ .popup{ position:fixed; inset-block-start:0; /*top - in English*/ inset-block-end:0; /*bottom - in English*/ inset-inline-start:0; /*left - in English*/ inset-inline-end:0; /*right - in English*/ } /* 新的邏輯屬性支持簡寫 */ .popup{ position:fixed; inset:0 0 0 0; /*top, right, bottom, left - in English*/ }
圖示:(圖片來自medium):
浮動float
的屬性也改了。
舊的邏輯屬性 | 新的邏輯屬性 |
---|---|
float: left | float: inline-start |
float: right | float: inline-end |
文本text-align
的屬性也改了。
舊的邏輯屬性 | 新的邏輯屬性 |
---|---|
text-align: left | text-align: start |
text-align: right | text-align: end |
除了writing-mode
,還有一個排版屬性就是direction
,跟writing-mode
相似,不同的是writing-mode
是控住網頁佈局方向的,而direction
是控制文本對齊方向的。屬性以下:
默認值,讓文本和其餘元素從左到右顯示。
讓文本和其餘元素從右到左顯示。
吐槽一下,看到這裏的切圖仔們,抓緊 跑路 重構吧,等哪天此屬性正式被啓用,就真的GG了。不過我想應該會立個屬性來選擇性開啓物理屬性仍是邏輯屬性,否則這對前端來講將會是一場災難!
當瀏覽器對一個render tree進行渲染時,瀏覽器的渲染引擎就會根據基礎盒模型(CSS basic box model),將全部元素劃分爲一個個矩形的盒子,這些盒子的外觀,屬性由CSS
來決定。
咱們在瀏覽器控制檯輸入以下代碼就能夠看到頁面的每個元素都是由一個矩形來包裹的,這些就是盒子
$$('*').forEach(e => { e.style.border = '1px solid'; })
圖示以下:
每一個盒子都由四個部分組成:
盒子(box) 的內容,顯示標籤內一切的文本,圖案或者別的內容。
盒子(box) 內的填充物,樣式爲透明,主要負責擴展盒子內區域大小。
盒子(box) 外部的區域,樣式爲透明,負責隔離相鄰的元素。
盒子(box) 的邊界,負責隔離外邊距以及內邊距。
盒子模型一共有三個值:
content-box
爲標準的盒子模型。盒子的width
跟height
只包括盒子自己的width
與height
屬性。
計算法則:
width = width
height = height
border-box
爲盒子模型可選的屬性之一。盒子的width
跟height
包括content
、padding
跟border
。這也是當文檔處於 Quirks模式 時Internet Explorer使用的盒模型。
計算法則:
width = width + border + padding
height = height + border + padding
padding-box
爲非標準屬性,曾經在Firefox中實現過,可是在Firefox 50中被刪除。padding-box
的width
和height
屬性包括內容和內邊距,可是不包括邊框和外邊距。
圖示:
這裏吐槽一下,不知道爲什麼沒有margin-box,雖然並無太大意義,當真實現了效果估計也很詭異,可是做爲一個強迫症患者晚期,少了一個屬性總感受好不舒服。
CSS
的 視覺格式化模型(visual formatting model) 是根據 基礎盒模型(CSS basic box model) 將 文檔(doucment) 中的元素轉換一個個盒子的實際算法。官方說法就是:它規定了用戶端在媒介中如何處理文檔樹( document tree )。
每一個盒子的佈局由如下因素決定:
視覺格式化模型(visual formatting model) 的計算,都取決於一個矩形的邊界,這個矩形,被稱做是 包含塊( containing block ) 。 通常來講,(元素)生成的框會扮演它子孫元素包含塊的角色;咱們稱之爲:一個(元素的)框爲它的子孫節點建造了包含塊。包含塊是一個相對的概念。
例子以下:
<div> <table> <tr> <td>hi</td> </tr> </table> </div>
以上代碼爲例,div
和 table
都是包含塊。div
是 table
的包含塊,同時 table
又是 td
的包含塊,不是絕對的。
圖示:(圖片來自w3help):
盒子的生成是
CSS視覺格式化模型 的一部分,用於從文檔元素生成盒子。盒子的類型取決於
CSS display
屬性。
塊級元素
display
爲 block
、list-item
或 table
時,它就是塊級元素。塊級盒子
匿名盒子
CSS 選擇器
選中,也就是全部可繼承的 CSS 屬性值都爲 inherit
,而全部不可繼承的 CSS 屬性值都爲 initial
。所以稱爲匿名盒子(anonymous boxes)。行內元素
display
爲 inline
、inline-block
或 inline-table
時,它就是行內級元素。行內盒子
行內格式化上下文(inline formatting context)
的建立。匿名行內盒子
initial
。行盒子
run-in 盒子(在CSS 2.1的標準中移除了)
display: run-in
來設置,它既能夠是塊盒子,又能夠是行內盒子,這取決於它後面的盒子的類型。一旦造成了盒子,CSS引擎就須要定位它們來完成佈局。
定位所使用的規則以下:
普通流
浮動:當一個盒子的float
不爲none
,而且position
爲static
或relative
時,該盒子爲浮動定位。
float: left
:盒子會定位到當前行盒子的開始位置(左側)。float: right
:盒子會定位到當前行盒子的尾部位置(右側)。絕對定位:若是元素的position
爲 absolute
或 fixed
,該元素爲絕對定位。
視覺格式化模型(Visual formatting model)
本篇文章主要介紹了CSS
的新舊邏輯屬性的狀態以及盒子模型的具體狀況。文章內還有部份內容沒有進行太多的介紹,例如塊格式化上下文(block formatting context) 跟 行內格式化上下文(inline formatting context)以及其餘一些具體的名稱,這些後續的文章都將會進行介紹,到時候將會進行具體的講解,但願你們能夠多多關注魚頭個人【Hello CSS】系列。
開頭時,魚頭我有問到你們一個問題,就是:
爲何Flex box
跟Grid box
的是以start
、end
爲排列規則,而不是常規的top
、right
、bottom
跟left
?
這個問題,經過本篇文章的分享,你們有答案了嗎?
魚頭我將會在下一篇開頭時分享答案,但願你們多多留意本系列文章。
【Hello CSS】
是以CSS
基礎概念爲主題的系列文章,旨在幫助你們更深入地瞭解而且提升CSS
在各位開發者心目中的地位。因爲魚頭我水平有限,文筆有限,若是各位在文章中發現有任何不合理,不正確的地方,還煩不吝指出,我會很是感謝的;若是經過文章有任何想法或疑問,也但願各位能積極留言,咱們互相探討;若是經過本系列文章有所收穫,這就讓魚頭我喜不自勝了!
若是你也喜歡CSS
,喜歡探討技術,或者對本文,本系列有任何的意見或建議,魚頭很是但願你能加入一個有趣的微信羣 — 「進擊的CSS」。你能夠掃描下方二維碼,添加魚頭微信,添加時註明 「加羣」,若是你以爲個人文章有趣,歡迎關注微信公衆號「魚頭的Web海洋」。衷心但願能夠碰見你。