容易忽略的七個CSS知識點

若是你在平常工做中使用CSS,那麼你的主要目標極可能集中在使事情看起來是正確的。最終獲得的正確結果遠好比何實現更重要。這意味着相比正確的語法和視覺效果咱們更少關注CSS的實現原理。css

你可能尚未意識到,但CSS的視覺效果一般是操縱隱藏屬性的間接結果。一些CSS屬性(如 background-color)和你看到的視覺效果就有顯然的直接關係。而其餘的(好比display)對咱們許多人來講仍然含糊不清,由於結果彷佛高度依賴於上下文。web

我懷疑不少開發者都不能簡單的描述當設置了display: block以後實際上作了什麼。最多你可能只是直觀地瞭解這個屬性是如何工做的。不要緊,你能夠在不瞭解基本原理的狀況下,對CSS有很好的使用。雖然,你知道解決問題的方案,可是你卻不必定真的瞭解問題。瀏覽器

對於許多人來講,諸如盒子模型、級聯和特殊性等概念是咱們所熟知的。雖然他們常常被曲解,可是知道這些工做原理有助於咱們編寫更好的CSS。佈局

正由於如此,我想試着揭示CSS的這些隱藏黑科技部分,只介紹涉及你須要知道的部分,並但願以邏輯順序解釋該過程,以便你更好的理解CSS真正的工做原理。性能

渲染過程概述

當你加載一個HTML文檔的時候,頁面的渲染過程當中會按照順序發生了不少事情。字體

第一步就是解析HTML文檔。從這一步開始瀏覽器會生成一個「文檔樹」。樹的結構是一種用HTML表明具備明顯層次結構信息的方式。樹中的元素能夠用相似於家譜的方式描述,好比:後代節點、父節點、子孫節點和兄弟節點。flex

你可能據說過「DOM」這個術語。它表明「文檔對象模型(Document Object Model)」。它是文檔樹結構的擴展,它被用來存儲web文檔內容和操做信息。網站

隨着HTML被解析,樣式文件和其餘資源文件會被下載。樣式聲明經過一個稱爲級聯的過程來解釋和決定。spa

在此過程當中,將解析CSS屬性的最終值。通過計算,這些值可能與咱們樣式表中所寫的值不一樣。例如:像auto 這樣的相對單位的關鍵字被賦予了真正的值,並會應用繼承的值。這些計算好的值會像存儲在DOM樹中的元素同樣被存儲在一個樹中,毫無疑問會被稱爲CSS對象模型(CSS Object Model )或CSSOM。代理

如今就能夠開始渲染頁面的過程了。這個過程當中的第一步是計算 盒模型。這一步對於計算出元素的大小和間距是很重要的,儘管可能並非最終的位置。

和 盒模型相比並非那麼被熟知的過程叫作 視覺格式模型。此過程會肯定頁面上元素的佈局和位置。它包含您可能已經熟悉的一些概念,例如:定位方案(positioning schemes), 格式化上下文(formatting contexts), 顯示模式(display modes), 和 堆疊上下文(stacking contexts)。

最終頁面被渲染出來。

以上段落中可能有幾個術語,您還不熟悉。若是是這樣的話,最重要的是理解 級聯, 盒模型, 和 視覺格式模型,理解這些術語是解釋、處理和渲染HTML和CSS相當重要的一步。在描述上面每一個渲染過程的細節時,我跳過了不少的細節,因此接下來咱們更加仔細地看這三個步驟。

級聯

級聯多是CSS中最容易被弄錯的屬性之一。它指的是合併不一樣樣式表並解決CSS選擇器之間衝突的過程。

級聯查看聲明的優先級、來源、特性和順序,以肯定使用哪一種樣式規則。

你須要知道什麼:

大多數網站都有多種樣式表。一般的樣式是在頁面中添加了一個引用css文件的link 標籤,或者在HTML主體中使用 style 標籤。即便最基本的頁面也有由瀏覽器提供的默認樣式。此默認樣式表有時稱爲用戶代理樣式表(user-agent stylesheet)。

在級聯過程當中樣式表按如下順序解釋:

!important 聲明

開發者編寫的樣式表

瀏覽器默認的樣式表

注意事項: 我跳過了用戶樣式表,由於它已不是常見的了。

合併這些來源的樣式以後,若是不少規則被用在了同一個元素上,則用權重肯定應用的規則。

特殊性

特殊性是指選擇器的權重。僅僅把它看做一個單獨的數字是一個常見的錯誤。實際上它是4個獨立的數字或4種類別的權重。

計算特殊性,把下面的權重相加:

  1. ID,
  2. class, 屬性 和 僞類,
  3. 元素 和 僞元素

例如: #nav .selected:hover > a::before 的權重分別是 1, 2, 2。

不管多少個class的權重,都沒有ID的權重高。當比較選擇器時,首先應該比較ID的權重大小。僅當ID的權重同樣的時候,再比較class、屬性和僞類的權重,最後,若是權重依然同樣的話就比較元素和僞元素的權重。

若是每一個類別的權重都相等的話,則採用就近優先的原則(即應用來源中最後聲明的規則)。

