【Hello CSS】第二章-CSS的邏輯屬性與盒子模型

在上一篇【Hello CSS】的第一章CSS的語法與工做流中介紹了CSS的語法規則以及基本的渲染流程。本篇則會分享CSS的邏輯屬性以及盒子模型。javascript

首先開篇以前先提個問題:css

爲何Flex boxGrid box的是以startend爲排列規則,而不是常規的toprightbottomlefthtml

先不要急着往下翻,你們先思考一下。前端

這個問題的答案,魚頭會在文章中給出,歡迎你們帶着這個問題往下翻閱,若是已經知道答案,也能夠看看跟你們所知道的答案是否一致。java

CSS的邏輯屬性

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

對於前端來講,咱們一直習慣於使用toprightbottomleft來定義咱們的HTML元素,這跟咱們物理上的概念是一致的。可是對於CSS這個本來是爲了服務於圖文展現才誕生的語言來講,實際上是不匹配的,爲何這麼說?github

writing-mode

writing-mode:定義了文本水平或垂直排布以及在塊級元素中文本的行進方向。

writing-mode一共有如下5個改變HTML文本書寫規則的值(還有幾個是用在SVG上的,本文不予討論):算法

writing-mode: horizontal-tb;

writing-mode: horizontal-tb 定義了內容從左到右水平流動,從上到下垂直流動。下一條水平線位於上一條線下方。segmentfault

writing-mode: vertical-rl;

writing-mode: vertical-rl 定義了內容從上到下垂直流動,從右到左水平流動。下一條垂直線位於上一行的左側。瀏覽器

writing-mode: vertical-lr;

writing-mode: vertical-lr定義了內容從上到下垂直流動,從左到右水平流動。下一條垂直線位於上一行的右側。

writing-mode: sideways-rl; (僅Firefox41+實現)

writing-mode: sideways-rl定義了內容從上到下垂直流動,全部字形,甚至是垂直腳本中的字形,都設置在右側。

writing-mode: sideways-lr;(僅Firefox41+實現)

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>

圖示以下:
css_writing-mode

從上圖能夠發現,當咱們設置了padding-right: 100px;的時候,不一樣的書寫規則,展現效果是不同的。

在最開始的時候,HTMLCSS只服務於英語國家,可是隨着互聯網的發展,逐漸各個不一樣書寫規則的國家也開始流行了起來。

咱們原來的CSS邏輯屬性是按照物理邏輯,從上(top)、右(right)、下(bottom)、左(left)劃分的。

那麼按着這個規則去修改文本屬性時,就會出現上述這種不符合語法規則的狀態。

大概也是基於這個緣由,因此W3C發佈了新的邏輯屬性與值。

新舊邏輯屬性對比

CSS新舊邏輯屬性是徹底不一樣的兩種模型。

咱們首先來看看新舊有的邏輯屬性的對比圖示(圖片來自medium):
css_technique

左舊右新

經過上圖能夠得知新舊邏輯屬性對應關係以下:

舊的邏輯屬性 新的邏輯屬性
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軸方向的屬性都改成了blockX軸方向的屬性都改成了inline

對於不一樣語系的國家,書寫順序會可能有很大的差別,意思就是blockinline的方向不一樣。例如:

  • 在英語國家 padding-inline-start = padding-left
  • 在阿拉伯padding-inline-start = padding-right
  • 在日本 padding-inline-start = padding-top

這就意味着舊的邏輯屬性,在某些國家裏會變得不合常理。

CSS定位

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):
old_technique

new_technique

CSS浮動

浮動float的屬性也改了。

舊的邏輯屬性 新的邏輯屬性
float: left float: inline-start
float: right float: inline-end

text-align

文本text-align的屬性也改了。

舊的邏輯屬性 新的邏輯屬性
text-align: left text-align: start
text-align: right text-align: end

direction

除了writing-mode,還有一個排版屬性就是direction,跟writing-mode相似,不同的是writing-mode是控住網頁佈局方向的,而direction是控制文本對齊方向的。屬性以下:

direction: ltr;

默認值,讓文本和其餘元素從左到右顯示。

direction: rtl;

讓文本和其餘元素從右到左顯示。


