CSS現狀和如何學習

在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

揭開CSS神祕的面紗

自從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的特性到成爲真正的規範要經歷多個階段:

  • 編輯草案(ED):初始階段,很是粗糙
  • 首個公開工做草案(FPWD):首個公開版本,開始接受工做組反饋
  • 工做草案(WD):會吸取來自工做組和社區的反饋,瀏覽器早期實現一般從這個階段開始
  • 候選推薦規範(CR):相對穩定版本,比較適合實現和測試
  • 提名推薦規範(PR):W3C會員公司對這項規範表達反對意見的最後機會
  • 正式推薦規範(REC):一項W3C技術規範的最終階段

這個時候你可能已經感受到了,一個東東到成爲正式規範是多麼漫長的。這個漫長的過程除了W3C規範組織本身的問題,也還有客戶端廠商爲了各自的利益,在特性的支持上也有所不一樣。對於咱們這些Web開發者來講也是有問題,由於大家更多的時候只是CSS特性的使用者或者說佈道者,但並非推進者。對於咱們身在國內的Web開發者而言,不多有人直接參與CSS特性的制定,討論和推動。

在CSS 選擇器 Level4模塊出來的時候,社區開始有CSS4這個說法。事實上呢,早在2016年 @Rachelandrew就在社區中發聲過《Why there is no CSS4 - explaining CSS Levels》:

在Github上@Jen Simmons 在 CSSWG Drafts上單獨開了一個關於CSS4相關的帖子,社區中一些大神都對這個話題發表了本身的觀點:

  • Why Are We Talking About CSS4?
  • There Is No Such Thing As CSS4
  • Why There Is No CSS4: Explaining CSS Levels
  • Where Is CSS4? When Is It Coming Out?
  • CSS4: La nueva versión de CSS que nunca existirá

上面主要和你們聊了CSS的歷史以及她的發展歷程。

聊完CSS發展以後,咱們來再來聊聊CSS的現狀。從2019年和2020年CSS發展狀態報告中,咱們就能夠看到CSS發展的一個現狀:

這份報告相對於來講仍是比較詳細的:

除了對CSS特性、單位和選擇器、方法論、框架、工具、環境等有統計以外,還對使用CSS的人羣及現狀也有描述,好比:

除了CSS狀態發展報告以外,還有每一年的Web年鑑對CSS也會有相應的調查統計:

另外,還有一些其餘的調查報告也會有一些CSS相關的報告,但都沒有CSS狀態發展報告這樣詳細和針對性。若是你對其餘報告中關於CSS方面的調查分析,能夠閱讀 @Geoff Graham 的《2020 Roundup of Web Research》一文中列出的報告中查閱:

CSS是什麼?

CSS稱爲 層疊樣式表,便是 Cascade Style Sheets三個詞的首字母縮寫。每一個字母表明的含義不一樣:

  • C(Cascade):指的是層疊,在CSS中編寫樣式規則是一個一個排列下來,能夠簡單的理解爲前後順序
  • S(Style) : 第一個S,它指的是樣式規則,好比 body{color: red}
  • S(Sheets) :第二個S,它指的是樣式表,就是咱們常說的 .css 文件,CSS的代碼會放置在樣式表裏

Web開發者都知道,一個Web頁面或Web應用都由HTML、CSS和JavaScript三個部分組成:

每一個部分在Web中所起的做用都有所不同:

  • HTML :是Web應用的骨架
  • CSS : 是用來美化Web的
  • 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很煩人:

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其餘的一些概念,好比說:

  • 文檔流(Normal Flow)
  • 格式化上下文(Formatting Context)
  • 層疊上下文(Stacking Context)
  • 層疊水平(Stacking Level)
  • 層疊順序(Stacking Order)