是的!我知道我說了4類的權重大小。可是行內樣式的權重比ID的更高。儘管它們是技術上權重計算中的第一類,可是一般是沒法和行內樣式競爭的,因此,很容易記住行內樣式老是高於其餘類別的權重。

重要注意事項: !important 聲明沒有考慮權重計算,可是它們比級聯中的正常聲明具備更高的優先級。

繼承

繼承不是級聯中的一部分,可是這裏我把它包含進來主要是由於它常常和級聯一塊兒被討論。

繼承是應用於元素的值能夠由其子元素傳遞(或繼承)的過程。

您可能很熟悉字體屬性(當應用於body或另外一個容器元素時)也由該容器內的每一個元素繼承的事實。這就是繼承。

並不是全部屬性都默認繼承。 瞭解繼承是編寫更加優雅和簡潔CSS的關鍵。 使用inherit關鍵字強制繼承是很是有用的。

注意事項: 某些屬性如border-color 具備默認值currentcolor。 這意味着他們將使用color屬性上設置的值。 這個默認值與繼承不同。 雖然顏色屬性自己一般是繼承的。

盒模型

瞭解盒子模型對於限制使用佈局和定位時的問題是必不可少的。 它是CSS中最基本的概念之一。

盒模型用於計算元素的寬和高。這是一個計算步驟,並不徹底被依賴於肯定元素的最終佈局和定位。

你須要知道什麼:

HTML的每個元素都是一個矩形的盒子。每一個盒子都有4個區域,用於定義元素的邊距(margin)、邊框(border)、填充(padding)和內容區域。

默認狀況下,你給一個元素設置的寬度,只是設置了內容區域的寬度。當你給元素添加padding、border和margin時,這是增長了除了寬度以外的部分。實際上,這意味着寬度爲50%的兩個元素若是添加了padding,margin或border,則會超過100%的寬度,進而致使不能並排排版了。
圖片描述

就是這樣!這是至關簡單的對吧?爲何這經常是困惑的來源呢?好吧,你可能遇到過一些狀況,事情彷佛有些不一樣的表現…

填充區域

當你給一個元素設置背景的時候,填充的不只僅是內容區域,並且還包括內部padding區域和邊框區域。
圖片描述

從概念上來講,咱們認爲HTML元素是單一的東西。所以很容易認爲元素的視覺邊界等於其寬度,但狀況並不是如此。儘管元素的視覺邊界包括填充(padding)和邊框(border)區域,width 屬性明確地應用於內容區域上。

注意事項: 改變 box-sizing 屬性能夠改變這種表現行爲。

動態寬度

另外一個潛在的困惑的來源是width: auto 是怎樣工做的。一個自動的寬度對於大部分的HTML元素都是一個默認值,好比:div和p標籤,auto 的寬度計算以便於margin、border、padding和內容區域合併以後可以適應可用的空間。

實際上,是從新計算寬度以確保一切都適合。 經過比較,設置寬度爲「100%」時,無論邊距、填充和邊框的大小是多少,內容區域都將填充可用空間。
圖片描述

Box-sizing

box-sizing屬性可以改變盒模型的工做方式。當 box-sizing設置爲border-box 時,padding和border將減小內容區域的內部寬度,而不是增長元素的總體寬度。這意味着一個元素的寬度如今與它的可視寬度相同。
圖片描述
不少人喜歡這個屬性,若是你正在創建一個網格系統,或任何其餘須要水平對齊類型的佈局項目,這能夠更直觀的工做方式。

邊距重疊

當邊距意外重疊的時候,真的使人很困惑,由於你不知道發生了什麼。當兩個或多個相鄰的垂直邊距接觸時,邊距有時會發生重疊,而且不會用填充或邊框分隔。若是子元素的邊緣擴展到父元素的邊緣,而且不會被填充分隔開,那麼就會出現邊距重疊的現象。

若是元素採用的是絕對定位、浮動定位或者有一個不同的 格式化上下文時,邊距不會發生重疊現象。

若是你感到困惑,不要緊。邊距不會發生重疊的規則是複雜的。 您須要知道的主要事情是當元素沒有填充或邊框時,垂直邊距可能會重疊。

視覺格式化模型

當盒模型計算元素的尺寸時,它是負責肯定這些盒佈局的視覺格式模型。 視覺格式模型考慮了盒的類型、定位方案、元素之間的關係和由內容強加的約束,以肯定頁面上每一個元素的最終位置和呈現。

你須要知道什麼:

視覺格式模型遍歷文檔樹,並按CSS盒模型生成一個或多個渲染元素所需的盒子。CSSdisplay 屬性在決定元素如何參與當前的格式化上下文和定位方案中起着關鍵的做用。這些部分將決定元素的最終佈局和位置。

這是一個複雜的步驟,是迄今爲止最難嘗試和總結的。若是你還不瞭解全部的關於這個部分的話,不要緊。理解咱們如何經過CSS屬性操做 定位方案和格式化上下文是一個很好的開始。若是你能掌握這一模式的不一樣部分之間的相互做用,你就會比大多數人作得更好。至少你應該知道它們是存在的。

顯示類型

