熱議:CSS為什么這么難學?一定是你的方法不對
大家好,我是零一。前段時間我在知乎刷到這樣一個提問:為什么CSS這么難學?

看到這個問題以后,我仔細一想,CSS學習起來好像是挺困難的,它似乎沒有像JavaScript那樣非常系統(tǒng)的學習大綱,大家平時也不會用到所有的CSS,基本上用來用去就是那么幾個常用的屬性,甚至就連很多培訓機構的入門教學視頻都也只會教你一些常用的CSS(不然你以為一個幾小時的教學視頻怎么能讓你快速入門CSS的呢?)
一般別人回答你CSS很好學也是因為它只用那些常用的屬性,他很有可能并沒有深入去了解。要夸張一點說,CSS應該也能算作一門小小的語言了吧,深入研究進去,知識點也不少。我們?nèi)绻皇菍iT研究CSS的,也沒必要做到了解CSS的所有屬性的使用以及所有后續(xù)新特性的語法,可以根據(jù)工作場景按需學習,但要保證你學習的屬性足夠深入~
那么我們到底該如何學習CSS呢? 為此我列了一個簡單的大綱,想圍繞這幾點大概講一講

一、書籍、社區(qū)文章
這應該是大家學習CSS最常見的方式了(我亦如此)。有以下幾個場景:
場景一:開發(fā)中遇到「文本字數(shù)超出后以省略號(...)展示」的需求,打開百度搜索:css字數(shù)過多用省略號展示,誒~搜到了!ctrl+c、ctrl+v,學廢了,完工!

場景二:某天早晨逛技術社區(qū),看到一篇關于CSS的文章,看到標題中有個CSS屬性叫resize,resize屬性是啥,我咋沒用過?點進去閱讀得津津有味~ two minutes later ~ 奧,原來還有這個屬性,是這么用的呀,漲姿勢了!

場景三:我決定了,我要好好學CSS,打開購物網(wǎng)站搜索:CSS書籍,迅速下單!等書到了,開始每天翻閱學習。當然了此時又有好幾種情況了,分別是:
就只有剛拿到書的第一天翻閱了一下,往后一直落灰
看了一部分,但又懶得動手敲代碼,最終感到無趣放棄了閱讀
認認真真看完了書,也跟著書上的代碼敲了,做了很多筆記,最終學到了很多

無論是上面哪幾種方式,我覺得都是挺不錯的,順便再給大家推薦幾個不錯的學習資源
張鑫旭大佬的博客[1] 大漠老師的W3Cplus[2] coco大佬的iCSS[3]
畢竟站在巨人的肩膀上,才是最高效的,你們可以花1個小時學習到大佬們花1天才總結出來的知識
二、記住CSS的數(shù)據(jù)類型
CSS比較難學的另一個點,可能多半是因為CSS的屬性太多了,而且每個屬性的值又支持很多種寫法,所以想要輕易記住每個屬性的所有寫法幾乎是不太可能的。最近在逛博客時發(fā)現(xiàn)原來CSS也有自己的數(shù)據(jù)類型,這里引用一下張鑫旭大佬的CSS值類型文檔大全[4],方便大家后續(xù)查閱
簡單介紹一下CSS的數(shù)據(jù)類型就是這樣的:

圖中用<>括起來的表示一種CSS數(shù)據(jù)類型,介紹一下圖中幾個類型:
<number>:表示值可以是數(shù)字 <length>:表示元素的尺寸長度,例如 3px、33em、34rem<percentage>:表示基于父元素的百分比,例如 33%<number-percentage>:表示值既可以是 <number>,也可以是 <percentage> <position>:表示元素的位置。值可以是 <length>、<percentage>、 left/right/top/bottom
來看兩個CSS屬性:
第一個是 width,文檔會告訴你該屬性支持的數(shù)據(jù)類型有 <length> 和 <percentage>,那么我們就知道該屬性有以下幾種寫法:width: 1px、width: 3rem、width: 33em、width: 33%第二個屬性是 background-position,文檔會告訴你該屬性支持的數(shù)據(jù)類型有 <position>,那么我們就知道該屬性有以下幾種寫法:background-position: left、background-position: right、background-position: top、background-position: bottom、background-position: 30%、background-position: 3rem
從這個例子中我們可以看出,想要盡可能得記住更多的CSS屬性的使用,可以從記住CSS數(shù)據(jù)類型(現(xiàn)在差不多有40+種數(shù)據(jù)類型)開始,這樣你每次學習新的CSS屬性時,思路就會有所轉變,如下圖
沒記住CSS數(shù)據(jù)類型的我:

記住CSS數(shù)據(jù)類型的我:

不知道你有沒有發(fā)現(xiàn),如果文檔只告訴你background-position支持 <position> 數(shù)據(jù)類型,你確定你能知道該屬性的全部用法嗎?你確實知道該屬性支持background-position: 3rem這樣的寫法,因為你知道 <position> 數(shù)據(jù)類型包含了 <length> 數(shù)據(jù)類型,但你知道它還支持background-position: bottom 50px right 100px;這樣的寫法嗎?為什么可以寫四個值并且用空格隔開?這是誰告訴你的?
這就需要我們了解CSS的語法了,請認真看下一節(jié)
三、讀懂CSS的語法
我之前某個樣式中需要用到裁剪的效果,所以準備了解一下CSS中的clip-path屬性怎么使用,于是就查詢了比較權威的clip-path MDN[5],看著看著,我就發(fā)現(xiàn)了這個

我這才意識到我竟然連CSS的語法都看不懂。說實話,以前無論是初學CSS還是臨時找一下某個CSS屬性的用法,都是直接百度,瞬間就能找到自己想要的答案(例如菜鳥教程),而這次,我是真的傻了! 因為本身clip-path這個屬性就比較復雜,支持的語法也比較多,光看MDN給你的示例代碼根本無法Get到這個屬性所有的用法和含義(菜鳥教程就更沒法全面地教你了)
于是我就順著網(wǎng)線去了解了一下CSS的語法中的一些符號的含義,幫助我更好得理解語法
因為關于CSS語法符號相關的知識在CSS屬性值定義語法 MDN[6]上都有一篇超級詳細的介紹了(建議大家一定要先看看MDN這篇文章!!非常通俗易懂),所以我就不多做解釋了,這里只放幾個匯總表格
屬性組合符號
屬性組合:表示多個屬性值的書寫組合情況。例如在border: 1px solid #000中,1px能否和solid互換位置、#000能否省略等等,這些都是屬性的組合情況
| 符號 | 名稱 | 作用 |
|---|---|---|
| 空格 | 并置 | 空格左右兩側的屬性順序不能互換 |
| , | 逗號(分隔符) | 逗號兩側的屬性之間必須用逗號隔開 |
| / | 斜杠(分隔符) | 斜杠兩側的屬性之間必須用斜杠隔開 |
| && | "與"組合符 | "與"組合符兩側的屬性都必須出現(xiàn),但左右順序隨意 |
| || | "或"組合符 | "或"組合符兩側的屬性至少出現(xiàn)一個,且左右順序隨意 |
| | | "互斥"組合符 | "互斥"組合符兩側的屬性恰好只出現(xiàn)一個 |
| [] | 中括號 | 中括號包住的內(nèi)容表示一個整體,可以類似看成數(shù)學中的小括號() |
組合符優(yōu)先級
"與"組合符、"或"組合符、"互斥"組合符都是為了表示屬性值出現(xiàn)的情況,但這三者之間還有個優(yōu)先級。例如bold | thin || <length>,其中“或”組合符的優(yōu)先級高于“互斥”組合符,所以該寫法等價于bold | [thin || <length>]
| 符號 | 名稱 | 優(yōu)先級(數(shù)字越大,優(yōu)先級越大) |
|---|---|---|
| 空格 | 并置 | 4 |
| && | "與"組合符 | 3 |
| || | "或"組合符 | 2 |
| | | "互斥"組合符 | 1 |
屬性重復符號
屬性重復:表示某個或某些屬性的出現(xiàn)次數(shù)。例如在rgba(0, 0, 0, 1)中,數(shù)字的個數(shù)能否是3個、最后一位能否寫百分比。這有些類似于正則的重復符號
| 符號 | 名稱 | 作用 |
|---|---|---|
| 無 | 不寫符號 | 默認。不寫符號表示這個屬性只出現(xiàn)一次 |
| + | 加號 | 加號左側的屬性或整體出現(xiàn)一次或多次 |
| ? | 問號 | 問號左側的屬性或整體出現(xiàn)零次或一次 |
| * | 星號 | 星號左側的屬性或整體出現(xiàn)零次或一次或多次 |
| # | 井號 | 井號左側的屬性或整體出現(xiàn)一次或多次,且以逗號(,)隔開 |
| {A, B} | 大括號 | 大括號左側的屬性或整體最少出現(xiàn)A次,最多出現(xiàn)B次 |
| ! | 感嘆號 | 感嘆號左側的整體中必須出現(xiàn)一個屬性,即使該整體中全部屬性都聲明了可以出現(xiàn)零次 |
解讀CSS語法
以本節(jié)clip-path的語法為例,我們來簡單對其中某一個屬性來進行解讀(只會解讀部分哦,因為解讀全部的話篇幅會很長很長)
先看看整體的結構