也基於這個緣由,我把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源碼中出現的順序,在其容器盒子裏從左上角開始,從上到下垂直地依次分配空間層疊(Stack),而且獨佔一行,邊界緊貼父盒子邊緣。兩相鄰元素間的距離由margin屬性決定,在同一個塊格式化上下文中的垂直邊界將被重疊(Collapse margins)。除非建立一個新的塊格式化上下文,不然塊級元素的寬度不受浮動元素的影響。
  • 在對應的行內格式化上下文中,行內元素從容器的頂端開始,一個接一個地水平排列。

扯了這麼多,若是簡單的描述就是:如何排列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元素都屬於一個層疊上下文。給定層疊上下文中的每一個定位元素都具備一個整數的層疊層級,具備更大堆棧級別的元素盒子老是在具備較低堆棧級別的盒子的前面(上面)。盒子可能具備負層疊級別。層疊上下文中具備相同堆棧級別的框根據文檔樹出現的順序層疊在一塊兒。

文檔中的層疊上下文由知足如下任意一個條件的元素造成:

  • 根元素 ()
  • z-index 值不爲 auto 的 position 值爲非 static
  • position 值爲非 static
  • 一個 z-index 值不爲 auto 的 Flex 項目 (Flex item),即:父元素 display: flex|inline-flex
  • opacity 屬性值小於 1 的元素
  • transform 屬性值不爲 none 的元素
  • mix-blend-mode 屬性值不爲 normal 的元素
  • filter 、 perspective 、 clip-path 、 mask 、 motion-path 值不爲 none 的元素
  • perspective 值不爲 none 的元素
  • isolation 屬性被設置爲 isolate 的元素
  • 在 will-change 中指定了任意 CSS 屬性,即使你沒有直接指定這些屬性的值

並且每一個頁面都有一個默認的層疊上下文。這個層疊上下文的根就是 html 元素。 html 元素中的一切都被置於這個默認的層疊上下文的一個層疊層上。

疊層水平

層疊水平(Stacking Level)決定了同一個層疊上下文中元素在z軸上的顯示順序。Level這個詞很容易讓咱們聯想到咱們真正世界中的三六九等、論資排輩。在真實世界中,每一個人都是獨立的個體,包括雙胞胎,有差別就有區分。例如,又胞胎雖然長得很像,但實際上,出生的時間仍是有前後順序的,先出生的那個就大(大哥或大姐)。網頁中的元素也是如此,頁面中的每一個元素都是獨立的個體,他們必定是會有一個相似排名排序的狀況存在。而這個排名排序、論資排輩就是咱們這裏所說的層疊水平。層疊上下文元素的層疊水平能夠理解爲官員的職級,一品兩品,縣長省長之類;對於普通元素,這個嘛...你本身隨意理解。

因而,顯而易見,全部的元素都有層疊水平,包括層疊上下文元素,層疊上下文元素的層疊水平能夠理解爲官員的職級,一品兩品,縣長省長之類。而後,對於普通元素的層疊水平,咱們的探討僅僅侷限在當前層疊上下文元素中。爲何呢?由於不然沒有意義。

翻譯成術語就是:

普通元素的層疊水平優先由層疊上下文決定,所以,層疊水平的比較只有在當前層疊上下文元素中才有意義。

須要注意的是,諸位千萬不要把層疊水平和CSS的 z-index 屬性混爲一談。沒錯,某些狀況下 z-index 確實能夠影響層疊水平,可是,只限於定位元素以及Flex盒子的孩子元素;而層疊水平全部的元素都存在。

疊層順序

在HTML文檔中,默認狀況之下有一個天然層疊順序(Natural Stacing Order),即元素在 z 軸上的順序。它是由許多因素決定的。好比下面這個列表,它顯示了元素盒子放入層疊順序上下文的順序,從層疊的底部開始,共有七種層疊等級:

  • 背景和邊框:造成層疊上下文的元素的背景和邊框。 層疊上下文中的最低等級。
  • 負 z-index 值:層疊上下文內有着負 z-index 值的子元素。
  • 塊級盒:文檔流中非行內非定位子元素。
  • 浮動盒:非定位浮動元素。
  • 行內盒:文檔流中行內級別非定位子元素。
  • z-index: 0 :定位元素。 這些元素造成了新的層疊上下文。
  • 正 z-index 值:定位元素。 層疊上下文中的最高等級。

