在2020年歲末有幸和一羣優秀大學生在一塊兒聊CSS相關的話題,感到很是的榮幸!在此很是感謝平臺(阿里巴巴集團.前端練習生計劃)給我這樣的機會,同時也要很是感謝好友 裕波,墨苒對個人鼓勵和支持。在結束直播的時候,說事後面要整理一篇文字版本,因爲我的新轉團隊(互動團隊轉到 F(x) Team團隊),加上本身太懶,因此今天才開始整理文字版本。所幸能在歲末完成,還算是一種補救。但願接下來的內容,對於新接觸CSS或對CSS感興趣的同窗有所幫助,更但願有更多的同窗能參與阿里巴巴集團練習生計劃的學習,並有所獲。css
雖然之前也參加過一些前端行業的會議分享,但在線直播仍是生平第一次,感受仍是很不一樣。其一沒有這方面的經驗,其二我仍是更喜歡線下會議的感受,由於這樣能和你們在一塊兒,有目光的交流。這是一種支持,一種鼓勵,一種鍛鍊,也是一種幸福。html
在前端社區中,你們常稱我「大漠」。我我的比較喜歡CSS,在這個領域深耕了近十年,雖無大的成就,但有所小收穫。我的平時比較宅,愛寫寫博客,看看電影,聽聽音樂等。前端
在2014年出版了一本有關於CSS方面的的書:git
好像如今沒有加印了,網上好象尚未停售,但內容有點偏老,不過還沒過期!github
在手淘互動呆了五年,最近剛到淘系前端技術F(x) Team團隊:編程
F(x) Team ,F(x) 指函數 F(x) ,是機器學習中常出現的符號,深度學習的本質也是求 f(x) 的最優解; 意味擁有不一樣特徵的成員通過 fx 團隊神奇做⽤,不斷「訓練」,⼀起找到前端智能化團隊的最優解。瀏覽器
接下來和你們圍繞着這六個方面和你們聊今天的話題。markdown
自從1994年萬維網之父蒂姆.伯納斯-李在美國麻省理工學院創立了萬維網(W3C),至今天也有幾十年了。你可能會感到好奇,當初的的第一個網頁長得像什麼:框架
和今天你所看到的Web頁面是否是相差十萬八千里。有這種見解是正確的,在那個時候,對於Web頁面而言,並無什麼樣式一說,並且那個時候Web頁面所承擔的也就是信息的傳遞。再簡單地說,他只有文字和圖像兩種,並無其餘的信息元素。機器學習
人老是愛漂亮的,即便是在那個年代,人們也想讓本身構建的Web頁面看上去更美。就在同年(1994年),哈肯.維姆.萊 提出層疊HTML樣式表(Cascading HTML Style Sheets,CHSS):
在HTML的標籤上新增了一些屬性,好比 bgcolor 、 face 等,也有一些相似 標籤來設置文本樣式。
時至今日估計不多有人接觸過,或者這樣寫過Web頁面。就我我的而言,雖沒有使用這些東西來構建Web頁面,但仍是看到過不少頁面長成這樣。那時候我並不知道,原來這種技術也有本身的專業術語,即 CHSS ( 層疊HTML樣式表 )。雖然說這些標籤和屬性能讓頁面上的元素有一些個性化的UI效果,好比改變文本顏色,字體,背景色之類的,但這樣的寫法對於Web開發者來講是痛苦的,特別對於一個複雜,大型的Web應用,這樣的方式來美化Web頁面,絕對會讓你痛苦難堪。
不說別的,最起碼這種方式增長了代碼的維護難度,同時也讓代碼變得臃腫。更沒有什麼靈活性,可擴展性,可用性一說了。
咱們這一批Web開發者是幸運的。就在1994年,哈肯.維姆.萊 和 伯特.波斯合做設計CSS,並在芝加哥的一次會議上展現了CSS的建議。這也是CSS第一次出如今Web開發者(不過,那個時候並無這個職稱)眼中。並且在兩年以後,CSS 1.0的規範出來了:
並且經歷兩年的發展,有了CSS2.0版本,在這以後,還經歷了CSS 2.1和CSS 2.2版本的迭代。同時CSS 2.1規範指導Web開發者寫CSS不少年。直到後面,也就是大約2015年,W3C規劃的CSS工做小組發現CSS發展的愈來愈快,有關於CSS方面的特性增長了很多,並且不一樣的特性推動速度都有所不一樣。也就這個時候,W3C的CSS工做小組爲了能更好的維護和管理CSS的特性,該組織決定不在以CSS的版本號,好比咱們熟悉的CSS1.0、CSS2.0、CSS2.1這樣的方式來管理CSS。而是將每一個CSS功能特性拆分紅獨立的功能模塊,而且以Level 1, Level2,Level 3等方式來管理CSS規範中的特性:
正如上圖所示,即便CSS按功能模塊拆分向前推動,但也並不表明拆分以後的CSS特性模塊就能很快的進入到正式的標準規範中,就比如CSS2.0到正式進入標準規範也歷時很長。這主要是由於,任何一個CSS的特性到成爲真正的規範要經歷多個階段:
這個時候你可能已經感受到了,一個東東到成爲正式規範是多麼漫長的。這個漫長的過程除了W3C規範組織本身的問題,也還有客戶端廠商爲了各自的利益,在特性的支持上也有所不一樣。對於咱們這些Web開發者來講也是有問題,由於大家更多的時候只是CSS特性的使用者或者說佈道者,但並非推進者。對於咱們身在國內的Web開發者而言,不多有人直接參與CSS特性的制定,討論和推動。
在CSS 選擇器 Level4模塊出來的時候,社區開始有CSS4這個說法。事實上呢,早在2016年 @Rachelandrew就在社區中發聲過《Why there is no CSS4 - explaining CSS Levels》:
在Github上@Jen Simmons 在 CSSWG Drafts上單獨開了一個關於CSS4相關的帖子,社區中一些大神都對這個話題發表了本身的觀點:
上面主要和你們聊了CSS的歷史以及她的發展歷程。
聊完CSS發展以後,咱們來再來聊聊CSS的現狀。從2019年和2020年CSS發展狀態報告中,咱們就能夠看到CSS發展的一個現狀:
這份報告相對於來講仍是比較詳細的:
除了對CSS特性、單位和選擇器、方法論、框架、工具、環境等有統計以外,還對使用CSS的人羣及現狀也有描述,好比:
除了CSS狀態發展報告以外,還有每一年的Web年鑑對CSS也會有相應的調查統計:
另外,還有一些其餘的調查報告也會有一些CSS相關的報告,但都沒有CSS狀態發展報告這樣詳細和針對性。若是你對其餘報告中關於CSS方面的調查分析,能夠閱讀 @Geoff Graham 的《2020 Roundup of Web Research》一文中列出的報告中查閱:
CSS稱爲 層疊樣式表,便是 Cascade Style Sheets三個詞的首字母縮寫。每一個字母表明的含義不一樣:
Web開發者都知道,一個Web頁面或Web應用都由HTML、CSS和JavaScript三個部分組成:
每一個部分在Web中所起的做用都有所不同:
時至今日,Web應用或Web頁面除了咱們上面所說的HTML、CSS、JavaScript三個部分組成以外,它還有一個新的部分,即 WAI-ARIA :
WAI-ARIA 是Web可訪問性(A11Y)規範中的一部分,主要用來幫助咱們構建一個更具可訪問性的Web應用。
對於初次接觸CSS的同窗來講,確定會感到好奇,CSS是如何工做的。要詳細的講清楚,那所涉及到的東西就多了,其中就少不了關於 瀏覽器工做原理 相關的內容。這方面也不是我擅長的領域,我只能在此拋磚引玉。
前面提到過,Web頁面至少由HTML、CSS和JavaScript三個部分構成,其中HTML會通過HTML Parser將HTML結構轉換成DOM Tree;CSS會通過CSS Parser將CSS轉換成CSSOM Tree,正以下圖所示:
DOM樹和CSSOM樹將會構建出渲染樹:
最終通過幾個過程就渲染出咱們所能看到的Web頁面:
若是再把AOM(可訪問樹)引入起來的話,大體就像下圖這樣:
這有點偏離咱們今天要聊的主題了。若是你其中過程不想了解太多的話,只須要簡單地記做:「CSS樣式要和相應的HTML元素結合在一塊兒使用,才能在瀏覽器渲染出來,呈現給用戶」。
就我我的而言,我更喜歡把CSS稱爲七巧板或積木:
實現同一效果,咱們能夠經過多種不一樣方式來完成。
也正由於如此,不少同窗都認爲CSS很煩人:
@Jeremy Keith 在2017年的CSS Day 大會說過:
大體意思是:
CSS與其編程語言不一樣,她沒有循環、邏輯和其餘概念,它只是聲明式的語言,所以,CSS很容易上手。也許正是由於如此,它纔得到了簡單的美譽。在 "不復雜 "的意義上,它是簡單的,但這並不意味着它很容易。把 "簡單 "誤認爲是 「容易」,只會讓人心痛」
就此話題,在Twitter上,或者在社區時不時的就會有所爭論:
有時候在Twitter上你也會感到,原來全世界的前端圈都像是個娛樂圈!
那麼爲何會有這些爭論呢?爲此我講講我本身對這方面的見解。
先上一張圖:
若是從CSS的語法規則和屬性的使用上來講,它的確很是地簡單,由於你只須要知道選擇器選中了HTML中的哪一個元素,給他運用了什麼樣的屬性和值,應該能在瀏覽器中呈現出來,好比:
body {
color: #fff;
background-color: #09f;
}
複製代碼
上面幾行簡單的CSS代碼,就可讓你在瀏覽器中看到一個藍底白字的效果:
並且也不須要一個一個把全部CSS屬性及屬性的值都記在腦中,由於咱們有不少方式能夠查閱到,好比MDN上就有CSS屬性列表:
這就是爲何說CSS簡單的主要緣由。
那麼爲何說CSS不容易呢?這是有不少緣由的,先拿你們認爲CSS簡單的規則來講:
<div class="card">1</div>
<div class="card__news">2</div>
.card {
width: 100px;
}
.card.card__news {
width: 100%;
}
複製代碼
想象一下,這兩個 div 的 width 分別是什麼呢?試問一下,你本身一看到上面的代碼能自信,立刻的說出正確的答案?若是你心理想的答案和本身驗證獲得的答案是一致的,那麼恭喜你,你對CSS有必定的認知,至少不是菜鳥級。那麼請繼續往下看這個示例:
<div class="a">Text</div>
<div class="b">Text</div>
<div class="a b">Text</div>
<div class="b a">Text</div>
.a {
color: red;
}
.b {
color: blue;
}
.a.b {
color: orange;
}
.b.a {
color: yellow;
}
複製代碼
試問這四個 div 的文本顏色分本是什麼?印象中 @Max Stoiber 在twitter上也出過相似的一個問卷:
就此題可讓很多同窗感到困惑。除此以外,CSS中還有不少基本概念,可讓你再也不以爲CSS容易,好比:
上面列的這些基礎概念,每個都須要一篇或多篇長文才能完全講清楚。因此我只能在此爲你們拋磚引玉,並在相應的內容上多附上相關知識點的連接。感興趣的同窗,能夠點擊相應的連接進行擴展閱讀。
CSS的層疊
按照前面的解釋,層疊是指「Cascade」,拿個示例來解說可能會更易於理解。好比咱們在一個 style.css 樣式文件中,對同一個元素寫了兩個樣式規則:
<a href="#" class="link">Link</a>
a {
color: #90f;
}
.link {
color: #f36;
}
複製代碼
a 先於 .link 出現,就是對同一元素使用的樣式規則出現的前後順序,被稱爲層疊。
事實上,CSS中的層疊要比這個更爲複雜,除了前面示例中提到的樣式規則出現的順序還有另外一種層疊之說,它會涉及到CSS其餘的一些概念,好比說:
也基於這個緣由,我把CSS中的層疊分爲兩個部分來闡述:
先來講第一部分的。
文檔流
在CSS中,文檔流是一個很基礎也是很重要的一個概念。不少時候她被稱爲Document Flow,但在CSS的標準被稱爲Normal Flow,即普通流或常規流。你們更喜歡稱之爲文檔流。那麼CSS的文檔流是怎麼一回事呢?
在HTML中任何一個元素其實就是一個對象,也是一個盒子。在默認狀況下它是按照出現的前後順序來排列,而這個排列的順序就是文檔流。
文檔流是元素在Web頁面上的一種呈現方式。全部的HTML元素都是塊盒子(Block Boxes,塊級元素)或行內框(Inline Boxes,行內元素)。當瀏覽器開始渲染HTML文檔時,它從窗口的頂端開始,通過整個文檔內容的過程當中,分配元素須要的空間。除非文檔的尺寸被CSS規則限定,不然瀏覽器垂直擴展文檔來容納所有的內容。每一個新的塊級元素渲染爲新行。行內元素則按照順序被水平渲染直到當前行遇到邊界,而後換到下一行垂直渲染。
事實上,在普通文檔流中的盒子屬於一種格式化上下文(Formatting Context),你們較爲熟悉的就是塊格式化上下文(Block formatting context)和行內格式化上下文(Inline formatting context)。不過有一點面要注意,它們只能是其中一者,但不能同時屬於二者。言外之意,任何被渲染的HTML元素都是一個盒子(Box),這些盒子不是塊盒子就是行內盒子。即便是未被任何元素包裹的文本,根據不一樣的狀況,也會屬於匿名的塊盒子或行內盒子。
綜合上面的描述,也能夠理解格式化上下文對元素盒子作了必定的範圍的限制,其實就是相似有一個width和height作了限制同樣。若是從這方面來理解的話,普通流就是這樣的一個過程:
扯了這麼多,若是簡單的描述就是:如何排列HTML元素而已。拿個塊格式化上下文的普通文檔流來舉例,就像下面這樣:
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
複製代碼
對應的效果以下:
格式化上下文
前面屢次提到 格式化上下文 ,在CSS中,格式化上下文指的是:
初始元素定義的環境
其主要包含兩個要點,一個是 元素定義的環境 ,另外一個是 初始化。
咱們使用CSS的 display 屬性能夠對元素進行格式化,即 建立格式化上下文 。
使用 display 對元素進行格式化以後,能夠把內容裝置在不一樣的容器中,比如咱們生活中的器皿同樣,不一樣的器皿能夠看到不一樣的效果:
來看一個簡單的示列:
上圖中最大的差別就是左側中的 ul 未顯式設置 display: contents ;右側中的 ul 顯式設置了 display: contents ,設置了 display: contents 會改變原有的格式,即其子元素 li 都會變成網格項目,二者效果差別以下:
層疊上下文
平時咱們從設備終端看到的HTML文檔都是一個平面的,事實上HTML文檔中的元素倒是存在於三個維度中。除了你們熟悉的平面畫布中的 x 軸和 y 軸,還有控制第三維度的z軸。
對於 x 和 y 軸咱們很易於理解,一個向右,一個向下。但對於 z 軸,理解起來就較爲費力。在CSS中要肯定沿着 z 軸排列元素,表示的是用戶與屏幕的這條看不見的垂直線:
該系統包括一個三維 z 軸,其中的元素是層疊(Stacked)的。 z 軸的方向指向查看者, x 軸指向屏幕的右邊, y 軸指向屏幕的底部。
一般,瀏覽器會按照CSS規範中指定的特定順序放置元素:
在DOM樹中最早出現的元素被放在首位,以後出現的元素被放在前面的元素之上。但它並不老是那麼簡單。只有當頁面上的全部元素是天然流才起做用。也就是說,當沒有元素在流中的位置被改變或者已經脫離文檔流,才起做用。
事實上,每一個HTML元素都屬於一個層疊上下文。給定層疊上下文中的每一個定位元素都具備一個整數的層疊層級,具備更大堆棧級別的元素盒子老是在具備較低堆棧級別的盒子的前面(上面)。盒子可能具備負層疊級別。層疊上下文中具備相同堆棧級別的框根據文檔樹出現的順序層疊在一塊兒。
文檔中的層疊上下文由知足如下任意一個條件的元素造成:
並且每一個頁面都有一個默認的層疊上下文。這個層疊上下文的根就是 html 元素。 html 元素中的一切都被置於這個默認的層疊上下文的一個層疊層上。
疊層水平
層疊水平(Stacking Level)決定了同一個層疊上下文中元素在z軸上的顯示順序。Level這個詞很容易讓咱們聯想到咱們真正世界中的三六九等、論資排輩。在真實世界中,每一個人都是獨立的個體,包括雙胞胎,有差別就有區分。例如,又胞胎雖然長得很像,但實際上,出生的時間仍是有前後順序的,先出生的那個就大(大哥或大姐)。網頁中的元素也是如此,頁面中的每一個元素都是獨立的個體,他們必定是會有一個相似排名排序的狀況存在。而這個排名排序、論資排輩就是咱們這裏所說的層疊水平。層疊上下文元素的層疊水平能夠理解爲官員的職級,一品兩品,縣長省長之類;對於普通元素,這個嘛...你本身隨意理解。
因而,顯而易見,全部的元素都有層疊水平,包括層疊上下文元素,層疊上下文元素的層疊水平能夠理解爲官員的職級,一品兩品,縣長省長之類。而後,對於普通元素的層疊水平,咱們的探討僅僅侷限在當前層疊上下文元素中。爲何呢?由於不然沒有意義。
翻譯成術語就是:
普通元素的層疊水平優先由層疊上下文決定,所以,層疊水平的比較只有在當前層疊上下文元素中才有意義。
須要注意的是,諸位千萬不要把層疊水平和CSS的 z-index 屬性混爲一談。沒錯,某些狀況下 z-index 確實能夠影響層疊水平,可是,只限於定位元素以及Flex盒子的孩子元素;而層疊水平全部的元素都存在。
疊層順序
在HTML文檔中,默認狀況之下有一個天然層疊順序(Natural Stacing Order),即元素在 z 軸上的順序。它是由許多因素決定的。好比下面這個列表,它顯示了元素盒子放入層疊順序上下文的順序,從層疊的底部開始,共有七種層疊等級:
這七個層疊等級構成了層疊次序的規則。 在層疊等級七上的元素會比在等級一至六上的元素顯示地更上方(更靠近觀察者)。 能夠結合w3help中的一張圖來幫助咱們更好的理解這七個層疊等級:
其實對於層疊順序規則仍是較爲複雜的。
當頁面包含浮動元素、絕對定位的元素、固定定位的元素或相對定位的元素(元素從正常位置偏移必定量)以及內聯元素時,瀏覽器會以不一樣的方式顯示它們(放置它們)。元素從最靠近查看者的地方排列到最遠的地方,以下所示:
這就是瀏覽器在呈現頁面上的元素時應用的默認層疊順序。
若是你想要更改定位元素在 z 軸上的渲染順序,可使用 z-index 屬性。例如,你有兩個絕對定位的元素,它們在某個點上重疊,而且你但願其中一個元素顯示在另外一個元素的前面,即便它在源代碼中出如今它以前,你也可使用 z-index 屬性來實現這一點。
此時須要注意的第一件重要的事情是, z-index 屬性只適用於定位元素。因此,即便爲元素提供 z-index 的值將其置於其餘元素以前, z-index 也不會對元素產生影響,除非它被定位;也就是說,除非它具備除 static 以外的 position 值。
所以,若是全部定位的元素具備z-index的索引值,則將元素從最靠近查看者排列到最遠的位置,以下所示:
具備正值的 z-index 的定位元素。較高的值更接近屏幕。而後,按照它們出如今源代碼中的順序排列:
當咱們在定位元素上設置 z-index 值時,它指定該元素在它所屬的層疊順序上下文中的順序,而且它將根據上述步驟在屏幕上渲染。
可是,當咱們設置元素的 z-index 時會發生另外一件事。獲取除默認值 auto 以外的 z-index 值的元素實際上爲其全部定位的後代元素建立層疊上下文。咱們以前提到過,每一個層疊上下文都有一個根元素,它包含其中的全部元素。當你將 z-index 屬性應用於這個元素時,它將在其包含的下下文中指定元素的 z 軸順序,而且還將建立以該元素爲根的新層疊順序上下文。
一個具備值爲 z-index:auto 的定位元素被視爲建立了新的堆疊順序上下文,但任何實際建立新層疊順序上下文的定位後代和後代被視爲父層疊順序上下文的一部分,而不是新的層疊順序上下文。
當一個元素成爲一個新的層疊順序上下文時,它所定位的後代元素將會按照咱們前面提到的元素自己的規則在其中進行層疊渲染。所以,若是咱們再次重寫渲染過程,它會是這樣的:
所以,當咱們使用 z-index 屬性來肯定其層疊順序中定位元素的順序時,咱們還建立了「原子(Atomic)」層疊順序上下文,其中每一個元素成爲其全部定位後代的層疊順序上下文。
樣式層疊
再回過頭來看樣式的層疊。CSS在任何代碼塊中,好比 {} 中均可以同時書寫相同的樣式規則,好比:
p {
color: red;
color: blue; /* 被採用 */
}
複製代碼
雖然這樣書寫並不會引發錯誤,但不建議這麼來寫CSS樣式規則。
前面咱們也提到過,在同一個樣式文件中也有可能在對同一個元素使用相同的樣式規則,好比:
<a class="link"></a>
a {
color: red;
}
.link {
color: blue;
}
複製代碼
甚至是咱們在不一樣的樣式文件中也可對同一元素使用相同的樣式規則,好比
/* base.css */
a {
color: red
}
/* style.css */
@import base.css;
a {
color: orange;
}
<!-- index.html -->
<link href="style.css" />
<style>
a {
color: lime;
}
</style>
複製代碼
上面幾種不一樣的樣式寫法,均可以被稱爲樣式的層疊。只不過最終被運用到元素上的規則以最終出現的規則爲準,固然這也有一個前提條件,那就是他們選擇器權重是相同。
權重
在CSS領域說到權重,或許你們更多關注到的是CSS選擇器的權重。其實除了選擇器權重對元素樣式有影響以外,也和CSS樣式規則出現的前後順序有關(正如前面所提到的層疊順序)。並且除了選擇器有權重以外,也有屬性權重一說。
對於選擇器權重,下圖能夠很形象的闡述:
選擇器權重能夠相似於海洋世界中的生存規則,大魚吃小魚,小魚吃蝦米。若是你實現不清楚兩個選擇器的權重,也能夠 使用在線的測試工具來檢測:
對於一個選擇器的權重,將會按下面這樣的規則進行計算:
4個數連起來 a-b-c-d (在一個基數很大的數字系統中)表示特殊性,好比下面這樣的示例:
* {} /* a=0 b=0 c=0 d=0 -> 選擇器權重 = 0,0,0,0 */
li {} /* a=0 b=0 c=0 d=1 -> 選擇器權重 = 0,0,0,1 */
li:first-line {} /* a=0 b=0 c=0 d=2 -> 選擇器權重 = 0,0,0,2 */
ul li {} /* a=0 b=0 c=0 d=2 -> 選擇器權重 = 0,0,0,2 */
ul ol+li {} /* a=0 b=0 c=0 d=3 -> 選擇器權重 = 0,0,0,3 */
h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> 選擇器權重 = 0,0,1,1 */
ul ol li.red {} /* a=0 b=0 c=1 d=3 -> 選擇器權重 = 0,0,1,3 */
li.red.level {} /* a=0 b=0 c=2 d=1 -> 選擇器權重 = 0,0,2,1 */
#x34y {} /* a=0 b=1 c=0 d=0 -> 選擇器權重 = 0,1,0,0 */
style="" /* a=1 b=0 c=0 d=0 -> 選擇器權重 = 1,0,0,0 */
複製代碼
客戶端渲染頁面時,除了選擇器權重會影響元素樣式規則以外,還有樣式來源也會影響元素樣式規則。就CSS規則的來源而言,規則主要來自三個地方:
這三種樣式表將在必定範圍內重疊,而且它們按照層疊互相影響。
CSS中運用於同一元素時的屬性也會有權重一說,好比說一樣用來描述元素寬度的屬性 width 、 min-width 、 max-width ,好比:
最終 max-width: 100% 取勝,即max-width權重高於 width 和 min-width ,但這並非絕對的,這和場景有着緊密關係。不過同時在同一個元素上使用了這三個屬性時,他們的權重大體以下:
若是你使用Flexbox來構建Web的佈局,那麼對於Flex項目的寬度也有必定的權重規則:
首先根據 content ➜ width ➜ flex-basis 來決定用哪一個來決定用於Flex項目。若是Flex項目顯式設置了 flex-basis 屬性,則會忽略 content 和 width 。並且 min-width 是用來設置Flex項目的下限值; max-width 是用來設置Flex項目的上限值。
即:
因爲 min-width 大於 max-width 時會取 min-width ,有了這個先取條件咱們就能夠將 flex-basis 和 min-width 作權重比較,即: flex-basis 會取於 min-width 。反過來,若是 min-width 小於 max-width 時則依舊會取 max-width ,同時要是 flex-basis 大於 max-width 就會取 max-width 。
注意,Flexbox佈局中有關於Flex項目的寬度計算是很是複雜的。
繼承
「繼承」是CSS中另外一個重要概念。在W3C規範中,描述每一個CSS屬性時都會有一個選項是「Inherited」,若是值爲「no」表示該屬性是不可繼承的,好比下圖左側的 border 屬性;若是值爲「yes」表示該屬性是可繼承的,好比下圖右側的 color 屬性:
在CSS中提供了處理CSS繼承的機制,簡單地講就是CSS提供了幾個屬性值,能夠用來處理屬性的繼承。這幾個屬性值就是 initial 、 inherit 、 unset 和 revert 。其實除了這四個屬性值以外,還有一個 all 屬性值。雖然這幾個屬性值主要用來幫助你們處理CSS屬性繼承的,但他們之間的使用,仍是有必定的差別化。
也就是說,CSS的層疊、權重和繼承都會對你的CSS有影響。在實際使用的時候,若是很好的運用這些概念和手段,能夠更好的幫助你們少寫不少樣式代碼,並且更易於維護本身的CSS代碼。
這裏提到的CSS層疊、權重和繼承都是CSS的基礎概念,也是CSS的核心概念,掌握或者瞭解這些概念對於每一位從事Web開發者同窗而言都是頗有必要的。只有掌握這些概念,有助於幫助你們更好的理解CSS和正確的使用CSS。
視覺格式化模型
首先要聲明一點:
視覺格式化模型和CSS盒模型不是同一個東西!
簡單點說呢。Web頁面(文檔樹)是由很一個個盒子組成(由於任何元素均可以被視爲是一個盒子),而視覺格式化模型倒是一套規則,用來計算元素轉換爲盒子的規則。而頁面的佈局都由這些盒子的所處的各處位置組合而成。那麼理解了元素怎麼轉成盒子的規則,就理解了Web頁面是怎麼佈局。而每一個盒子的佈局主要由如下幾個因素決定:
若是你想完全理解CSS的視覺可式化模型,其中還有一些概念須要掌握,好比:
除了上述說到的盒子,在CSS中還定義了幾種內容模型,這些模型一樣能夠應用於元素。這些模型通常用來描述佈局,它們可能會定義一些額外的盒子類型:
就這些概念也足讓咱們感到煩人了吧。我想你看到這些概念,應該不會再說CSS容易了。
有了這些概念,咱們再來講CSS中的格式化上下文。我想你或多或少聽過這個詞吧。在CSS中,格式化上下文有不少種,除了你們熟悉的 BFC 、 IFC 以外還有由Flexbox佈局建立的 FFC 和Grid佈局建立 GFC 等。這些統稱爲CSS 格式化上下文 ,也被稱做 視覺格式化模型 。而CSS視覺格式化模型是用來處理文檔並將它顯示在視覺媒體上的機制。
簡單地說, 就是用來控制盒子的位置,即實現頁面的佈局 。
格式化上下文也能夠說是CSS視覺渲染中的一部分, 其主要做用是決定盒子模型的佈局,其子元素將如何定位以及和其餘元素的關係和相互做用 。那麼理解CSS格式化上下文有助於咱們掌握各種CSS佈局的關鍵。
行內格式化上下文
行內格式化上下文(Inline Formatting Context),簡稱 IFC 。主要用來規則行內級盒子的格式化規則。
IFC的行盒的高度是根據包含行內元素中最高的實際高度計算而來。主要會涉及到CSS中的 font-size 、 line-height 、 vertical-align 和 text-align 等屬性。
行內元素從包含塊頂端水平方向上逐一排列,水平方向上的 margin 、 border 、 padding 生效。行內元素在垂直方向上可按照頂部、底部或基線對其。
當幾個行內元素不能在一個單獨的行盒中水平放置時,他們會被分配給兩個或更多的(Vertically-stacked Line Box)垂直棧上的行盒,所以,一個段落是不少行盒的垂直棧。這些行盒不會在垂直方向上被分離(除非在其餘地方有特殊規定),而且他們也不重疊。
下面這些規則都會建立一個行內格式化上下文:
IFC主要用於:
塊格式化上下文
塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其餘元素交互的區域。
BFC實際上就是頁面中一塊渲染區域,該區域與其餘區域隔離開來。容器裏面子元素不會影響到外部,外部的元素也不會影響到容器裏的子元素。
BFC 內部的盒子會從上至下一個接着一個順序排列。BFC 內的垂直方向的盒子距離以 margin 屬性爲準,上下 margin 會疊加。每一個元素的左側最外層邊界與包含塊 BFC 的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。BFC 的區域不會與浮動元素的盒子摺疊。BFC 的高度也會受到浮動元素的影響,浮動元素參與計算。
下面這些規則能夠建立一個BFC:
塊格式化上下文包含建立它的元素內部的全部內容。其主要使用:
Flex格式化上下文
Flex格式化上下文(Flexbox Formatting Context)俗稱 FFC 。當 display 取值爲 flex 或 inline-flex ,將會建立一個Flexbox容器。該容器爲其內容建立一個新的格式化上下文,即Flex格式化上下文。
不過要注意的是,Flexbox容器不是塊容器(塊級盒子),下列適用於塊佈局的屬性並不適用於Flexbox佈局:
Grid格式化上下文
Grid格式化上下文(Grid Formaatting Context),俗稱 GFC 。和FFC有點相似,元素的 display 值爲 grid 或 inline-grid 時,將會建立一個Grid容器。該完徹底全器爲其內容建立一個新的格式化上下文,即Grid格式化上下文。這和建立BFC是同樣的,只是使用了網格佈局而不是塊佈局。
網格容器不是塊容器,所以一些假定爲塊佈局設計的屬性並不適用於網格格式化上下文中。特別是:
盒模型
在CSS世界中,會何一個HTML元素能夠解析成一個盒子。能夠經過CSS屬性(物理屬性)來決定盒子的大小。而決定盒子大小主要由四個屬性來決定:
若是咱們用一張圖來描述的話,能夠相似下面這樣的:
上面提到的幾個屬性就是瀏覽器渲染元素盒子所須要的一切。對於CSSer來講,都喜歡用相似下圖來闡述元素的盒模型:
而在瀏覽器調試器中「Computed」能夠看到它是怎麼來解釋一個元素的盒模型:
在通常狀況之下,咱們所說的盒子的 width 是元素內容的寬度,內距和邊框的和,這也經常被稱之爲內盒的寬度。若是你在內盒的寬度上加外距的大小就能夠計算出盒子外盒的寬度。
盒子的 height 計算和 width 相似。
但在佈局中,盒子的寬度計算會直接影響到佈局,甚至會直接打破頁面的佈局。好比說,一個 div 元素:
div {
width: 100%;
padding: 1rem;
}
複製代碼
會讓 div 超出容器,相似下圖這樣:
面對這樣的場景時,就須要藉助CSS的 box-sizing 屬性,它能夠更好的幫助咱們控制盒子的大小:
用個實例來解釋,這樣更易於理解:
你們是否有留意到,在前面提到的 padding 、 border 和 margin 等都是採用的物理特性來描述一個盒子,並且開發者討論盒模型的時候,都習慣使用下圖來闡述它:
但隨着CSS的邏輯屬性的出現,在CSS中就除咱們所熟悉的物理屬性以外,還新增了不少邏輯屬性:
同時邏輯屬性對於CSS盒模型也將帶來相應的變化:
若是你在佈局時,使用邏輯屬性來替代物理屬性,對於一些國際網站,好比阿拉伯語的網站,有着明顯的做用。在改變書寫模式時,不須要額外調整佈局相關的屬性:
佈局
Web佈局對於Web前端開發者而言,它就是一個永恆的話題。
隨着Web技術不斷向前推動,Web佈局相關技術也在Web不一樣的演化過程也有相應的演進。
在Web佈局整個演進過程中,經歷了沒有任何佈局、表格佈局、定位佈局、浮動佈局、Flexbox佈局等佈局模式。除了這些咱們常看到的佈局以外,即將還會有Grid、Shapes(相似雜誌不規則佈局)和多列布局(相似報紙排版佈局)等現代佈局模式。這些佈局模式從側面也反映出其自身是Web演進過程當中的一種產物,都承載了本身在當時那個時期的史命。
對於Web前端開發人員而言面對Web的佈局始終跟着網頁的設計在走。而網頁的設計在不一樣的時期也在不斷的發生變化:從最初的站點到如今流行的站點在設計的發展有三個階段:
不一樣是代的的設計情景之下,Web的元素的定位也有其演變過程:
若是咱們用樂高積木來形容的話,會更爲形象一些,如上圖所示。
針對不一樣階段,Web佈局相對應的模式也能夠套入整個設計演變過程,若是有人猿進化來描述的話,有點相似下圖:
時至今日,已經是移動端的天下,咱們須要針對的設備類型也多起來了,爲了知足更多的設備終端,咱們還可使用響應式Web佈局:
但這並無終止Web佈局的討論。或許你不久就須要面對摺疊設備或多屏設備的佈局適配:
多屏和摺疊屏設備的出現,有多是下十年Web開發方式,設計和交互的模式都將帶來改變。一樣的,有關於這方面設備的CSS相關規範也開始在草案階段。
寫CSS的姿式
正由於CSS的層疊、權重、繼承等因素,不少開發者在編寫CSS的時候老是會碰到選擇器衝突、樣式覆蓋、代碼冗餘等種種問題。爲此,社區中有不少種關於書寫或者說維護CSS的方法論,好比:
也有不少相關的CSS框架(CSS Frameworks)來幫助你們快速編寫CSS,構建項目:
特別是這兩年,社區討論比較多的是Utility-first CSS,而這方面的表明框架就是Tailwind CSS:
就我的而言,我比較喜歡BEM和Atomic:
如今我喜歡的是**Utility-first CSS是Tailwind CSS。
除了CSS的方法論和框架,爲了提升你們的編碼效率和維護項目的CSS,社區中還有不少CSS方面的處理器:
不少時候,Sass、Stylus和LESS常被稱爲預處理器,PostCSS常被稱爲後處理器,他們能夠說是一前一後:
他們之間的關係以下圖所示:
不過,隨着React和Vue這樣的框架出來以後,社區中出現另外一種聲音,那就是在JavaScript中編寫CSS(即:CSS-in-JS):
經歷的這些種種,CSS的編寫和維護也發生了很大的變化:
不過,無論怎麼變,咱們在編寫CSS時,均可以像下面這張找到最爲適合的方式。由於沒有最好,只有最合適:
@Brandon Smith 有一篇博文是專門說 CSS is Awesome!
爲何說CSS很是棒(很是強大)呢?我從我本身的角度來和你們聊這個話題。
有一點年紀的CSSer(或者說Web開發者)對於CSS禪意花園應該不會感到陌生。CSS禪意花園有一個最大的特點,那就是基於同一套HTML的結構,能夠實現不一樣的Web UI效果,即,有着不一樣的佈局風格:
它也被稱爲CSS設計之美。並且還有一本這方面的書:
感興趣的同窗不仿也去試試,看看本身能基於同一套HTML結構,能實現多少種不一樣的UI效果。
另一個和CSS禪意花園類似的就是 @Stephanie Eckles 推出的 Style Stage,也能夠基於同一HTML結構,實現 同的UI效果:
我把她稱爲現代版的CSS禪意花園,現代版的CSS設計之美。
時至今日,在現代Web開發中,CSS愈來愈強大,她的做用不只僅是實現Web佈局,簡單的UI效果。咱們可使用CSS實現項目中不少複雜的UI效果:
我把她稱之爲CSS的視覺之美。
使用CSS的 border 、 box-shadow 、 border-radius、漸變、 clip-path、 transform和 mask 等屬性能夠直接用來繪製不一樣的視覺效果,甚至實現一些複雜的UI,還能夠結合CSS的 transition和 animation 實現帶有微動效的UI場景。
想象一下,使用一個 div 繪製不一樣的UI效果,你可能看到效果,會以爲難以想象吧:
更難以想象的是,使用CSS還能夠繪畫:
在咱們國內 @袁川 老師在這方面也頗有研究,好比袁川老師在CSSConf(中國)分享的《Generative Art With CSS》的話題:
給你們展現瞭如何使用以 繪製不一樣的藝術做品,你會領略到CSS神奇的另外一面,也會感嘆到原來CSS離藝術的創做是這麼的近:
除此以外,近幾年CSS發展也特別的快,推出不少新特性。好比@argyleink在倫敦(LondonCSS 2020)CSS第四次活動中分享的一個話題《What's new with CSS?》,就提到了不少個CSS的新特性:
在PPT中提到:
我在該基礎上從新整理了一篇新的文章,在文章中介紹了近24個有關於CSS方面的特性。
另外,在分享的時候,還遺漏了一個話題,那就是CSS的Houdini,我自已對這方面很是的感興趣。今年的GDS大會上 @Una Kravets 就分享了一個這方面的話題,並且還向特區推出了houdini.how網站,收集了CSS Houdini中Paint API和自定義屬性構建的Demo集:
在houdini.how提供的Demo,咱們均可以經過調整自定義屬性值,看到不一樣的效果:
若是你對這方面感興趣的話,也能夠把本身構建的Demo提交到Github的倉庫中。
接下來簡單地聊一下,我本身是怎麼學習CSS的,僅是本身的一點當心得,僅供參考。
我想無論是學習什麼知識,應該都離不開書吧!就CSS方面,我以爲有幾本書是很值得你們花點時間閱讀的,好比:
若是你已不是初級的CSSer,那麼W3C中有關於CSS相關的規範文檔是值得一讀:
說實話,閱讀規範是件痛苦的事情,但不一樣的時期,不一樣的階段去閱讀規範都會有不一樣的收穫。比如我本身,我今年從新閱讀這些規範時,收穫就很多。可能閱讀規範更多關注點是CSS屬性的使用,但近一年來從新閱讀規範時,我更關注的是屬性使用的臨界點相關的知識。換句話說,咱們在平時使用CSS時碰到的問題,其實在規範中都有相應的描述,也能找到相應的答案。
除了閱讀規範以外,社區中不少優秀的博客也是值得咱們去閱讀:
在中國社區,有關於CSS方面的博客,特別推薦:
在社區中發現好的博客或者站點時,你還可使用RSS應用來訂閱它們:
RSS是一個好東西,她能幫你省下很多的時間,並且獲取信息更有針對性,都有多是你本身喜歡的內容。
須要這個RSS列表的,能夠私密偶!
若是你不太喜歡使用RSS的話,也可使用一些瀏覽器的擴展插件,好比Chrome瀏覽器,我就整了一個Daily.dev:
獲取信息還有另外一種方式,那就是訂閱Github上感興趣倉庫或者關注行業內的一些大神:
獲取信息渠道不少,形成獲取信息成本很大。不少時候可能今天看到了好的話題,只是草草瞄了一下,想在有時間的時候深讀,卻在這個時候找不到文章的連接了。我就常犯這樣的毛病,爲此我這兩年養成了一個習慣,在本地建立了一個本地Blog,其中有一個欄目就是收集每月本身認爲有意思的文章:
上面說的都是看和讀,僅此是不夠的,咱們應該還須要多寫。
寫Demo,我本身經常會在Codepen上寫一些Demo,無論是驗證性的,仍是創做性的,或者說是練習性的。我都喜歡在上面寫:
Codepen上除了可讓本身作練習以外,還能夠看到不少Demo,從別人寫的Demo中學到一些新知識,新技巧。若是你尚未開始體驗的話,那麼這裏強烈建議你開啓在Codepen之旅。
除了寫Demo仍是不夠的,咱們還應該針對本身學的知識點作總結,其中寫博客就是很好的一種方式:
我本身通常會先對問題分類:
針對這些都列出一些清單,那麼就能夠有計劃的去看一些東西,學一些東西,寫一些東西。
到如今爲止,應該是2020年最後一天了,回憶了一下,我自2010年建立W3cplus到如今,我堅持寫了十年的博客,差不寫了1561篇文章:
固然,你可能會以爲有些是無用的,但就我本身而言都是有用的。除了有寫博客的習慣以外,我有時候還會對本身的一年,或一個階段作一些總結。
每一個人和每一個人都會有所不一樣的,均可能有適合本身的一套方法,個人學習方法可能比較笨,簡單地說就是 多看 、 多寫 、 多問 、 多總結 等。
臨近年末,我本身從呆了五年以外的互動團隊換到了 淘系F(x) Team 團隊。開啓了新的征程,在新團隊主要作的是一款技術產品:imgcook
若是你感興趣的話,能夠直接來先體驗一波!若是你使用imgcook碰到任何問題,均可以私密偶!
最後留一個話題,但願對該話題感興趣的同窗能夠一塊兒來探討:
「 在不久的將來,AI會取替CSSer嗎? 」