一共分為四部分,順序是從上到下的,每兩個部分之間都以where來連接,表示的是where下面的部分是對上面那個部分的補充解釋
①:表示的是clip-path這個屬性支持的寫法為:要不只寫 <clip-source> 數(shù)據(jù)類型的值,要不就最起碼從 <basic-shape> 和 <geometry-box> 這兩者之間選一種類型的值來寫,要不就為none。
②:我們得知①中的 <basic-shape> 數(shù)據(jù)類型支持的寫法為:inset()、circle()、ellipse()、polygon()、path()這5個函數(shù)
③:因為我們想了解circle()這個函數(shù)的具體使用,所以就先只看這個了。我們得知circle()函數(shù)的參數(shù)支持 <shape-radius> 和 <position> 兩種數(shù)據(jù)結構,且兩者都是可寫可不寫,但如果要寫 <position> ,那前面必須加一個at
④:首先看到 <shape-radius> 支持的屬性是 <length-percentage> (這個顧名思義就是<length>和<percentage>)、closest-side、farthest-side。而 <position> 數(shù)據(jù)類型的語法看起來就比較復雜了,我們單獨來分析,因為真的非常非常長,我將 <position> 格式化并美化好給你展現(xiàn)出來,便于你們閱讀(我也建議你們?nèi)绻趯W習某個屬性的語法時遇到這么長的語法介紹,也像我一下把它格式化一下,這樣方便你們閱讀和理解)

如圖可得,整體分為三大部分,且這三部分是互斥關系,即這三部分只能出現(xiàn)一個,再根據(jù)我們前面學習的CSS語法的符號,就可以知道怎么使用了,因為這里支持的寫法太多了,我直接列個表格吧(其實就是排列組合)!如果還有不懂的,你們可以仔細閱讀一下MDN的語法介紹或者也可以評論區(qū)留言問我,我看到會第一時間回復!
<position>類型支持的寫法
| 第一部分 | 第二部分 | 第三部分 |
|---|---|---|
left | left | left 30px top 30px 或 top 30px left 30px |
center | center | left 30px top 30% 或 top 30% left 30px |
right | right | left 30px bottom 30px 或 bottom 30px left 30px |
top | 30% | left 30px bottom 30% 或 bottom 30% left 30px |
bottom | 3px 或 3em 或 3rem 等長度值 | left 30% top 30px 或 top 30px left 30% |
left top 或 top left | left top | left 30% top 30% 或 top 30% left 30% |
left center 或 center left | left center | left 30% bottom 30px 或 bottom 30px left 30% |
left bottom 或 bottom left | left bottom | left 30% bottom 30% 或 bottom 30% left 30% |
center center | left 30% | right 30px top 30px 或 top 30px right 30px |
right top 或 top right | left 30px | right 30px top 30% 或 top 30% right 30px |
right center 或 center right | center top | right 30px bottom 30px 或 bottom 30px right 30px |
right bottom 或 bottom right | center center | right 30px bottom 30% 或 bottom 30% right 30px |
center bottom | right 30% top 30px 或 top 30px right 30% | |
center 30% | right 30% top 30% 或 top 30% right 30% | |
center 30px | right 30% bottom 30px 或 bottom 30px right 30% | |
right top | right 30% bottom 30% 或 bottom 30% right 30% | |
right center | ||
right bottom | ||
right 30% | ||
right 30px | ||
30% top | ||
30% center | ||
30% bottom | ||
30% 30% | ||
30% 30px | ||
30px top | ||
30px center | ||
30px bottom | ||
30px 30% | ||
30px 30px |
嚯!累死我了,這支持的寫法也太多太多了吧!
四、多動手嘗試
上一節(jié),我們在學習clip-path屬性的語法以后,知道了我們想要的圓圈裁剪(circle())的語法怎么寫,那么你就真的會了嗎?可能你看了MDN給你舉的例子,知道了circle(40%)大致實現(xiàn)的效果是咋樣的,如下圖

如我前文說的一樣,MDN只給你列舉了circle()這個函數(shù)最簡單的寫法,但我們剛剛學習了其語法,得知還有別的寫法(例如circle(40% at left)),而且MDN文檔也只是告訴你支持哪些語法,它也并沒有明確告訴你,哪個語法的作用是怎么樣的,能實現(xiàn)什么樣的效果。
此時就需要我們自己上手嘗試了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>嘗試clip-path的circle()的使用</title>
<style>
#zero2one {
width: 100px;
height: 100px;
background-color: ;
clip-path: circle(40%); <!-- 等會就在這一行改來改去,反復嘗試! -->
}
</style>
</head>
<body>
<div id="zero2one"></div>
</body>
</html>
看一下效果,嗯,跟MDN展示的是一樣的

再修改一下值clip-path: circle(60%),看看效果