這七個層疊等級構成了層疊次序的規則。 在層疊等級七上的元素會比在等級一至六上的元素顯示地更上方(更靠近觀察者)。 能夠結合w3help中的一張圖來幫助咱們更好的理解這七個層疊等級:

其實對於層疊順序規則仍是較爲複雜的。

當頁面包含浮動元素、絕對定位的元素、固定定位的元素或相對定位的元素(元素從正常位置偏移必定量)以及內聯元素時,瀏覽器會以不一樣的方式顯示它們(放置它們)。元素從最靠近查看者的地方排列到最遠的地方,以下所示:

  • 定位元素按源代碼中的外觀順序排列。源代碼中的最新內容最接近查看者
  • 內聯元素(好比文本和圖像)是流入和非定位(它們的位置是靜態的)
  • 非浮動元素按照源代碼中外觀的順序排列
  • 非定位和非浮動塊級元素
  • 根元素 html 是全局層疊上下文的根,包含頁面上的全部元素

這就是瀏覽器在呈現頁面上的元素時應用的默認層疊順序。

若是你想要更改定位元素在 z 軸上的渲染順序,可使用 z-index 屬性。例如,你有兩個絕對定位的元素,它們在某個點上重疊,而且你但願其中一個元素顯示在另外一個元素的前面,即便它在源代碼中出如今它以前,你也可使用 z-index 屬性來實現這一點。

此時須要注意的第一件重要的事情是, z-index 屬性只適用於定位元素。因此,即便爲元素提供 z-index 的值將其置於其餘元素以前, z-index 也不會對元素產生影響,除非它被定位;也就是說,除非它具備除 static 以外的 position 值。

所以,若是全部定位的元素具備z-index的索引值,則將元素從最靠近查看者排列到最遠的位置,以下所示:

具備正值的 z-index 的定位元素。較高的值更接近屏幕。而後,按照它們出如今源代碼中的順序排列:

  • 定位元素的 z-index:0 或 z-index: auto ;
  • 內聯元素(如文本和圖像)是流中的和非定位的(它們的位置是靜態的)
  • 源代碼中出現順序的非定位浮動元素
  • 非定位和非浮動塊級元素
  • 具備負值的 z-index 的定位元素。較低的 z-index 索引值更近。而後按照它們在源代碼中出現的順序
  • 根元素 html 是全局層疊上下文的根,包含頁面上的全部元素

當咱們在定位元素上設置 z-index 值時,它指定該元素在它所屬的層疊順序上下文中的順序,而且它將根據上述步驟在屏幕上渲染。

可是,當咱們設置元素的 z-index 時會發生另外一件事。獲取除默認值 auto 以外的 z-index 值的元素實際上爲其全部定位的後代元素建立層疊上下文。咱們以前提到過,每一個層疊上下文都有一個根元素,它包含其中的全部元素。當你將 z-index 屬性應用於這個元素時,它將在其包含的下下文中指定元素的 z 軸順序,而且還將建立以該元素爲根的新層疊順序上下文。

一個具備值爲 z-index:auto 的定位元素被視爲建立了新的堆疊順序上下文,但任何實際建立新層疊順序上下文的定位後代和後代被視爲父層疊順序上下文的一部分,而不是新的層疊順序上下文。

當一個元素成爲一個新的層疊順序上下文時,它所定位的後代元素將會按照咱們前面提到的元素自己的規則在其中進行層疊渲染。所以,若是咱們再次重寫渲染過程,它會是這樣的:

  • 具備正值 z-index 的定位元素組成的層疊順序上下文。較高的值更接近屏幕。而後按照它們在源代碼中出現的順序呈現
  • 定位元素的 z-index: 0 或 z-index: auto
  • 內聯元素(好比文本和圖像)是流中的和非定位的(它們的位置是靜態的)
  • 非浮動元素按照源代碼中外觀的順序排列
  • 非定位和非浮動塊級元素
  • 具備負值 z-index 的定位元素組成的層疊順序上下文。較低的 z-index 的值更接近屏幕。而後按照它們在源代碼中出現的順序呈現
  • 根元素 html 是全局層疊上下文的根,包含頁面上全部元素

