CSS 為什麼這麼難學?

飢人谷前端發表於2017-12-19

最近半年,我一直都沒在知乎上遇到好的前端問題,而這個問題,問到我心坎上了。

在過去一年的教學過程中,不斷有學生嘗試理性地理解 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 的真正規律。

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

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

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

先看正常情況:

CSS 為什麼這麼難學?

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

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

CSS 為什麼這麼難學?

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

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

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

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

其實是可以的:

CSS 為什麼這麼難學?

但是必須是在當前元素有 position: absolute; top: 0; bottom:0; 的情況下才能垂直居中。這就很「不正交」了。

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

只有一個辦法:試。

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

別無他法。

目前 CSS 常用的屬性就按 50 個算吧,兩種屬性組合一共有 50 * 49 / 2 = 1225 種情況,三種屬性組合一共有 50 * 49 * 48 / 6 = 19600 種情況。這還沒有算上父子元素的互相影響的情況。

少年,你有生之年,慢慢試吧。

目前我們知道

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

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

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

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

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

所以我在課上說過一句話:

CSS 不是科學,CSS 是藝術。

P.S. 「正交」概念我是從《Unix程式設計藝術》學到的,少逛社群多讀書吧。關注【飢人谷前端】——一個有愛的前端交流社群。

相關文章