函數(shù)式 CSS

2018-06-16 18:03 更新

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

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

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

引入作用域

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

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

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

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

假如我們?cè)谖覀兊腍TML中引入上面的CSS文件,我們無(wú)意中用其中一個(gè)樣式重寫(xiě)(覆蓋)了另一個(gè)。隨著網(wǎng)站的增長(zhǎng),這種狀況變得越來(lái)越復(fù)雜和普遍。

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

在CSS中模擬更細(xì)粒度的作用域的安全做法是用命名約定。在這種情況下,我們?yōu)槲覀兯械臉邮揭?guī)則設(shè)置命名空間通過(guò)添加一個(gè)前綴。前綴命名空間規(guī)則不是一個(gè)新的理念,但重要的是我們知道我們?yōu)槭裁茨菢幼?。在前綴的樣式中我們創(chuàng)造了我們的“作用域”,你可以說(shuō)我們的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ī)則不再?zèng)_突。我們使他們免受副作用,通過(guò)聲明我們的規(guī)則在命名空間作用域中。

減小依賴,增大可重用性

通過(guò)使用復(fù)雜的選擇符來(lái)保持我們的標(biāo)記整潔和無(wú)類(lèi)是很容易的。我們都見(jiàn)過(guò)像下面這樣的CSS:

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

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

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

但如果我們想在其他地方有小號(hào)的.whitepaper-link呢?上面這樣的嵌套選擇符我們?cè)谖覀兊臉邮街袕?qiáng)制了DOM結(jié)構(gòu)(樣式規(guī)則和DOM結(jié)構(gòu)緊緊耦合在一起)。這就是說(shuō)”你只能在main-footer中有一個(gè)小的whitepaper鏈接“。在CSS規(guī)則中強(qiáng)制結(jié)構(gòu)阻止我們重用樣式,并且將我們數(shù)據(jù)的表現(xiàn)和它在結(jié)構(gòu)中的表現(xiàn)混合在一起(結(jié)構(gòu)和表現(xiàn)緊耦合)。當(dāng)我們通過(guò)嵌套的選擇符強(qiáng)制結(jié)構(gòu)時(shí),我們?cè)谒鼈冮g創(chuàng)造了依賴。在軟件工程的任何區(qū)域管理依賴都是令人頭痛和容易出錯(cuò)的。我們應(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 類(lèi)到頁(yè)腳元素來(lái)實(shí)現(xiàn)和舊版中一樣的效果?,F(xiàn)在我們能復(fù)用 “small”樣式到站點(diǎn)中的任何其他元素,無(wú)論它是否在footer元素內(nèi)。我們?cè)谶@真正見(jiàn)到的是組合的魔力,我們將在一分鐘后討論。

避免突變性

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

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

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

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

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

組合是你的福音

讓我們看下我們?nèi)绾斡梦覀兩厦婷枋龅膩?lái)完成例子。

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

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

這仍然讓人有點(diǎn)迷惑,我們沒(méi)有重寫(xiě) .error 規(guī)則自己,但我們重寫(xiě)他的一個(gè)屬性。如果你正在使用 Sass,更富有表現(xiàn)力的在你的樣式中用SCSS方式定義組合是通過(guò)@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)記保持苗條,并且沒(méi)有給人錯(cuò)誤的印象,它看起來(lái)應(yīng)該像 .error。任何瀏覽錯(cuò)誤樣式表的開(kāi)發(fā)者將看到 .slidebar-error是 .error 外加一個(gè)邊擴(kuò)展。他們能自信的使用 .error 因?yàn)樗鼜臎](méi)被重定義,并且我們?nèi)詫⒂形覀冏远x的 .sidebar-error 表現(xiàn)。

FCSS

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

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

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

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)