所以,當咱們使用 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樣式規則出現的前後順序有關(正如前面所提到的層疊順序)。並且除了選擇器有權重以外,也有屬性權重一說。

對於選擇器權重,下圖能夠很形象的闡述:

選擇器權重能夠相似於海洋世界中的生存規則,大魚吃小魚,小魚吃蝦米。若是你實現不清楚兩個選擇器的權重,也能夠 使用在線的測試工具來檢測:

對於一個選擇器的權重,將會按下面這樣的規則進行計算:

  • 若是聲明來自一個行內樣式( style 屬性)而不是一條選擇器樣式規則,算 1 ,不然就是 0 ( =a )。HTML中,一個元素的 style 屬性值是樣式規則,這些屬性沒有選擇器,因此 a=1 , b = 0 , c = 0 , d = 0 ,即 1, 0, 0, 0
  • 計算選擇器中 ID 屬性的數量 ( = b )
  • 計算選擇器中其它屬性和僞類的數量 ( = c )
  • 計算選擇器中元素名和僞元素的數量 ( = d )

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規則的來源而言,規則主要來自三個地方:

  • 編寫者規則(Author) :這是HTML文檔聲明的CSS。也就是咱們前端開發人員編寫的,根據文檔語言(好比HTML)約定給源文檔指定樣式表。這也是咱們可以控制的惟一來源
  • 用戶(User) :這是由瀏覽器的用戶定義和控制的。不是每一個人都會有一個,可是當人們添加一個時,一般是爲了覆蓋樣式和增長網站的可訪問性。好比,用戶能夠指定一個售有樣式表的文件,或者用戶代理可能會提供一個用來生成用戶樣式(或者表現得像這樣作了同樣)的界面
  • 用戶代理(User-Agent) :這些是瀏覽器爲元素提供的默認樣式。這就是爲何 input 在不一樣的瀏覽器上看起來略有不一樣,這也是人們喜歡使用CSS重置樣式,以確保重寫用戶代理樣式的緣由之一

這三種樣式表將在必定範圍內重疊,而且它們按照層疊互相影響。

CSS中運用於同一元素時的屬性也會有權重一說,好比說一樣用來描述元素寬度的屬性 width 、 min-width 、 max-width ,好比:

最終 max-width: 100% 取勝,即max-width權重高於 width 和 min-width ,但這並非絕對的,這和場景有着緊密關係。不過同時在同一個元素上使用了這三個屬性時,他們的權重大體以下:

  • 當 width 大於 min-width 時,會取 width 的值;當 width 小於 min-width 時,會取 min-width 的值
  • 當 width 大於 max-width 時,會取 max-width 的值;當 width 小於 max-width 時,會取 width 的值
  • 若是min-width大於max-width,那麼min-width值將做爲元素的寬度;若是min-width小於max-width,那麼min-width值將做爲元素的寬度

若是你使用Flexbox來構建Web的佈局,那麼對於Flex項目的寬度也有必定的權重規則:

首先根據 content ➜ width ➜ flex-basis 來決定用哪一個來決定用於Flex項目。若是Flex項目顯式設置了 flex-basis 屬性,則會忽略 content 和 width 。並且 min-width 是用來設置Flex項目的下限值; max-width 是用來設置Flex項目的上限值。

即:

  • flex-basis 大於 max-width ,Flex項目的寬度等於 max-width ,即 max-width 能覆蓋 flex-basis
  • 若是 flex-basis 小於 min-width 時,Flex項目的寬度會取值 min-width ,即 min-width 覆蓋 flex-basis