我似乎摸出了規(guī)律,看樣子是以元素的中心為基準點,60%的意思就是從中心到邊緣長度的60%為半徑畫一個圓,裁剪掉該圓之外的內(nèi)容。這些都是MDN文檔里沒有講到的,靠我親手實踐驗證出來的。
接下來我們來試試其它的語法~
試試將值改成clip-path: circle(40% at top)

誒?很神奇!為什么會變成這個樣子,我似乎還沒找到什么規(guī)律,再把值改一下試試clip-path: circle(80% at top)

看樣子圓心挪到了元素最上方的中間,然后以圓心到最下面邊緣長度的80%為半徑畫了個圓進行了裁剪。至此我們似乎明白了circle()語法中at 后面的<position>數(shù)據(jù)類型是干什么的了,大概就是用來控制裁剪時畫的圓的圓心位置
剩下的時間就交給你自己來一個一個試驗所有的語法了,再舉個簡單的例子,比如你再試一下clip-path: circle(40% at 30px),你一定好奇這是啥意思,來看看效果

直觀上看,整個圓向左移動了一些距離,在我們沒設置at 30px時,圓心是在元素的中心的,而現(xiàn)在似乎向右偏移了,大膽猜測at 30px的意思是圓心的橫坐標距離元素的最左側30px
接下來驗證一下我們的猜測,繼續(xù)修改其值clip-path: circle(40% at 0)

很明顯此時的圓心是在最左側的中間部分,應該可以說是證明了我們剛才的猜測了,那么不妨再來驗證一下縱坐標的?繼續(xù)修改值clip-path: circle(40% at 0 0)

不錯,非常順利,at 0 0中第二個0的意思就是圓心縱坐標離最上方的距離為0的意思。那么我們此時就可以放心得得出一個結論了,對于像30px、33em這樣的 <length> 數(shù)據(jù)類型的值,其對應的坐標是如圖所示的

好了,本文篇幅也已經(jīng)很長了,我就不繼續(xù)介紹其它語法的使用了,剛才純粹是用來舉個例子,因為本文我們本來就不是在介紹circle()的使用教程,感興趣的讀者可以下去自己動手實踐哦~
所以實踐真的很重要很重要!!MDN文檔沒有給你列舉每種語法對應的效果,因為每種都列出來,文檔看著就很雜亂了,所以這只能靠你自己。記得張鑫旭大佬在一次直播中講到,他所掌握的CSS的特性,也都是用大量的時間去動手試出來的,也不是看看啥文檔就能理解的,所以你在大佬們的一篇文章中了解到的某個CSS屬性的使用,可能是他們花費幾小時甚至十幾個小時研究出來的。
CSS很多特性會有兼容性問題,因為市面上有很多家瀏覽器廠商,它們支持的程度各不相同,而我們平常了解CSS某個屬性的兼容性,是這樣的
查看MDN的某個屬性的瀏覽器兼容性

通過Can I Use[7]來查找某個屬性的瀏覽器兼容性

這些都是正確的,但有時候可能某些CSS屬性的瀏覽器兼容性都無法通過這兩個渠道獲取到,那么該怎么辦呢?手動試試每個瀏覽器上該屬性的效果是否支持唄(鑫旭大佬說他以前也會這么干),這點我就不舉例子了,大家應該能體會到
?? 最后
其實每個CSS大佬都不是因為某些快捷的學習路徑而成功的,他們都是靠著不斷地動手嘗試、記錄、總結各種CSS的知識,也會經(jīng)常用學到的CSS知識去做一個小demo用于鞏固,前幾個月加了大漠老師的好友,我就經(jīng)常看到他朋友圈有一些CSS新特性的demo演示代碼和文章(真心佩服),coco大佬也是,也經(jīng)常會發(fā)一些單純用CSS實現(xiàn)的炫酷特效
另外,如果想要更加深入,你們還可以關注一下CSS的規(guī)范,這個比較權威的就是W3C的CSS Working Group[8]了,里面有很多CSS的規(guī)范文檔

好了,再推薦幾本業(yè)界公認的還算不錯的書籍吧~例如《CSS權威指南》、《CSS揭秘》、《CSS世界》、《CSS新世界》等等...
最后對于「如何學習CSS?」這個話題,你還有什么問題或者你覺得還不錯的學習方法嗎?歡迎在評論區(qū)留言討論~
參考資料
張鑫旭大佬的博客: https://www.zhangxinxu.com/
[2]W3Cplus: https://www.w3cplus.com/
[3]iCSS: https://github.com/chokcoco/iCSS
[4]CSS值類型文檔大全: https://www.zhangxinxu.com/wordpress/2019/11/css-value-type/
[5]clip-path MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
[6]CSS屬性值定義語法 MDN: https://developer.mozilla.org/zh-CN/docs/Web/CSS/Value_definition_syntax
[7]Can I Use: https://caniuse.com/
[8]CSS Working Group: https://www.w3.org/Style/CSS/current-work
