為什麼 CSS 這麼難學?

飢人谷前端發表於2018-01-09

本文為飢人谷講師方方原創文章

CSS 不正交併不是對 CSS 的指責,如果能正交它肯定會做到正交的,現在的設計雖然不完美,但可能是最好的設計。

下文列舉的問題能在規範裡找到解釋不能說明 CSS 是正交的,因為正不正交應該是從表面上就能看出來的。正交一般都是對介面的約束,具體實現我不管的。

本答案可以很好地解釋「為什麼你會覺得 CSS 難學」,至於不難的學習方式,其實是不存在的。要麼你大量練習從實踐中總結,要麼你大量閱讀文件從理論中領悟,反正 CSS 就是很難學。

我是這麼覺得的,如果有人問 CSS 為什麼這麼難學,我們就應該好好回答 CSS 為什麼這麼難學;至於 CSS 多牛逼,應該另開一個問題。

短答案:因為 CSS 不正交。

長答案: 我先來解釋一下什麼是正交。 你調過顯示器的「亮度」、「色調」和「飽和度」吧。

  • 「亮度」就是明暗程度,值越大,螢幕越亮。
  • 「色調」就是顏色,你通過調色調,可以把紅色調成綠色。
  • 「飽和度」就是鮮豔程度,值越大越鮮豔。 「正交」就是,你調節這三者中的一個時,不影響其他兩個效果。
  • 你調節「亮度」的時候「色調」和「飽和度」不會變化。
  • 你調節「色調」的時候「亮度」和「飽和度」不會變化。
  • 你調節「飽和度」的時候「亮度」和「色調」不會變化。 「正交」看起來應該是理所當然的,對吧。想象一下「不正交」的情況:你調節「亮度」的時候,「色調」和「飽和度」會跟著無規律的變化。如果是這樣,你會調得想死,因為你很難調到你想要的效果。

而 CSS,就是「不正交」的。

我以 width 對 margin-left 的影響為例,假設有如下程式碼:

為什麼 CSS 這麼難學?

.parent 裡面的 .child 寬度為 300px,現在我給他新增一個 margin-left: -10px,會發現

為什麼 CSS 這麼難學?

整個 .child 左移 10 畫素
複製程式碼

好的,於是我們知道 margin-left: -10px 會讓元素整體左移。

真的是這樣嗎?

這個時候把 width 去掉重新做實驗,這是在新增 margin-left 之前:

為什麼 CSS 這麼難學?

這是在新增 margin-left 之後:

為什麼 CSS 這麼難學?

我們發現 margin-left: -10px 並沒有讓整個元素左移,只是讓左邊緣左移了,右邊緣並沒有動。

現在來總結一下:

  1. 如果指定了 width,那麼 margin-left: 10px 會使元素整體左移
  2. 如果沒有指定 width,那麼 margin-left: 10px 只會使做邊緣左移(也就是寬度擴大)

看到這裡,你就會覺得 CSS 特別不正交:

  1. 為什麼 width 的存在與否會影響 margin-left 的作用?
  2. 有沒有 width 之外的其他屬性也會影響 margin-left 的作用?恐怕你無法得知。 這就是不正交的恐怖之處,你只有把所有屬性與 margin-left 一起用一下,才能得知 margin-left 的真正規律。

這還只是兩個屬性的影響,你能想象三個屬性互相影響的情況嗎?

P.S. 有些前端老手已經能「感性」地理解 width: auto 的意義,覺得這不是「不正交」。其實我只是舉例說明「你無法只看一個屬性就知道這個屬性對應的效果,你必須結合另一個屬性一起來看」。

我再舉第二個例子,大家都知道 position: fixed 是相對於視口(viewport)定位的。

但是這個「真理」會受另一個元素的影響……對,我知道你很震驚……

先看正常情況:

為什麼 CSS 這麼難學?

網頁右邊是一個 iframe,紅色的 .fixed 元素相對於 iframe 視口左上角定位,與我們預期一致。

接下來我在 .box 上面加一個 CSS3 中的屬性,就會改變你的認知:

為什麼 CSS 這麼難學?

父容器加了 transform 之後,fixed 定位的元素居然相對於父容器定位。

天知道以後 CSS 會不會加更多元素來影響我已經認為是真理的事情?