因爲 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頁面是怎麼佈局。而每一個盒子的佈局主要由如下幾個因素決定:

  • 盒子的尺寸 :精確指定、由約束條件指定或沒有指定
  • 盒子的類型 :行內盒子(inline)、行內級盒子(inline-level)、原子行內級盒子(atomic inline-level)和塊盒子(block)
  • 定位方案 :普通流定位、浮動定位或絕對定位
  • 文檔樹中的其它元素 :即當前盒子的子元素或兄弟元素
  • 視窗尺寸與位置
  • 所包含的圖片的尺寸
  • 其餘的某些外部因素

若是你想完全理解CSS的視覺可式化模型,其中還有一些概念須要掌握,好比:

  • 塊(Block) :一個抽象的概念,一個塊在文檔流上佔據一個獨立的區域,塊與塊之間在垂直方向按照順序依次堆疊(默認狀況之下)
  • 包含塊(Containing Block) :指的是包含其餘盒子的塊
  • 盒子(Box) : 一個抽象的概念,由CSS引擎根據文檔中的內容所建立,主要用於文檔元素的定位、佈局和格式化等用途
  • 塊級盒子(Block-level Box) :由塊級元素生成。一個塊級元素至少會生成一個塊級盒子,但也有可能生成多個(例如列表項元素)
  • 行內級盒子(Inline-level Box) :由行內級元素生成。一樣的,一個行內元素至少會生成一個行內級盒子。行內級盒子包括行內盒子和原子行內級盒子兩種,區別在於該盒子是否參與行內格式化上下文的建立
  • 塊盒子(Block Box) :若是一個塊級盒子同時也是一個塊容器盒子,則稱其爲塊盒子。除具名塊盒子以外,還有一類塊盒子是匿名的,稱爲匿名塊盒子(Anonymous Block Box),匿名盒子沒法被CSS選擇器選中
  • 原子行內級盒子(Atomic Inline-level Box) :不參與行內格式化上下文建立的行內級盒子。原子行內級盒子一開始叫作原子行內盒子(Atomic Inline Box),後被修正。原子內級盒子的內容不會拆分紅多行顯示。
  • 行盒(Line Box) : 和行內盒是不同的。行盒是由行內格式化上下文(Inline Formatting Context)產生的盒子,用於表示一行。行盒從包含塊的一邊排版到另外一邊。通常狀況下,瀏覽器爲會每行建立一個看不見的行盒
  • 塊容器盒子(Block Container Box或Block Containning Box) :塊容器盒子側重於當前盒子做爲容器角色,它不參與當前塊的佈局和定位,它所描述的僅僅是當前盒子與其後代之間的關係
  • 塊級元素(Block-level Element) : 是指元素的 display 值爲 block 、 list-item 、 table 、 flex 和 grid 等,該元素將成爲塊級元素。元素是不是塊級元素僅是元素自己的屬性,並不直接用於格式化上下文的建立或佈局
  • 行內級元素(Inline-level Element) :是指元素的 display 值爲 inline 、 inline-block 、 inline-table 、 inline-flex 和 inline-grid 等,該元素將成爲行內級元素。與塊元素同樣,元素是不是行內級元素僅是元素自己的屬性,並不直接用於格式化上下文的建立或佈局
  • 視窗(Viewport) :視窗就是瀏覽器中可視區域。視窗大小指的就是瀏覽器可視區域的大小
  • 匿名盒子 : 分爲塊匿名盒子和行內匿名盒子。在某些狀況下進行視覺格式化時,須要添加一些增補性的盒子,這些盒子沒法被CSS的選擇器選中,而這種盒子被稱爲匿名盒子(Anonymous Box)。

除了上述說到的盒子,在CSS中還定義了幾種內容模型,這些模型一樣能夠應用於元素。這些模型通常用來描述佈局,它們可能會定義一些額外的盒子類型:

  • 表格內容模型 :可能會建立一個表格包裝器盒子和一個表格盒子,以及多個其餘盒子如表格標題盒子等
  • 多列內容模型 :可能會在容器盒子和內容之間建立多個列盒子
  • Flexbox內容模型 :可能會建立一個彈性盒子
  • Grid內容模型 :可能會建立一個網格盒子

