做爲程序員,技術的落實與鞏固是必要的,所以想到寫個系列,名爲 why what or how
每篇文章試圖解釋清楚一個問題。css
why what or how
的第二章,什麼是 CSS
?html
CSS
- Cascading Style Sheets
,層疊樣式表程序員
CSS
也算是一種標記語言,其內容做爲瀏覽器的輸入,瀏覽器會解析其文本內容,做爲 HTML
附加的樣式信息,用以修飾標籤。bootstrap
標記語言,一類以固定的形式描述文檔結構或是數據處理細節的語言,通常爲純文本形式,其內容做爲其餘程序的輸入。
樣式表你們都很清楚,記錄樣式信息的表格,以鍵值對的形式存在,格式以下數組
p { font-size: 10px; }
那麼何爲層疊呢?層疊的意義是什麼?瀏覽器
層疊,字面意思:層層疊加,咱們知道 HTML
的頁面結構是樹狀的,不一樣標籤的層級嵌套最終組合造成了頁面,那麼從另外一個角度來看,頁面的結構就是一層一層的,以下圖所示sass
html
爲最底層,body
位於 html
層之上,header
、nav
、article
、aside
、footer
這些標籤位於 body
之上,section
位於 article
之上,標籤的堆疊就造成了網頁結構,那麼這關 CSS
什麼事?less
先拋出一個問題:若是說 article
標籤表明一篇文章,那麼其內部的文字大小,樣式,排版是否是應該一致?ide
是!那麼樣式進行層疊的意義也在於此,只要我給 article
標籤固定的樣式,那麼 article
內部的標籤就會(部分)繼承這個默認的樣式信息,層級結構表明了節點間的關係,那麼就有了父子級的區別,也就有了繼承的關係。佈局
那有的朋友就會問了?如今的 CSS
不就是這樣的嗎?這不是默認的行爲?
CSS
確實如此,但剛開始爲 HTML
進行修飾的樣式規則卻並不是如此,CSS
只是在衆多規則中,最終成爲標準的那一個。
1991 - 1993
年,各類瀏覽器相繼出現,但每一個都實現了本身制定樣式規則,網頁呈現由用戶控制,樣式沒有統一的規定。1993
年,Mosaic
瀏覽器採用增長新種類的 HTML
標籤實現樣式的表達,以知足設計師的要求,<FONT></FONT>
之類表明樣式的標籤開始出現。1994
年,Håkon W Lie
提出層疊 HTML
樣式表(Cascading HTML Style Sheets
),CSS
的雛形出現。1995
年,W3C
創建,W3C
對 CSS
很感興趣,爲此專門組織了一次討論會。1996
年,CSS
語法完成,發佈了 CSS1.0
,但因爲當時主流的瀏覽器並不支持(每家都有本身的樣式寫法),而且當時主流的方式爲 HTML
的樣式標籤,所以 CSS
等幾年後才流行起來。1997
年,W3C
組織了專門管 CSS
的工做組。1998
年,瀏覽器市場份額被微軟公司的 IE4
和網景公司的 Netscape Navigator
兩大瀏覽器巨頭所佔據。IE4
率先實現了 CSS 1.0
但因爲不重視,致使規範實現不完善,bug
不少。因爲不一樣瀏覽器支持的標準不一致,網頁設計人員不得不爲 IE
和 Netscape Navigator
分別設計一套網頁。民間設計人員團體 網頁標準計劃(WaSP)
發動水軍將 W3C
的建議宣揚爲標準,並批評還未加盟 W3C
標準的業界廠商。1998
年,W3C
組織出版 CSS2.0
網頁標準計劃的 7
位成員成立了 CSS武士團(CSS Samurai)
,指出 Opera
瀏覽器和 IE
瀏覽器在支持 CSS
方面存在的諸多問題。Opera
公司着手解決了問題,但微軟並未解決。他們同時也勸說其餘瀏覽器開始支持 CSS
標準。1999
年,W3C
開始制定 CSS3
標準。2003
年,Dave Shea
推出了一個名爲 CSS禪意花園("CSS Zen Garden")
的站點,向人們展現出僅經過應用不一樣頁面樣式規則,就能夠實現對網頁藝術風格的面目一新。2006 - 2009
年, DIV+CSS
佈局逐步取代缺少靈活性的傳統表格佈局,無表格網頁設計成爲網頁內容佈局的主流方案。2009 - 至今
,CSS3
標準已部分公佈,但仍未所有制訂完畢,瀏覽器廠商也逐步跟進,W3C
官方將這些不一樣的特性分門別類,稱爲 modules
,不在沿用 CSS3.0
的版本號,而是將單獨的 module
分別命名,每一個 module
也有不一樣的版本號。CSS
從標準制定,到最終有瀏覽器開始實現,至少間隔了 5
年的時間,而 CSS
的上位也由民間組織推進,到瀏覽器廠商最終採納。直到目前,咱們還能在 HTML
中使用相似 <FONT></FONT>
之類表明樣式的標籤,也是歷史遺留下來的產物,但 HTML5
的推出,規範了 HTML
標籤是做爲網頁的結構,CSS
做爲網頁的樣式信息,所以那些表明樣式的標籤已經被規範所移除,咱們也應該少用甚至不用。
CSS
在衆多的樣式規則中脫穎而出,其實和 IE4
的成功有這很大的關係,IE
系列最早實現了 CSS1.0
標準,能夠說是在與 Netscape Navigator
戰爭中勝利的因素之一,甚至不少的 CSS3
屬性背後也有着 IE
的影子,但後來 IE
系列的落寞很大程度上是由於它的不做爲。
一條 CSS
規則的結構以下:
┌─────── 選擇規則 ──────┐ ┌────────── 聲明塊 ──────────┐ p + p > span:first-child { ┌────── CSS 屬性 ───────┐ font-size : 10px ; └─ 屬性名 ─┘ └─ 屬性值 ─┘ }
由兩部分組成,選擇器與聲明塊。
HTML
中符合要求的標籤一條選擇規則有兩部分組成,選擇器與鏈接符,上面例子中,p
、span
、:first-child
屬於選擇器,而 +
、>
這些符號屬於鏈接符。
一個聲明塊由多條 CSS
屬性組成,屬性分爲兩部分,屬性名與屬性值,以 :
分隔,以 ;
結尾,一條屬性規定了標籤的一個樣式。
選擇規則,意如其名,用於選擇 HTML
文檔中的標籤,那麼如何進行選擇的呢?選擇規則分爲兩部分,咱們分開介紹
選擇器用於選擇 HTML
頁面中存在的標籤。選擇器分爲幾大類,以下:
選擇器類型 | 含義 |
---|---|
元素選擇器(elementname ) |
選擇對應標籤 |
類選擇器(.classname ) |
選取具備對應類名的標籤 |
ID 選擇器(#idname ) |
選取具備對應 ID 的標籤 |
通配選擇器(* ) |
選取全部標籤 |
屬性選擇器([屬性名=值] ) |
選取有相應規則屬性的標籤 |
僞類選擇器 | 選取僞類規定的標籤 |
屬性選擇器有多種寫法,以下:
寫法 | 含義 |
---|---|
[attr] |
選取帶 attr 屬性的標籤 |
[attr=value] |
選取 attr 屬性值爲 value 的標籤 |
[attr~=value] |
選取 attr 屬性中有 value 單詞(單詞不與其餘字母相連)存在的標籤 |
[attr|=value] | 選取 attr 屬性爲 value 或以 value- 開頭的標籤 |
[attr^=value] |
選取 attr 屬性以 value 開頭的標籤 |
[attr$=value] |
選取 attr 屬性以 value 結尾的標籤 |
[attr*=value] |
選取 attr 屬性中含有 value 的標籤 |
注: 屬性選擇器寫法,如 [attr=value]
其後均可以跟 i
,好比 [attr=value i]
表明在匹配時,忽略 value
的大小寫。
經常使用僞類,以下
寫法 | 含義 |
---|---|
:active |
選中被用戶激活的標籤 |
:hover |
選中被鼠標懸浮的標籤 |
:visited |
選中已訪問過的連接 |
:focus |
選中獲取到焦點的標籤 |
:first-child |
選中一組兄弟標籤中的第一個標籤 |
:last-child |
選中一組兄弟標籤中的最後一個標籤 |
:first-of-type |
選中一組兄弟標籤中其類型的第一個標籤 |
:last-of-type |
選中一組兄弟標籤中其類型的最後一個標籤 |
:not(X) |
選中不被 X 選擇器選中的全部標籤 |
:nth-child(an+b) |
a b 爲固定值,n 爲任意天然數,選中一組兄弟標籤中第 an+b 個元素 |
:nth-last-child(an+b) |
同上規則,從後往前匹配 |
:nth-of-type(an+b) |
同上規則,從前日後找,匹配相同類型的標籤 |
:nth-last-of-type(an+b) |
同上規則,從後往前匹配 |
:only-child |
若是父標籤中只有一個子元素則選中該子標籤 |
:only-of-type |
若是父標籤中只有一個該類型的子元素則選中該子標籤 |
鏈接符規定了選擇器該如何進行組合,爲了方便解釋,我會將符號取一個名字,最終的選擇規則表明的含義只需按順序從前日後讀便可。
符號 | 名字 | 含義 |
---|---|---|
'' (無) |
而且 | 選擇器疊加 |
',' |
或者 | 選擇器共用 |
' ' (空格) |
內 | 後代選擇 |
'>' |
內第一級 | 子元素選擇 |
'+' |
以後的第一個 | 相鄰兄弟選擇 |
'~' |
以後的全部 | 兄弟選擇 |
給幾個例子
p.class1
p,div
p .class1
p > .class1
p + .class1
p ~ .class1
咱們順起來念:
p
而且帶有 class1
類名的標籤。p
標籤或者 div
標籤。p
標籤內的帶有 class
類名的標籤。p
標籤內第一級帶有 class
類名的標籤。p
標籤以後的第一個帶有 class
類名的標籤。p
標籤以後的全部帶有 class
類名的標籤。針對於複雜的選擇規則的編寫,好比在 bootstrap
中有這樣一段:
.btn-group > .btn-group:not(:first-child):not(:last-of-type) > .btn { border-radius: 0; }
表明的意義是什麼呢?
按照順序念:選中帶有 btn-group
類名標籤內第一級帶有 btn-group
類名而且不是第一個子元素而且不是最後一個子元素標籤內第一級帶有 btn
類名的標籤。
對應的 html
以下:
<span class="btn-group"> <span class="btn">按鈕1</span> <span class="btn-group"> <span class="btn">按鈕2</span> <span class="btn">按鈕3</span> <span class="btn">按鈕4</span> </span> <span class="btn">按鈕5</span> </span>
選中的標籤爲按鈕2/3/4。
咱們從該條規則的意義來理解這條規則:btn-group
中的 btn-group
下的 btn
不該該有圓角(在中間時)。由於正常的按鈕都是帶圓角的,而放在按鈕組中的按鈕其實只要左右兩邊的按鈕帶上圓角就好,這時候就須要經過特殊的手段來吧這些要去除圓角的元素給選擇,並去掉圓角。
接着咱們在看咱們翻譯出來的內容,是否是不那麼繞了呢?
最後在提一段 bootstrap
中的樣式規則,你們一塊兒翻譯翻譯吧
.btn-group > .btn-group:last-of-type:not(:first-child) > .btn:first-child { border-bottom-left-radius: 0; border-top-left-radius: 0; }
選擇器的內容到此爲止,接下來就要談談聲明塊中的 CSS
屬性了。
CSS 中樣式分不少種,按照樣式效果進行區別,大體能夠分爲以下幾類
大類 | 做用 | 表明屬性 |
---|---|---|
字體 | 控制字體的顯示效果 | font-* color text-transform text-decoration text-shadow |
文字排版 | 控制文字的排版 | text-align text-align-last text-indent text-overflow line-height word-spacing letter-spacing |
背景 | 控制元素背景顯示 | background-* |
佈局 | 控制元素的佈局行爲 | flex 系列屬性 grid 系列屬性 |
文檔流相關 | 控制元素在文檔流中的位置 | position top left bottom right z-index float clear |
列表 | 控制列表的行爲 | list-* |
盒模型 | 控制元素大小 | width height padding border margin box-sizing |
動畫 & 過渡 | 控制元素動畫 | transition-* transform animation-* @keyframes |
該篇僅介紹 CSS
是什麼,而不解釋 CSS
有什麼,因此不過於深究這些屬性的具體內容,能夠經過查看 CSS參考來了解。
開篇咱們就提到了,CSS
爲層疊樣式表,層疊表明的意思爲屬性的繼承。
這個繼承能夠簡單的總結爲一句話:
父級標籤的字體樣式和文章排版樣式會被子標籤所繼承,也就是說子標籤不用寫這些屬性,就擁有了這些屬性。
CSS
中有幾個特殊的屬性值,須要特別關注一下:
unset
- 若是該屬性爲繼承屬性則使用繼承值,不是則使用瀏覽器默認值initial
- 使用初始化的值,也就是瀏覽器默認值inherit
- 使用繼承值因爲相同的標籤能夠由不一樣的選擇規則所選中,那麼這時候就出現了一個狀況,若是有多個選擇規則同時選中了同一個元素,而且同時設置了相同屬性,那麼標籤最終是要按照哪條規則定義的屬性來顯示?
不一樣CSS
規則對同一個標籤設置了相同屬性,CSS
選擇規則權重最高的規則會覆蓋權重低的樣式設置。
何爲權重,通過上面的介紹,CSS
設置標籤的樣式有以下幾種
從上到下,選擇器的權重依次遞減,就像是一樣是一張紙幣,100
的紙幣表明的比 10
塊的紙幣大,可是與紙幣不一樣的是,權重高的永遠比權重低的優先級要高,無論低權重的選擇器有幾個。
除去 style
的方式咱們用一個數組來表明選擇規則的權重。
[0, 0, 0, 0, 0]
從左到右爲:ID 選擇器
、類名選擇器
、僞類
、標籤選擇器
、通配符
,數組的初始值全爲 0
,咱們能夠變看選擇規則來肯定最終數組,好比那個很複雜的 btn
選擇:
.btn-group > .btn-group:not(:first-child):not(:last-of-type) > .btn { border-radius: 0; }
從左到右,每出現一個選擇器,就將對應的數組內的數組加一,那麼上條規則最終的數組以下:
[0, 3, 2, 0, 0]
這時,有的朋友可能會問了,僞類選擇有 4
個啊,怎麼是 2
?這裏須要注意的是::not
僞類僅帶有取反的意思,並不增長權重。
那麼權重該如何比較?
簡單的來講,從前日後比,誰比誰先大,誰的權重高。相信寫一段比較程序你們就瞭解了:
function compare(weight1, weight2){ for(let i = 0; i < 5; i++){ if(weight1[i] !== weight2[i]){ if(weight1[i] > weight2[i]){ console.log('參一權重大'); }else{ console.log('參二權重大'); } return; } } }
那麼 style
所規定的樣式權重如何?
style
樣式所規定的權重,比ID 選擇器
的權重還要高。
那麼咱們想要在 CSS
文件中修改 style
所規定的樣式該怎麼辦?
使用
!important
修飾特定的樣便可。以下所示
p { color: red !important; }
那麼 p
標籤的字體顏色即爲紅色,即便設置了 style
也沒用。
總結一下:權重等級由高到低爲:!important > style > 選擇規則。就像是老大哥說東小弟不敢說西,權重也是絕對服從上一級的。
所以爲了不出現尷尬的情況,請慎重使用 !important
。
CSS
發展到如今,人們發現 CSS
雖然含有層疊的含義,可是寫法倒是一維的,就好比文檔結構以下的一個網頁:
<article> <p>這是一段文字</p> </article>
咱們要在 article
,p
標籤上設置樣式,看起來是這樣的:
article { font-size: 14px; } article p { color: red; }
因爲樣式規則按照一條一條的形式進行編寫,看起開就是一維,標籤的層級結構不能在其中體現,若是這樣寫那就行了:
article { font-size: 14px; p { color: red; } }
從樣式編寫上就說明了層級結構,p
標籤所繼承的樣式明瞭,可是瀏覽器又僅能識別一維的樣式編寫,那該如何讓瀏覽器認識該結構呢?
預編譯器因運而生,經常使用的 css
預編譯器有:sass
、less
、stylus
等,這些預編譯器須要特定的語法,但都支持二維的寫法。
那麼這些個預編譯幹了什麼?
很簡單的一句話,將符合預編譯器語法的文件轉化爲
css
文件。
一樣的這些預編譯器的語法,這裏不過多介紹,提供幾個網站供你們查閱:
我是在 2019
年寫下這篇文章,爲什麼要特意的聲明時間,是由於一個東西的出現:CSS Modules
,咱們須要好好來了解了解。
何爲 CSS Modules
,官方解釋以下:
CSS files in which all class names and animation names are scoped locally by default.
翻譯過來就是:
CSS 的類名和動畫名字都在一個命名空間下。
不懂?寫個例子。
如下爲僞源碼:
// test.css .box{ color:red; }
import style from 'test.css' function Test(){ return (<div class={style.box} />) }
如下爲僞輸出:
<div class="_styles__box_34682763478"></div>
_styles__box_34682763478
就是在加了命名空間後的類名,這樣構建出的代碼就不會出現相同類名被覆蓋的問題。
總的來講,CSS Modules
作了一件時,混淆了class
類名、id
和動畫名。
這時就有一些開發站出來講,這個東西好啊,我不再用去想類名該如何取才能不致使衝突了。冷靜下來先考慮這幾個問題:
JavaScript DOM API
?若是是,那麼經過樣式名選取變的不可靠。CSS Modules
後項目中是否出現了極多的 :global
若是是,那要仔細思考下,不用 CSS Modules
成本是否更低?如下是問題對應的一些場景
問題一:你引用了團隊中其餘人寫的組件,但須要你本身修改(覆蓋)一些樣式,而其餘人也是用 CSS Modules
編寫樣式,所以他的類名是不固定的,你該如何去覆蓋這個組件中標籤的樣式?
CSS Modules
的意義在於哪?問題三四:當你程序須要使用 DOM API
但經過 CSS Modules
生成的樣式名會隨着文件的位置或內容改變,這樣程序就變得不可靠,固然這個問題有辦法解決
js
中也用 CSS Modules
的命名,只不過調試變得些許困難js
中使用的樣式名與 CSS Modules
進行區分,js
和 CSS Modules
使用兩套樣式單獨的樣式那麼接下來講說個人使用體驗,或者說我以爲好的使用體驗
CSS Modules
和原始的 CSS
一同使用。CSS Modules
僅使用在組件內部,項目中依然使用公共樣式。CSS Modules
僅使用在一些與結構無關的但又很差命名的標籤上,這些標籤通常也不會被 js
所選擇。CSS Modules
混淆採用和文件位置相關的命名空間產生方式,而不根據文件內容。CSS Modules
,經過項目規定的命名空間在原始 CSS
文件中定義。UI
庫或公共組件,不用 CSS Modules
。總的來講就是一個原則,CSS Modules
用在非共用,無所謂命名以及非跨組件通用的標籤上,這些標籤能夠認爲是組件的內部狀態,不會被外部影響或修改。
也不知道多年之後 CSS Modules
是否真的解決了編譯慢的問題(至少個人電腦上是),CSS Modules
原理上還是傳統的 CSS
編寫方式,只不過它混淆了名稱,並添加了映射,可是之後的發展會如何呢?我不知道,但我會持續的關注它。
慣例以問句開篇,用問句來結尾
CSS
的層疊體如今哪?CSS
選擇規則分爲那兩部分,每部分都如何組成?CSS Modules
是什麼?CSS Modules
的見解吧。最後,其實本篇還想談談佈局和文檔流的內容,但篇幅過長,也涉及到了 HTML
,因此就打算將佈局單獨出來,之後會有如何進行網頁佈局的單篇,已經記錄,但願你們持續關注。
該系列全部問題由 minimo
提出,愛你喲~~~