首先開篇之前先提個問題:
為什么Flex box
跟Grid box
的是以start
、end
為排列規(guī)則楷掉,而不是常規(guī)的top
厢蒜、right
、bottom
跟left
烹植?
先不要急著往下翻斑鸦,大家先思考一下。
這個問題的答案刊橘,魚頭會在文章中給出鄙才,歡迎大家?guī)е@個問題往下翻閱,如果已經(jīng)知道答案促绵,也可以看看跟大家所知道的答案是否一致攒庵。
CSS的邏輯屬性
2017年5月18日,W3C的 CSS工作組(CSS Working Group) 發(fā)布了 CSS邏輯屬性和值(CSS Logical Properties and Values Level 1) 的首份工作草案(First Public Working Draft)败晴。不同的書寫模式(writing mode)中浓冒,可以抽取出共性的抽象概念(如開始位置,或行)尖坤,這些邏輯抽象概念需要在不同書寫模式下映射到左或右稳懒、上或下等物理的概念上。一些CSS布局可能依賴這些共性的邏輯概念慢味。該 CSS 模塊給出了用于通過邏輯方式(而不是基于物理坐標场梆、書寫方向和維映射等)控制布局的邏輯屬性和取值(logical properties and values)。這個模塊來源于CSS21中關(guān)于邏輯屬性和值的特性纯路。
對于前端來說或油,我們一直習慣于使用top
、 right
驰唬、 bottom
顶岸、 left
來定義我們的HTML
元素腔彰,這跟我們物理上的概念是一致的。但是對于CSS
這個原本是為了服務(wù)于圖文展示才誕生的語言來說辖佣,其實是不匹配的霹抛,為什么這么說?
writing-mode
writing-mode:定義了文本水平或垂直排布以及在塊級元素中文本的行進方向卷谈。
writing-mode
一共有以下5個改變HTML
文本書寫規(guī)則的值(還有幾個是用在SVG
上的杯拐,本文不予討論):
writing-mode: horizontal-tb;
writing-mode: horizontal-tb
定義了內(nèi)容從左到右水平流動,從上到下垂直流動雏搂。下一條水平線位于上一條線下方藕施。
writing-mode: vertical-rl;
writing-mode: vertical-rl
定義了內(nèi)容從上到下垂直流動寇损,從右到左水平流動凸郑。下一條垂直線位于上一行的左側(cè)。
writing-mode: vertical-lr;
writing-mode: vertical-lr
定義了內(nèi)容從上到下垂直流動矛市,從左到右水平流動芙沥。下一條垂直線位于上一行的右側(cè)。
writing-mode: sideways-rl; (僅Firefox41+實現(xiàn))
writing-mode: sideways-rl
定義了內(nèi)容從上到下垂直流動浊吏,所有字形而昨,甚至是垂直腳本中的字形,都設(shè)置在右側(cè)找田。
writing-mode: sideways-lr;(僅Firefox41+實現(xiàn))
writing-mode: sideways-lr
內(nèi)容從上到下垂直流動歌憨,所有字形,甚至是垂直腳本中的字形墩衙,都設(shè)置在左側(cè)务嫡。
源碼如下:
.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>
web前端開發(fā)學習Q-q-u-n: 731771211,分享學習的方法和需要注意的小細節(jié)漆改,不停更新最新的教程和學習方法(詳細的前端項目實戰(zhàn)教學視頻心铃,PDF)
圖示如下:
從上圖可以發(fā)現(xiàn),當我們設(shè)置了padding-right: 100px;
的時候挫剑,不同的書寫規(guī)則去扣,展示效果是不一樣的。
在最開始的時候樊破,HTML
與CSS
只服務(wù)于英語國家愉棱,但是隨著互聯(lián)網(wǎng)的發(fā)展,逐漸各個不同書寫規(guī)則的國家也開始流行了起來哲戚。
我們原來的CSS
邏輯屬性是按照物理邏輯奔滑,從上(top)、右(right)惫恼、下(bottom)档押、左(left)劃分的。
那么按著這個規(guī)則去修改文本屬性時,就會出現(xiàn)上述這種不符合語法規(guī)則的狀態(tài)令宿。
大概也是基于這個原因叼耙,所以W3C發(fā)布了新的邏輯屬性與值。
新舊邏輯屬性對比
CSS新舊邏輯屬性是完全不同的兩種模型粒没。
我們首先來看看新舊有的邏輯屬性的對比圖示:
左舊右新
通過上圖可以得知新舊邏輯屬性對應(yīng)關(guān)系如下:
舊的邏輯屬性 | 新的邏輯屬性 |
---|---|
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定位
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*/
}
web前端開發(fā)學習Q-q-u-n: 731771211枫甲,分享學習的方法和需要注意的小細節(jié)源武,不停更新最新的教程和學習方法(詳細的前端項目實戰(zhàn)教學視頻,PDF)
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
是控住網(wǎng)頁布局方向的,而direction
是控制文本對齊方向的食店。屬性如下:
direction: ltr;
默認值渣淤,讓文本和其他元素從左到右顯示。
direction: rtl;
讓文本和其他元素從右到左顯示叛买。
吐槽一下砂代,看到這里的切圖仔們,抓緊 跑路 重構(gòu)吧率挣,等哪天此屬性正式被啟用刻伊,就真的GG了。不過我想應(yīng)該會立個屬性來選擇性開啟物理屬性還是邏輯屬性椒功,不然這對前端來說將會是一場災(zāi)難捶箱!
CSS的盒子模型
基礎(chǔ)盒模型(CSS basic box model)
當瀏覽器對一個render tree進行渲染時,瀏覽器的渲染引擎就會根據(jù)基礎(chǔ)盒模型(CSS basic box model)动漾,將所有元素劃分為一個個矩形的盒子丁屎,這些盒子的外觀,屬性由CSS
來決定旱眯。
我們在瀏覽器控制臺輸入如下代碼就可以看到頁面的每一個元素都是由一個矩形來包裹的晨川,這些就是盒子
$$('*').forEach(e => {
e.style.border = '1px solid';
})
圖示如下:
每個盒子都由四個部分組成:
內(nèi)容(content)
盒子(box) 的內(nèi)容证九,顯示標簽內(nèi)一切的文本,圖案或者別的內(nèi)容共虑。
內(nèi)邊距(padding)
盒子(box) 內(nèi)的填充物愧怜,樣式為透明,主要負責擴展盒子內(nèi)區(qū)域大小妈拌。
外邊距(margin)
盒子(box) 外部的區(qū)域拥坛,樣式為透明,負責隔離相鄰的元素尘分。
邊框(border)
盒子(box) 的邊界猜惋,負責隔離外邊距以及內(nèi)邊距。
盒子模型的值
盒子模型一共有三個值:
content-box
content-box
為標準的盒子模型培愁。盒子的width
跟height
只包括盒子本身的width
與height
屬性著摔。
計算法則:
width = width
height = height
border-box
border-box
為盒子模型可選的屬性之一。盒子的width
跟height
包括content
竭钝、padding
跟border
梨撞。這也是當文檔處于 Quirks模式 時Internet Explorer使用的盒模型雹洗。
計算法則:
width = width + border + padding
height = height + border + padding
padding-box
padding-box
為非標準屬性香罐,曾經(jīng)在Firefox中實現(xiàn)過,但是在Firefox 50中被刪除时肿。padding-box
的width
和height
屬性包括內(nèi)容和內(nèi)邊距庇茫,但是不包括邊框和外邊距。
圖示:
這里吐槽一下螃成,不知道為何沒有margin-box旦签,雖然并沒有太大意義,當真實現(xiàn)了效果估計也很詭異寸宏,但是作為一個強迫癥患者晚期宁炫,少了一個屬性總感覺好不舒服。
視覺格式化模型(visual formatting model)
CSS
的視覺格式化模型(visual formatting model) 是根據(jù) 基礎(chǔ)盒模型(CSS basic box model) 將 文檔(doucment) 中的元素轉(zhuǎn)換一個個盒子的實際算法氮凝。官方說法就是:它規(guī)定了用戶端在媒介中如何處理文檔樹( document tree )羔巢。
每個盒子的布局由以下因素決定:
- 盒子的尺寸
- 盒子的類型:行內(nèi)盒子 (inline)、行內(nèi)級盒子 (inline-level)罩阵、原子行內(nèi)級盒子 (atomic inline-level)竿秆、塊盒子 (block)
- 定位:普通流、浮動稿壁、絕對定位
- 文檔樹中當前盒子的子元素 或 兄弟元素
- 視口(viewport) 的尺寸 和位置
- 盒子內(nèi)部圖片的尺寸
- 其他某些外部因素
視覺格式化模型(visual formatting model) 的計算幽钢,都取決于一個矩形的邊界,這個矩形傅是,被稱作是 包含塊( containing block ) 匪燕。 一般來說蕾羊,(元素)生成的框會扮演它子孫元素包含塊的角色;我們稱之為:一個(元素的)框為它的子孫節(jié)點建造了包含塊帽驯。包含塊是一個相對的概念肚豺。
例子如下:
<div>
<table>
<tr>
<td>hi</td>
</tr>
</table>
</div>
web前端開發(fā)學習Q-q-u-n: 731771211,分享學習的方法和需要注意的小細節(jié)界拦,不停更新最新的教程和學習方法(詳細的前端項目實戰(zhàn)教學視頻吸申,PDF)
以上代碼為例,div
和 table
都是包含塊享甸。div
是 table
的包含塊截碴,同時 table
又是 td
的包含塊,不是絕對的蛉威。
盒子的生成
盒子的生成是 CSS視覺格式化模型 的一部分日丹,用于從文檔元素生成盒子。盒子的類型取決于
CSS display
屬性蚯嫌。
-
塊級元素
- 當元素的
display
為block
哲虾、list-item
或table
時,它就是塊級元素择示。
- 當元素的
-
塊級盒子
- 塊級盒子用于描述它與父束凑、兄弟元素之間的關(guān)系。
- 每個塊級盒子都會參與塊格式化上下文(block formatting context)的創(chuàng)建栅盲。
- 每個塊級元素都會至少生成一個塊級盒子汪诉,即主塊級盒子(principal block-level box)
- 主塊級盒子包含由后代元素生成的盒子以及內(nèi)容,同時它也會參與定位方案谈秫。
- 一個同時是塊容器盒子的塊級盒子稱為塊盒子(block box)扒寄。
-
匿名盒子
- 某些情況下需要進行視覺格式化時,需要添加一些增補性的盒子拟烫,這些盒子不能被
CSS 選擇器
選中该编,也就是所有可繼承的 CSS 屬性值都為inherit
,而所有不可繼承的 CSS 屬性值都為initial
硕淑。因此稱為匿名盒子(anonymous boxes)课竣。
- 某些情況下需要進行視覺格式化時,需要添加一些增補性的盒子拟烫,這些盒子不能被
-
行內(nèi)元素
- 當元素的
display
為inline
、inline-block
或inline-table
時喜颁,它就是行內(nèi)級元素稠氮。 - 顯示時可以與其他行內(nèi)級內(nèi)容一起顯示為多行。
- 當元素的
-
行內(nèi)盒子
- 行內(nèi)級元素會生成行內(nèi)級盒子半开,該盒子同時會參與
行內(nèi)格式化上下文(inline formatting context)
的創(chuàng)建隔披。
- 行內(nèi)級元素會生成行內(nèi)級盒子半开,該盒子同時會參與
-
匿名行內(nèi)盒子
- 類似于塊盒子,CSS引擎有時候也會自動創(chuàng)建一些行內(nèi)盒子寂拆。這些行內(nèi)盒子無法被選擇符選中奢米,因此是匿名的抓韩,它們從父元素那里繼承那些可繼承的屬性,其他屬性保持默認值
initial
鬓长。
- 類似于塊盒子,CSS引擎有時候也會自動創(chuàng)建一些行內(nèi)盒子寂拆。這些行內(nèi)盒子無法被選擇符選中奢米,因此是匿名的抓韩,它們從父元素那里繼承那些可繼承的屬性,其他屬性保持默認值
-
行盒子
- 行盒子由行內(nèi)格式化上下文創(chuàng)建谒拴,用來顯示一行文本。在塊盒子內(nèi)部涉波,行盒子總是從塊盒子的一邊延伸到另一邊(譯注:即占據(jù)整個塊盒子的寬度)英上。當有浮動元素時,行盒子會從向左浮動的元素的右邊緣延伸到向右浮動的元素的左邊緣啤覆。
-
run-in 盒子(在CSS 2.1的標準中移除了)
- run-in盒子可以通過
display: run-in
來設(shè)置苍日,它既可以是塊盒子,又可以是行內(nèi)盒子窗声,這取決于它后面的盒子的類型相恃。
- run-in盒子可以通過
定位規(guī)則
一旦形成了盒子,CSS引擎就需要定位它們來完成布局笨觅。
定位所使用的規(guī)則如下:
-
普通流
- 在普通流中拦耐,盒子會依次放置。
- 在塊格式化上下文(block formatting context)中见剩,盒子在垂直方向依次排列杀糯。
- 在行內(nèi)格式化上下文(inline formatting context) 中,盒子則水平擺列炮温。
-
浮動:當一個盒子的
float
不為none
火脉,并且position
為static
或relative
時,該盒子為浮動定位柒啤。-
float: left
:盒子會定位到當前行盒子的開始位置(左側(cè))。 -
float: right
:盒子會定位到當前行盒子的尾部位置(右側(cè))畸颅。
-
-
絕對定位:如果元素的
position
為absolute
或fixed
担巩,該元素為絕對定位。- 在絕對定位中没炒,盒子會完全從當前流中移除涛癌,并且不會再與其有任何聯(lián)系。