就這些概念也足讓咱們感到煩人了吧。我想你看到這些概念,應該不會再說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)垂直棧上的行盒,所以,一個段落是不少行盒的垂直棧。這些行盒不會在垂直方向上被分離(除非在其餘地方有特殊規定),而且他們也不重疊。

  • 垂直方向上,當行內元素的高度比行盒要低,那麼 vertical-align 屬性決定垂直方向上的對齊方式。
  • 水平方向上,當行內元素的總寬度比行盒要小,那麼行內元素在水平方向上的分部由 text-align 決定。
  • 水平方向上,當行內元素的總寬度超過了行盒,那麼行內元素會被分配到多個行盒中去,若是設置了不可折行等屬性,那麼行內元素會溢出行盒。
  • 行盒的左右兩邊都會觸碰到包含塊,而 float 元素則會被放置在行盒和包含快邊緣的中間位置。

下面這些規則都會建立一個行內格式化上下文:

  • IFC只有在一個塊級元素中僅包含行內級元素時纔會生成
  • 內部的盒子會在不平方向,一個接一個的放置
  • 這些盒子垂直方向的起點從包含塊盒子的頂部開始
  • 擺放這些盒子的時候,它們在水平方向上的 padding 、 border 和 margin 所佔用的空間都會被考慮在內
  • 在垂直方向上,這些盒子可能會以不一樣形式來對齊( vertical-align )
  • 能把在一行上的盒子都徹底包含在一行行盒(Line Box),行盒的寬度是由包含塊和存在的浮動來決定
  • IFC中的行盒通常左右邊都緊貼其包含塊,可是會因浮動元素的存在發生變化。浮動元素會位於IFC與行盒之間,使得行盒寬度縮短
  • 當行內級盒的總寬度小於包含它們的行盒時,其水平渲染規則則由 text-align 來肯定
  • 當行內盒超過行盒的寬度時,它會被分割成多個盒子,這些盒子被分佈在多個行盒裏。若是一個行內盒不能被分割,則會溢出行盒

IFC主要用於:

  • 行內元素按照 text-align 進行水平居中
  • 行內元素撐開父元素高度,經過 vertical-align 屬性進行垂直居中

塊格式化上下文

塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其餘元素交互的區域。

BFC實際上就是頁面中一塊渲染區域,該區域與其餘區域隔離開來。容器裏面子元素不會影響到外部,外部的元素也不會影響到容器裏的子元素。

BFC 內部的盒子會從上至下一個接着一個順序排列。BFC 內的垂直方向的盒子距離以 margin 屬性爲準,上下 margin 會疊加。每一個元素的左側最外層邊界與包含塊 BFC 的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此。BFC 的區域不會與浮動元素的盒子摺疊。BFC 的高度也會受到浮動元素的影響,浮動元素參與計算。

下面這些規則能夠建立一個BFC:

  • 根元素或包含根元素的元素
  • 浮動元素(元素的 float 不是 none )
  • 絕對定位元素(元素的 position 爲 absolute 或 fixed )
  • 行內塊元素(元素的 display 爲 inline-block )
  • 表格單元格(元素的 display 爲 table-cell ,HTML表格單元格默認爲該值)
  • 表格標題(元素的 display 爲 table-caption ,HTML表格標題默認爲該值)
  • 匿名錶格單元格元素(元素的 display 爲 table 、 table-row 、 table-row-group 、 table-header-group 、 table-footer-group (分別是HTML table 、 row 、 tbody 、 thead 、 tfoot 的默認屬性)或 inline-table )
  • overflow 值不爲 visible 的塊元素
  • display 值爲 flow-root 的元素
  • contain 值爲 layout 、 content 或 strict 的元素
  • 彈性元素( display 爲 flex 或 inline-flex 元素的直接子元素)
  • 網格元素( display 爲 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不爲 auto ,包括 column-count 爲 1 )
  • column-span 爲 all 的元素始終會建立一個新的BFC,即便該元素沒有包裹在一個多列容器中