咱們知道在CSS中設置display 屬性能夠決定一個元素怎樣被渲染,可是目前還不清楚它的工做原理是什麼樣的。事實上,有時甚至是不可預測的。

這是由於display 屬性決定了元素的「盒類型」。該隱藏屬性由內部顯示類型和外部顯示類型組成,這些類型一塊兒幫助肯定元素的呈現方式。

外部顯示類型一般解析爲「block」或「inline」,而且幾乎與CSS中的「display」屬性的指望一致。 從技術上講,外部顯示類型決定了元素如何參與其父元素的格式化上下文。

內部顯示類型肯定該元素將生成什麼樣的格式化上下文。 這將影響其子元素的佈局。

想象一下Flexbox容器的工做原理。 它的外部類型是block,其內部類型是flex。 它的子元素外部類型也能夠是block,但它們的佈局受到Flexbox容器的格式上下文的影響。

格式化上下文

格式化上下文是關於佈局的。 它們是管理容器內元素佈局的規則,以及它們如何相互交互。

一些格式化上下文能夠直接在容器上創建,例如經過使用display 的值爲:flex、grid或table。 其餘類型(如塊和內聯格式化上下文)按照瀏覽器的要求建立。

注意事項: 一度,由於它和浮動元素的交互方式,理解如何讓瀏覽器創建一個新的塊格式化上下文很是重要。一個塊格式化上下文的元素會包含浮動的元素。

定位方案

一個盒元素能夠根據3種定位方案中的一種來佈局。這三種方案分別是:正常文檔流佈局, 浮動佈局 和 絕對定位佈局。您可能熟悉浮動和絕對定位佈局的方式,由於咱們在編寫CSS時常常與這些方案進行交互。 當一個元素未浮動或絕對定位佈局時,就是正常文檔流佈局。

正常文檔流佈局
正常文檔流描述了默認的定位方案,「in-flow」描述符合此要求的元素。 在文檔流中您能夠認爲是根據其源的順序和格式化上下文佈局的元素的天然位置。

浮動佈局
Float(浮動)是一個CSS屬性,它使一個元素從正常流中跳出來,並儘量地向左或向右偏移,直到它接觸到其上一級的盒元素或另外一個浮動元素的邊緣。 當這種狀況發生時,文本和內聯元素將包圍浮動元素。

一般若是不設置,元素的高度將適應其全部後代元素。 當元素浮動時,它們從正常文檔流跳出來,這意味着容器不會調整其高度以將其清除。

正是這種行爲容許多種文本、標題和其餘元素對浮動內容進行流式包裹。但有時這是有問題的。清除浮動和創建一個新的塊格式化上下文將使容器清除其浮動的子元素。這種技術容許使用浮動來進行佈局,好久以前這就已經成爲web開發技術之一了。這種技術仍然很重要,但它也正逐漸被新的佈局技術所取代,好比Flexbox和Grid。

絕對定位佈局
絕對定位的元素徹底從文檔流中去除,不一樣於浮動元素,它們對周圍的內容沒有影響。

具備相對定位的容器容許您使用絕對定位來控制後代元素的偏移量。

相對定位的元素也能夠被給定一個偏移量,可是這個偏移量是與元素的正常位置相對的,而不是另外一個相對的容器。

CSS的top, bottom, left 和 right 屬性用來計算「盒容器的偏移量」。這些屬性不是二維偏移,而是每一個邊緣相對於其容器的內容盒子進行定位。

具備重疊偏移的定位元素能夠致使元素佔用相同空間而發生重疊問題。堆疊上下文能夠解決這個問題。

層疊上下文

堆疊上下文決定事物呈現到頁面的順序。 你能夠想象一個堆疊上下文,如圖層。 堆疊底部的圖層首先繪製,堆疊上方的元素出如今頂部(相對於底部來講是在上層)。

在一個絕對或相對定位的元素上設置z-index 是創建新的堆疊上下文的最多見方式。 可是還有其餘一些方法能夠造成堆疊上下文,包括設置不透明度(opacity),轉換(transforms),過濾(filters)或使用will-change屬性。

其中的一些緣由並不直觀,與開發人員的預期相比,更多的是與渲染的性能有關。這有助於理解這些層能夠由瀏覽器單獨渲染。所以,出於性能考慮,故意建立一個新的堆棧上下文有時會頗有用。

除非創建了堆疊上下文,否則設置z-index沒有效果。 z-index的值設置的越高,層疊放置的堆疊越高(越靠近被最終顯示的上層)。

關於堆疊最使人困惑的部分之一是能夠在現有堆疊環境中創建新的堆疊上下文。 這意味着您能夠擁有多層圖層。

在這種狀況下,並不老是擁有最高的z-index值顯示在堆疊越高的位置。

總結

簡短地介紹一些CSS的重要的不爲人熟知的工做原理部分。若是你只是讀了其中的一部分也不要緊。但願這篇文章澄清了一些事情,或者對所涉及的過程有了一個大體的說明。在不犧牲精確性的狀況下,用簡單的術語解釋這些東西是一個真正的挑戰。
圖片描述

相關文章
相關標籤/搜索