我說一個更實際的問題吧,你敢在接手一個專案時,在任意一個元素上加 transform 屬性嗎?

你不敢!除非你把它的每個子元素的屬性都檢查一遍……確定沒有 fixed 定位。

這就是「不正交」的噁心之處。

我再舉一個例子,大家都知道給固定寬度的 div 加 margin: 0 auto 可以讓它水平居中,很多人就問,那為什麼 margin: auto 0(注意 auto 和 0 的位置反過來了)不能做到垂直居中呢?

其實是可以的:

為什麼 CSS 這麼難學?

但是必須是在當前元素有 position: absolute; top: 0; bottom:0; 的情況下才能垂直居中。或者與 flex 結合起來用也行。

這就很「不正交」了……

還有一些很常見的例子我就不一一詳細列舉了:

  1. border、padding、overflow、display:table、display:inline-block 會影響 margin
  2. position: absolute 會影響 display 和 float
  3. transform 會影響 z-index
  4. display 會影響 li 前面的小黑點 JS Bin 關鍵在於這些例子,要一個一個記,各屬性被影響的情況都不一樣!

CSS 最不正交的地方就是明明有 BFC,卻非要把 BFC 藏起來,然後用 overflow:hidden 和 display: inline-block 等屬性來觸發 BFC。但用這些屬性觸發 BFC 總是會有副作用,這就是典型的不正交。

要觸發 BFC 就單獨發明一個觸發 BFC 的屬性不就好了。display: flow-root; 不就是在填這個坑嘛?所以你們說 CSS 是正交的,我肯定是不服的。

怎麼學習「不正交」的東西?

有一個辦法:試。

你試的組合情況越多,就越能瞭解各種奇怪的現象。

其實不用那麼悲觀,常用的組合也就幾十種吧,都試出來並記下來就行了。

目前我們知道

  1. 不同屬性的組合會有不同的效果;
  2. 新的屬性會影響你已經學會的知識;
  3. 這些規律,毫無邏輯可言,你只能試出來。 這,就是 CSS 難學的原因。

以我的經驗,越是理性的人,越難理解 CSS;越是感性的人,越容易理解 CSS。

這就是為什麼大部分後端程式設計師能學會 JS,卻學不會 CSS——他們太理性了。

你想用學程式設計的思路來學 CSS?放棄吧!

你需要用學畫畫的思路來學習 CSS——每天不停地畫畫,一個雞蛋用不同的方式畫一千遍,就成了。

所以我在課上說過一句話: CSS 不是科學,CSS 是藝術。

不過凡事都有例外,如果你願意老老實實看完 CSS 規格文件,然後再寫 CSS,可能就不覺得有那麼多不正交的地方了,但是有多少人有這個能力和精力呢?

P.S. 「正交」概念我是從《Unix程式設計藝術》學到的,少逛知乎多讀書吧。

文中指出 CSS 不正交,使得你改動一處,就會在另一處出錯,大概就像下圖這樣:

為了讓 CSS 不難學,我們創作了一套課程

就在今天,飢人谷歷經兩個月時間錄製的 《CSS深入淺出》系列視訊 也錄製完了,共包含 53 個視訊和 12 個任務,還推薦了很多CSS相關的優秀網站,視訊內容有:

為什麼 CSS 這麼難學?

  • CSS 學習思路
  • 寬度與高度(文件流)
  • 堆疊上下文
  • icon 全解
  • 移動端頁面(響應式)
  • Flex 佈局
  • 佈局套路
  • 為什麼這麼多人講不清楚 BFC
  • 動態 REM
  • 表單美化
  • Bootstrap 的使用方法就是複製貼上
  • IFC(BFC的兄弟)

如果你學習 CSS 的時候遇到瓶頸,希望有人用更直觀的形式教會你,可以考慮購買這套視訊。

同時該視訊裡有 3 節課可免費試看,你可以先試看再購買。

希望我們能使 CSS 稍微變得好學一點。

加微訊號: astak10或者長按識別下方二維碼進入前端技術交流群 ,暗號:寫程式碼啦

每日一題,每週資源推薦,精彩部落格推薦,工作、筆試、面試經驗交流解答,免費直播課,群友輕分享... ,數不盡的福利免費送

為什麼 CSS 這麼難學?

相關文章