函數(shù)式 CSS

2018-06-16 18:02 更新

Wealthfront我們是一個函數(shù)式編程的超級粉絲。強(qiáng)調(diào)不變性和函數(shù)式風(fēng)格意味著更少的“意外”(surprises),因?yàn)楦弊饔檬怯邢薜幕虿淮嬖诘?。我們能將?dú)立的組件迅速構(gòu)建出大型系統(tǒng),通過組合的方式組合組件。函數(shù)式編程原則直接應(yīng)用在大多數(shù)語言中,即使他們不是被定義為函數(shù)式。同樣適用非函數(shù)式的css。讓我們看下我們最喜歡的(和最討厭的)一些特性在樣式語言中。

  • 一切都是全局作用域。
  • 一切都是可變的。
  • 優(yōu)先級的計算,基于一些有趣的規(guī)則。

因此讓我們討論下我們能做什么。Wealthfront的 CSS(實(shí)際是 SCSS)風(fēng)格指南概述一些經(jīng)驗(yàn)法則,讓我們在CSS中獲得函數(shù)式編程范式的效益。確切的說,指南通過限制副作用減少意外,提倡組合使我們的樣式表更具伸縮性。在本文中,我將介紹一些我們的樣式指南中的主要的規(guī)則。

引入作用域

大部分語言中,變量定義被限制在它們的作用域內(nèi)。在Javascript中,變量的作用域是他們所在的函數(shù),而其他語言中,如Java變量具有塊級作用域。我在我的作用域里定義的變量不能被其他人在我的作用域外重定義或修改。

作用域是防御式編程和降低副作用的重要部分。如果您的規(guī)則、函數(shù)或變量只存在于一個受限的作用域,那么你可以放心沒人會更改它,無論是有意還是無意的。

CSS沒有作用域。樣式定義時可能意外重寫其他規(guī)則,而且無法保證你挑選的樣式規(guī)則名稱沒被其他人使用。它可能在完全不同的文件里,并且是深度嵌套的選擇符。假如你問你的樣式規(guī)則選擇了一個相同的名字,則意外重寫其他人規(guī)則的概率驟然升高。讓我們思考下面的例子:

/* profile.css */
.error { color: orange; }
.success { color: blue; }
/* signup.css */
.error { color: red; }
.success { color: green; }

假如我們在我們的HTML中引入上面的CSS文件,我們無意中用其中一個樣式重寫(覆蓋)了另一個。隨著網(wǎng)站的增長,這種狀況變得越來越復(fù)雜和普遍。

那么我們?nèi)绾卧贑SS中引入作用域呢?

在CSS中模擬更細(xì)粒度的作用域的安全做法是用命名約定。在這種情況下,我們?yōu)槲覀兯械臉邮揭?guī)則設(shè)置命名空間通過添加一個前綴。前綴命名空間規(guī)則不是一個新的理念,但重要的是我們知道我們?yōu)槭裁茨菢幼觥T谇熬Y的樣式中我們創(chuàng)造了我們的“作用域”,你可以說我們的css是在“prefix”作用域內(nèi)——我們的樣式只在設(shè)置了前綴的規(guī)則中存在。

讓我們用前綴符嘗試修改前面的例子:

/* profile.css */
.profile-error { color: orange; }
.profile-success { color: blue; }
/* signup.css */
.signup-error { color: red; }
.signup-success { color: green; }

加前綴允許我們封裝我們的規(guī)則,保護(hù)它們免受修改。有了這些附加的前綴,我們的規(guī)則不再沖突。我們使他們免受副作用,通過聲明我們的規(guī)則在命名空間作用域中。

減小依賴,增大可重用性

通過使用復(fù)雜的選擇符來保持我們的標(biāo)記整潔和無類是很容易的。我們都見過像下面這樣的CSS:

.whitepaper-link {
  font-weight: bold;
  font-size:12px;
}

.main-nav .whitepaper-link {
  font-size:16px;
}

.main-footer .whitepaper-link {
  font-size:9px;
}

但如果我們想在其他地方有小號的.whitepaper-link呢?上面這樣的嵌套選擇符我們在我們的樣式中強(qiáng)制了DOM結(jié)構(gòu)(樣式規(guī)則和DOM結(jié)構(gòu)緊緊耦合在一起)。這就是說”你只能在main-footer中有一個小的whitepaper鏈接“。在CSS規(guī)則中強(qiáng)制結(jié)構(gòu)阻止我們重用樣式,并且將我們數(shù)據(jù)的表現(xiàn)和它在結(jié)構(gòu)中的表現(xiàn)混合在一起(結(jié)構(gòu)和表現(xiàn)緊耦合)。當(dāng)我們通過嵌套的選擇符強(qiáng)制結(jié)構(gòu)時,我們在它們間創(chuàng)造了依賴。在軟件工程的任何區(qū)域管理依賴都是令人頭痛和容易出錯的。我們應(yīng)該避免。