塊格式化上下文包含建立它的元素內部的全部內容。其主要使用:

  • 建立獨立的渲染環境
  • 防止因浮動致使的高度塌陷
  • 防止上下相鄰的外邊距摺疊

Flex格式化上下文

Flex格式化上下文(Flexbox Formatting Context)俗稱 FFC 。當 display 取值爲 flex 或 inline-flex ,將會建立一個Flexbox容器。該容器爲其內容建立一個新的格式化上下文,即Flex格式化上下文。

不過要注意的是,Flexbox容器不是塊容器(塊級盒子),下列適用於塊佈局的屬性並不適用於Flexbox佈局:

  • 多列中的 column-* 屬性不適用於Flexbox容器
  • float 和 clear 屬性做用於Flex項目上將無效,也不會把讓Flex項目脫離文檔流
  • vertical-algin 屬性做用於Flex項目上將無效
  • ::first-line 和 ::first-letter 僞元素不適用於Flexbox容器,並且Flexbox容器不爲他們的祖先提供第一個格式化的行或第一個字母

Grid格式化上下文

Grid格式化上下文(Grid Formaatting Context),俗稱 GFC 。和FFC有點相似,元素的 display 值爲 grid 或 inline-grid 時,將會建立一個Grid容器。該完徹底全器爲其內容建立一個新的格式化上下文,即Grid格式化上下文。這和建立BFC是同樣的,只是使用了網格佈局而不是塊佈局。

網格容器不是塊容器,所以一些假定爲塊佈局設計的屬性並不適用於網格格式化上下文中。特別是:

  • float 和 clear 運用於網格項目將不會生效。可是 float 屬性仍然影響網格完徹底全器子元素上 display 的計算值,由於這發生在肯定網格項目以前
  • vertical-align 運用於網格項目也將不會生效
  • ::first-line 和 ::first-letter 僞元素不適用於網格容器,並且網格容器不向它們社先提供第一個格式化行或第一個格式化字母

盒模型

在CSS世界中,會何一個HTML元素能夠解析成一個盒子。能夠經過CSS屬性(物理屬性)來決定盒子的大小。而決定盒子大小主要由四個屬性來決定:

  • Content :元素中的文本、圖像或其餘媒體內容
  • padding :盒子內容格邊框之間的空間
  • border :盒子的邊框
  • margin :盒子與其餘盒子之間的距離

若是咱們用一張圖來描述的話,能夠相似下面這樣的:

上面提到的幾個屬性就是瀏覽器渲染元素盒子所須要的一切。對於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設計1.0是「一維的」:設計元素大可能是按順序排列的(按文檔流的天然順序排列)
  • Web設計2.0是「二維的」:單元格中有放置元素的網格,具備更多的自由性
  • Web設計3.0是一個「新的維度」:它能夠像平面設計工具同樣的自由地定位元素、重疊。爲網頁設計開闢了新的前景。也將開啓新的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時,均可以像下面這張找到最爲適合的方式。由於沒有最好,只有最合適:

CSS Is Awesome

@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中提到:

  • CSS自定義屬性
  • CSS邏輯屬性
  • CSS書寫模式
  • CSS的 gap 屬性
  • CSS的Grid佈局,以及 subgrid
  • CSS的滾動捕捉
  • CSS新的媒體特性
  • CSS選擇器Level 4

我在該基礎上從新整理了一篇新的文章,在文章中介紹了近24個有關於CSS方面的特性。

另外,在分享的時候,還遺漏了一個話題,那就是CSS的Houdini,我自已對這方面很是的感興趣。今年的GDS大會上 @Una Kravets 就分享了一個這方面的話題,並且還向特區推出了houdini.how網站,收集了CSS Houdini中Paint API和自定義屬性構建的Demo集:

在houdini.how提供的Demo,咱們均可以經過調整自定義屬性值,看到不一樣的效果:

若是你對這方面感興趣的話,也能夠把本身構建的Demo提交到Github的倉庫中。

如何學習CSS