吐槽一下,看到這裏的切圖仔們,抓緊 跑路 重構吧,等哪天此屬性正式被啓用,就真的GG了。不過我想應該會立個屬性來選擇性開啓物理屬性仍是邏輯屬性,否則這對前端來講將會是一場災難!

CSS的盒子模型

基礎盒模型(CSS basic box model)

當瀏覽器對一個render tree進行渲染時,瀏覽器的渲染引擎就會根據基礎盒模型(CSS basic box model),將全部元素劃分爲一個個矩形的盒子,這些盒子的外觀,屬性由CSS來決定。

咱們在瀏覽器控制檯輸入以下代碼就能夠看到頁面的每個元素都是由一個矩形來包裹的,這些就是盒子

$$('*').forEach(e => {
  e.style.border = '1px solid';
})

圖示以下:
css_box

每一個盒子都由四個部分組成:

內容(content)

盒子(box) 的內容,顯示標籤內一切的文本,圖案或者別的內容。

內邊距(padding)

盒子(box) 內的填充物,樣式爲透明,主要負責擴展盒子內區域大小。

外邊距(margin)

盒子(box) 外部的區域,樣式爲透明,負責隔離相鄰的元素。

邊框(border)

盒子(box) 的邊界,負責隔離外邊距以及內邊距。

盒子模型的值

盒子模型一共有三個值:

content-box

content-box爲標準的盒子模型。盒子的widthheight只包括盒子自己的widthheight屬性。

計算法則:

width = width

height = height

border-box

border-box爲盒子模型可選的屬性之一。盒子的widthheight包括contentpaddingborder。這也是當文檔處於 Quirks模式 時Internet Explorer使用的盒模型。

計算法則:

width = width + border + padding

height = height + border + padding

padding-box

padding-box爲非標準屬性,曾經在Firefox中實現過,可是在Firefox 50中被刪除。padding-boxwidthheight 屬性包括內容和內邊距,可是不包括邊框和外邊距。

圖示:

css_box-sizing

這裏吐槽一下,不知道爲什麼沒有margin-box,雖然並無太大意義,當真實現了效果估計也很詭異,可是做爲一個強迫症患者晚期,少了一個屬性總感受好不舒服。

視覺格式化模型(visual formatting model)

CSS視覺格式化模型(visual formatting model) 是根據 基礎盒模型(CSS basic box model)文檔(doucment) 中的元素轉換一個個盒子的實際算法。

官方說法就是:它規定了用戶端在媒介中如何處理文檔樹( document tree )。

每一個盒子的佈局由如下因素決定:

  • 盒子的尺寸
  • 盒子的類型:行內盒子 (inline)行內級盒子 (inline-level)原子行內級盒子 (atomic inline-level)塊盒子 (block)
  • 定位:普通流浮動絕對定位
  • 文檔樹中當前盒子的子元素兄弟元素
  • 視口(viewport)尺寸位置
  • 盒子內部圖片的尺寸
  • 其餘某些外部因素

視覺格式化模型(visual formatting model) 的計算,都取決於一個矩形的邊界,這個矩形,被稱做是 包含塊( containing block ) 。 通常來講,(元素)生成的框會扮演它子孫元素包含塊的角色;咱們稱之爲:一個(元素的)框爲它的子孫節點建造了包含塊。包含塊是一個相對的概念。

例子以下:

<div>
    <table>
        <tr>
            <td>hi</td>
        </tr>
    </table>
</div>

以上代碼爲例,divtable 都是包含塊。divtable 的包含塊,同時 table 又是 td 的包含塊,不是絕對的。

圖示:(圖片來自w3help):

css_containing_blocks

盒子的生成