代替強(qiáng)制結(jié)構(gòu),讓我們像下面這樣定義它:

.whitepaper-link {
  font-weight: bold;
  font-size:12px;
}

.whitepaper-link-large {
  font-size:16px;
}

.whitepaper-link-small {
  font-size:9px;
}

我們的標(biāo)記能添加 .whitepaper-link 和 .whitepaper-link-small 類到頁腳元素來實(shí)現(xiàn)和舊版中一樣的效果?,F(xiàn)在我們能復(fù)用 “small”樣式到站點(diǎn)中的任何其他元素,無論它是否在footer元素內(nèi)。我們在這真正見到的是組合的魔力,我們將在一分鐘后討論。

避免突變性

在CSS中重寫樣式規(guī)則并非是罕見的(恰恰相反)。例如,你可能想讓一個錯誤消息有不同的效果如果它在側(cè)邊欄里。

/* errors.css.scss */
.error { color: red; }
.sidebar .error { border:1px solid red; }

這是意大利面條式代碼的東西。這不是與一群工程師使用全局變量類似。一些工程師在他們的代碼中將重定義變量(樣式),然而其他人仍然期望它(變量)保持原來的定義。這 .error 樣式變得不再安全,無法知道它在給定的上下文中的確切行為。樣式規(guī)則變得充滿意外,然而我們討厭意外。

解決方案是從不重寫一個已經(jīng)定義的樣式規(guī)則。如果你把規(guī)則當(dāng)成不可更改的——那意味著,它們是一成不變的,定義之后也永遠(yuǎn)無法改變它們——你可以避免許多由全局變量和不穩(wěn)定變量引起的問題。

我們可以通過組合實(shí)現(xiàn)這些,無論我們通過元素的類屬性或通過Sass的@extend 指令。

組合是你的福音

讓我們看下我們?nèi)绾斡梦覀兩厦婷枋龅膩硗瓿衫印?/p>

/* errors.css.scss */
.error { color: red; }
.sidebar-error { border:1px solid red; }
\<!-- example.html -->
\<div class="error sidebar-error">Oh no!</div>

我們沒有重定義 .error 規(guī)則,而是給我們的 error div增加一個新的規(guī)則來增強(qiáng)它。我們的 error div 的表現(xiàn)將是 .error 和 .sidebar-error的組合。

這仍然讓人有點(diǎn)迷惑,我們沒有重寫 .error 規(guī)則自己,但我們重寫他的一個屬性。如果你正在使用 Sass,更富有表現(xiàn)力的在你的樣式中用SCSS方式定義組合是通過@extend指令。

/*errors.css.scss*/
.error { color: red; }
.sidebar-error { 
  @extend .error;
  border:1px solid red; 
}
example.html
<!-- example.html -->
<div class="sidebar-error">Oh no!</div>

現(xiàn)在我們的標(biāo)記保持苗條,并且沒有給人錯誤的印象,它看起來應(yīng)該像 .error。任何瀏覽錯誤樣式表的開發(fā)者將看到 .slidebar-error是 .error 外加一個邊擴(kuò)展。他們能自信的使用 .error 因?yàn)樗鼜臎]被重定義,并且我們?nèi)詫⒂形覀冏远x的 .sidebar-error 表現(xiàn)。

FCSS

Wealthfront有一些更多的規(guī)則,我們在本文中沒有討論。但他們都融入到整個我們討論過的指導(dǎo)原則中。例如,我們避免元素和過多偽類及偽對象選擇符,因?yàn)樗麄兒虳OM結(jié)構(gòu)緊耦合,并且我們更喜歡類選擇符替代id選擇符來提高可重用性(ID 選擇符被用來非常特殊的,單個元素重寫或樣式)。

在此強(qiáng)調(diào):

  • 通過前綴為你的類增加命名空間,增加偽作用域和減少意外。
  • 不要通過多次定義重寫樣式中的規(guī)則,而是用組合。
  • 不要用嵌套,元素選擇符或過度的偽類及偽對象選擇符——他們將你的CSS和DOM結(jié)構(gòu)僅僅綁定在一起。
  • 每一個團(tuán)隊(duì)需要自己的樣式指南在缺少約束的語言中強(qiáng)制約束。如果運(yùn)氣好,我們的“函數(shù)式”方法將帶給你一些靈感。

注:本文為翻譯文章,原文為 Functional CSS (FCSS)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號