接下來簡單地聊一下,我本身是怎麼學習CSS的,僅是本身的一點當心得,僅供參考。

我想無論是學習什麼知識,應該都離不開書吧!就CSS方面,我以爲有幾本書是很值得你們花點時間閱讀的,好比:

若是你已不是初級的CSSer,那麼W3C中有關於CSS相關的規範文檔是值得一讀:

說實話,閱讀規範是件痛苦的事情,但不一樣的時期,不一樣的階段去閱讀規範都會有不一樣的收穫。比如我本身,我今年從新閱讀這些規範時,收穫就很多。可能閱讀規範更多關注點是CSS屬性的使用,但近一年來從新閱讀規範時,我更關注的是屬性使用的臨界點相關的知識。換句話說,咱們在平時使用CSS時碰到的問題,其實在規範中都有相應的描述,也能找到相應的答案。

除了閱讀規範以外,社區中不少優秀的博客也是值得咱們去閱讀:

在中國社區,有關於CSS方面的博客,特別推薦:

  • 張鑫旭 老師的鑫空間,鑫生活
  • chokcoco 老師的 愛CSS(ICSS)

在社區中發現好的博客或者站點時,你還可使用RSS應用來訂閱它們:

RSS是一個好東西,她能幫你省下很多的時間,並且獲取信息更有針對性,都有多是你本身喜歡的內容。

須要這個RSS列表的,能夠私密偶!

若是你不太喜歡使用RSS的話,也可使用一些瀏覽器的擴展插件,好比Chrome瀏覽器,我就整了一個Daily.dev:

獲取信息還有另外一種方式,那就是訂閱Github上感興趣倉庫或者關注行業內的一些大神:

獲取信息渠道不少,形成獲取信息成本很大。不少時候可能今天看到了好的話題,只是草草瞄了一下,想在有時間的時候深讀,卻在這個時候找不到文章的連接了。我就常犯這樣的毛病,爲此我這兩年養成了一個習慣,在本地建立了一個本地Blog,其中有一個欄目就是收集每月本身認爲有意思的文章:

上面說的都是看和讀,僅此是不夠的,咱們應該還須要多寫。

寫Demo,我本身經常會在Codepen上寫一些Demo,無論是驗證性的,仍是創做性的,或者說是練習性的。我都喜歡在上面寫:

Codepen上除了可讓本身作練習以外,還能夠看到不少Demo,從別人寫的Demo中學到一些新知識,新技巧。若是你尚未開始體驗的話,那麼這裏強烈建議你開啓在Codepen之旅。

除了寫Demo仍是不夠的,咱們還應該針對本身學的知識點作總結,其中寫博客就是很好的一種方式:

我本身通常會先對問題分類:

  • 我懂的
  • 我彷佛懂的
  • 我不懂的
  • 我感興趣的

針對這些都列出一些清單,那麼就能夠有計劃的去看一些東西,學一些東西,寫一些東西。

到如今爲止,應該是2020年最後一天了,回憶了一下,我自2010年建立W3cplus到如今,我堅持寫了十年的博客,差不寫了1561篇文章:

固然,你可能會以爲有些是無用的,但就我本身而言都是有用的。除了有寫博客的習慣以外,我有時候還會對本身的一年,或一個階段作一些總結。

每一個人和每一個人都會有所不一樣的,均可能有適合本身的一套方法,個人學習方法可能比較笨,簡單地說就是 多看 、 多寫 、 多問 、 多總結 等。

AI會取替CSSer?

臨近年末,我本身從呆了五年以外的互動團隊換到了 淘系F(x) Team 團隊。開啓了新的征程,在新團隊主要作的是一款技術產品:imgcook

在Github上也能找到喲!

若是你感興趣的話,能夠直接來先體驗一波!若是你使用imgcook碰到任何問題,均可以私密偶!

最後留一個話題,但願對該話題感興趣的同窗能夠一塊兒來探討:

「 在不久的將來,AI會取替CSSer嗎? 」

相關文章
相關標籤/搜索