盒子的生成是 CSS視覺格式化模型 的一部分,用於從文檔元素生成盒子。盒子的類型取決於 CSS display 屬性。
  • 塊級元素

    • 當元素的displayblocklist-itemtable 時,它就是塊級元素。
  • 塊級盒子

    • 塊級盒子用於描述它與父、兄弟元素之間的關係。
    • 每一個塊級盒子都會參與塊格式化上下文(block formatting context)的建立。
    • 每一個塊級元素都會至少生成一個塊級盒子,即主塊級盒子(principal block-level box)
    • 主塊級盒子包含由後代元素生成的盒子以及內容,同時它也會參與定位方案。
    • 一個同時是塊容器盒子的塊級盒子稱爲塊盒子(block box)
  • 匿名盒子

    • 某些狀況下須要進行視覺格式化時,須要添加一些增補性的盒子,這些盒子不能被CSS 選擇器選中,也就是全部可繼承的 CSS 屬性值都爲 inherit ,而全部不可繼承的 CSS 屬性值都爲 initial。所以稱爲匿名盒子(anonymous boxes)
  • 行內元素

    • 當元素的displayinlineinline-blockinline-table 時,它就是行內級元素。
    • 顯示時能夠與其餘行內級內容一塊兒顯示爲多行。
  • 行內盒子

    • 行內級元素會生成行內級盒子,該盒子同時會參與行內格式化上下文(inline formatting context)的建立。
  • 匿名行內盒子

    • 相似於塊盒子,CSS引擎有時候也會自動建立一些行內盒子。這些行內盒子沒法被選擇符選中,所以是匿名的,它們從父元素那裏繼承那些可繼承的屬性,其餘屬性保持默認值 initial
  • 行盒子

    • 行盒子由行內格式化上下文建立,用來顯示一行文本。在塊盒子內部,行盒子老是從塊盒子的一邊延伸到另外一邊(譯註:即佔據整個塊盒子的寬度)。當有浮動元素時,行盒子會從向左浮動的元素的右邊緣延伸到向右浮動的元素的左邊緣。
  • run-in 盒子(在CSS 2.1的標準中移除了)

    • run-in盒子能夠經過display: run-in來設置,它既能夠是塊盒子,又能夠是行內盒子,這取決於它後面的盒子的類型。

定位規則

一旦造成了盒子,CSS引擎就須要定位它們來完成佈局。

定位所使用的規則以下:

  • 普通流

    • 在普通流中,盒子會依次放置。
    • 塊格式化上下文(block formatting context)中,盒子在垂直方向依次排列。
    • 行內格式化上下文(inline formatting context) 中,盒子則水平擺列。
  • 浮動:當一個盒子的float不爲none,而且positionstaticrelative時,該盒子爲浮動定位。

    • float: left:盒子會定位到當前行盒子的開始位置(左側)。
    • float: right:盒子會定位到當前行盒子的尾部位置(右側)。
  • 絕對定位:若是元素的positionabsolutefixed,該元素爲絕對定位。

    • 在絕對定位中,盒子會徹底從當前流中移除,而且不會再與其有任何聯繫。

參考資料:

W3C 中國

New CSS Logical Properties!

w3help

視覺格式化模型(Visual formatting model)

MDN 視覺格式化模型

包含塊( Containing block )

結語

本篇文章主要介紹了CSS的新舊邏輯屬性的狀態以及盒子模型的具體狀況。文章內還有部份內容沒有進行太多的介紹,例如塊格式化上下文(block formatting context)行內格式化上下文(inline formatting context)以及其餘一些具體的名稱,這些後續的文章都將會進行介紹,到時候將會進行具體的講解,但願你們能夠多多關注魚頭個人【Hello CSS】系列

開頭時,魚頭我有問到你們一個問題,就是:

爲何Flex boxGrid box的是以startend爲排列規則,而不是常規的toprightbottomleft

這個問題,經過本篇文章的分享,你們有答案了嗎?

魚頭我將會在下一篇開頭時分享答案,但願你們多多留意本系列文章。

【Hello CSS】系列

【Hello CSS】是以CSS基礎概念爲主題的系列文章,旨在幫助你們更深入地瞭解而且提升CSS在各位開發者心目中的地位。因爲魚頭我水平有限,文筆有限,若是各位在文章中發現有任何不合理,不正確的地方,還煩不吝指出,我會很是感謝的;若是經過文章有任何想法或疑問,也但願各位能積極留言,咱們互相探討;若是經過本系列文章有所收穫,這就讓魚頭我喜不自勝了!

若是你也喜歡CSS,喜歡探討技術,或者對本文,本系列有任何的意見或建議,魚頭很是但願你能加入一個有趣的微信羣 — 「進擊的CSS」。你能夠掃描下方二維碼,添加魚頭微信,添加時註明 「加羣」,若是你以爲個人文章有趣,歡迎關注微信公衆號「魚頭的Web海洋」。衷心但願能夠碰見你。
css_modules

相關文章
相關標籤/搜索