Sass 願景

在最近的一個 CSS 見面會上,我向與會者提問,「有人會在平常的工做流中使用 Sass 嗎?」回答結果壓倒性的表示確定——保守謹慎地使用 Sass 已經成爲過去式。Sass 正迅速成長爲編寫 CSS 的標準方式。css

這真是可貴的好消息!Sass 包含了諸多 CSS 規範未定義的特性,好比變量、控制指令、混合宏等。這些特性賦予了開發者強有力的工具,以應對複雜和持續更迭的樣式表。Sass 的靈活性和健壯性,足以實現開發者任何天馬行空的創意思惟。html

使人遺憾的是,雖然 Sass 的使用規模在持續擴大,但生成的 CSS 質量卻在不斷下降。合理的解釋是:Sass 在開發者和樣式表之間引入了一層抽象層。過去,咱們曾經反覆修正 web 標準,如今,咱們須要一種方式將其融合入新的開發環境中。目前的問題是,Sass 規範擴展了太多東西,以致於須要持續修正以應對任何 web 標準的改變。實際上,咱們須要一種指導思想——適用且獨立於 Sass,指導開發者的編程方式。前端

爲了更深刻的探討問題,咱們有必要再回顧一次當下面臨的困境。web

癥結

對於 Sass 的諸多特性,最多見的濫用方式就是——選擇器的過分嵌套。這裏請不要誤解個人意思:嵌套選擇器確實是很是有用的編程方式,它組織起了局部的代碼,使之更易於管理;可是,過分嵌套就是一種災難了。sql

舉例來講,有時候嵌套會生成冗長的選擇器列表,而這會嚴重影響渲染性能:編程

body #main .content .left-col .box .heading { font-size: 2em; }

使用如此詳細的選擇器弊大於利。當將來須要重寫級聯樣式時,開發者就必須使用權值更高的選擇器列表。甚至,最終須要藉助 !important 的權值 —— 這種寫法,上帝都看不下去,嚴重影響後續的可維護性。瀏覽器

body #main .content .left-col .box .heading [0,1,4,1] .box .heading [0,0,2,0]

最後,因爲選擇器依賴於 HTML 文檔結構,那麼如此冗長的嵌套就會下降樣式的可維護性和可移植性。將來,若是咱們想要給一個父級不是 leftcol 的 box,一樣設置 heading 樣式,咱們就須要再寫一條樣式來實現(合理的開發方案應該是複用這條樣式的)。sass

生成的 CSS 代碼質量低下,最大的緣由就應該歸罪於過分嵌套。其餘存在的問題,還包括代碼的重複和耦合——有必要再次指出,這些都是使用 Sass 的不合理方式所引發的。那麼,咱們應該如何更縝密的使用 Sass 呢?ruby

對策

一種方式是建立一些規則,限制和掌控那些存在風險的特性。好比,Mario Ricalde 使用 Inception-inspired 準則限制嵌套:「嵌套永遠不要超過四層」。bash

這些規則每每很是適用於新手,爲他們制定了明確的使用權限。可是,一方面這種公認的規則少之又少,另外一方面 Sass 規範又在持續擴展。對於每一次新版本發佈,都會帶來諸多新的特性,而且使用起來會束縛開發者的創造力。單獨的幾條規則是沒法掀起革命性影響的。

咱們應該高度重視開發過程當中的最佳實踐,而不是去整理收集零散的規則。這種最佳實踐的核心內容以下所示:

  • 編程準則,或者是特定編程語言的編程規範,包含建議的編程風格、最佳實踐和方法。
  • 框架,或者是標準化編程的文件/文件夾結構,能夠用做網站開發的基礎。
  • 樣式指南,或是在線文檔,詳述了開發網站和應用的全部元素和代碼模塊。

每一個方面各有所長:

  • 在一個大型代碼庫中,編程準則有利於統一團隊的編程風格,改善總體代碼的可維護性。更多信息請參考 Chris Coyier 的 Sass guidelines
  • 框架兼具實用性和靈活性,同時也將開發過程當中的決策壓力降到了最低。正如全部的前端開發者所熟知的那樣,即便是決定 CSS 的命名方式都會讓人感到壓力重重。
  • 樣式指南將編程語言的語法規則和實際生成的效果聯繫在了一塊兒,指南中使用詳細的示例解釋了系統中每個組件的特色。

每一個方面也各有難點:

  • 編程準則每每是冗雜繁重的,必須持續更新保持準確性。對於新手和缺少經驗的開發者,都存在不小的學習難度。
  • 框架每每會讓總體代碼變得有些臃腫,其靈活性是須要付出必定代價的。
  • 樣式指南在不一樣的開發主題中是迥然不一樣的,每每爲了適應特定的上下文環境須要付出必定的修正時間和精力。

不幸的是,雖然這些方法指出了一些使用 Sass 的技巧,但沒有解決咱們的實際問題。咱們使用 Sass 的難點並非源於語法規範自己,而是咱們使用 Sass 的方式。歸根結底,Sass 只是一個 CSS 預處理器;因此咱們的問題其實是,處理過程。

那麼,咱們又該如何處理?

再看癥結

每一份工做都或多或少受到人爲因素的影響,當咱們將工做投入實際生產以後,問題就會被放大出來。咱們須要認清,Sass 幫助了咱們構建 CSS,但這並非咱們奮鬥的終點。實際上,若是 CSS 中引入了變量,那麼大多數的事情都要改寫,而 Sass 和 CSS 規範也將逐漸融合爲一體——這也意味着 Sass 的消亡。

咱們實際上所須要的解決方案,並不該該針對代碼自己,而應該針對做爲開發者的咱們。該解決方案須要包含技術準則,以輔助開發者使用 Sass,同時還要深思熟慮放眼將來。因此,咱們須要一份了包含了相關意圖和目標的公開聲明,換言之,一份宣言。

Sass 宣言

當我學會 Sass 以後,我就創建了一些我的準則。時間匆匆,它們造成了宣言的雛形,經常被我用來評估新的特性和技巧——以判斷它們是否適用於個人工做流程。當 Sass 羽翼豐滿頻頻被用於個人團隊時,這些信條就變得舉足輕重了。

個人 Sass 宣言包含了六個信條,或者說是條款,詳列以下:

  1. 輸出賽過輸入
  2. 可用賽過依賴
  3. 易懂賽過簡潔
  4. 穩固賽過反覆
  5. 功能賽過表現
  6. 一致賽過新奇

雖然每一個信條均可能逐步發展爲規範建議的條款,但固定不變的運用它們顯然是沒有意義的。接下來,讓咱們進一步解析每一個信條背後的深層次思考。

1. 輸出賽過輸入

最終生成的 CSS 的質量和完整性,顯然要比預編前的代碼更重要。

該信條是其餘信條的根本。有必要認清,Sass 只是整個流程的一個處理過程,它轉換爲 CSS 文件,還要通過瀏覽器的解析。這可不是說 CSS 須要優雅的格式和極高的可讀性(這每每不是關注的重點,尤爲是在開發者遵循最佳實踐使用壓縮的 CSS),但你必須時刻警戒最終的渲染性能。

當你使用了 Sass 規範最新的特性,有必要捫心自問,「這種方式輸出的 CSS 是怎樣的?」 若是疑惑不清,那麼就要看一看源碼——能夠查看生成的 CSS 代碼。深度理解 Sass 和 CSS 相互之間的關係,將有助於你發現潛在的性能瓶頸,並拿出相應的對策優化 Sass 結構。

舉例來講,使用 @extend 指令繼承選擇器中的每一個樣式。Sass 代碼以下:

.box {
  background: #eee; border: 1px solid #ccc; .heading { font-size: 2em; } } .box2 { @extend .box; padding: 10px; }

編譯結果:

.box, .box2 { background: #eee; border: 1px solid #ccc; } .box .heading, .box2 .heading { font-size: 2em; } .box2 { padding: 10px; }

如你所見,.box2 不只僅繼承了 .box 的樣式,還像 .box 同樣成爲了 .heading 的父級選擇器。雖然這只是一個小例子,但若是你不理解 Sass 的生成方式,那麼就會生成意想不到的結果。

2. 可用賽過依賴

項目應該具備可移植性,遠離對外部的過分依賴。

只要你使用 Sass,那麼你就須要引入相關的依賴。最簡單的例子就是 Sass 的安裝和編譯依賴於 Ruby 和 Sass gem。須要牢記的是,使用的依賴越多,作出的妥協越多,就會逐漸喪失了使用 Sass 的帶來的收益:團隊協做不因噎廢食。

舉例來講,使用 Sass gem 能夠安裝不少額外的軟件包——它們每每能夠完成大量的工做。最經常使用的框架就要屬 Compass 了,此外你還能夠安裝編寫柵格的 gems,以及 Bootstrap 之類的框架。這些 gems 對完成大量的細碎工做很是有用,好比建立一個調色板,或是添加陰影等。

這些 gems 內建了一系列的混合宏,能夠被開發者引用到本身的 Sass 文件中。不一樣於開發者在項目內編寫的混合宏,gem 中的混合宏存放在安裝目錄。gems 在外部被引用的方式,很是相似 Sass 核心功能的使用方式,並且只能經過 @include 指令調用。

這就是 gem 棘手的地方。如今咱們假設一種場景,有一支團隊正致力於某個項目:團隊成員之一,John,決定安裝一個 gem 來輔助管理柵格。他安裝後就將 gem 引入了項目,並在開發者中使用它。與此同時,另外一個團隊成員,Mary,下載了項目的最新版本,想要更改一下網站的字體。她下載以後嘗試進行編譯,卻忽然編譯中斷拋出了錯誤。因爲 John 在項目中引入了額外的依賴,而 Mary 的文件中缺乏相關的依賴,致使她必須調試錯誤並下載相關的依賴。

在大型團隊中,這種問題家常便飯。若是再算上錯綜複雜的版本和 gem 的內部依賴,處理起來使人崩潰。對於 Ruby 項目,維護統一的開發環境,其最佳實踐就是追蹤和安裝確實須要的 gems 和版本。但最簡單的方法,仍是儘可能避免使用額外的 gems。

免責聲明:我最近正在實用 Compass 框架,並且也感受利大於弊。不過,因爲 Sass 規範的建議,我已經開始考慮適時和 Compass 說拜拜了。

3. 易懂賽過簡潔

編寫 Sass,代碼結構要清晰易懂,方便後續開發者的維護工做。

Sass 能夠輸出嚴格壓縮的 CSS,因此無需手動優化編譯前的代碼。不一樣於 CSS 的註釋,Sass 中的行內註釋並不會出如今最終的 CSS 中。

這對於書寫混合宏的文檔很是有用,以下所示的註釋不會被輸出到最終的 CSS 中:

// Force overly long spans of text to truncate, e.g.: // @include truncate(100%); // Where $truncation-boundary is a united measurement. @mixin truncate($truncation-boundary){ max-width:$truncation-boundary; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

不管怎樣,必定要考慮 Sass 中的哪些部分須要導入到最終的 CSS 文件中。

4. 穩固賽過反覆

不要重複。認清併合理編寫複用模式。

在開始任意項目前,明確且嘗試定義既定設計中全部不一樣的模塊,是很是明智的作法。這也是編寫面向對象的 CSS 的第一步。固然,有一些模式可能沒法預測,直到編寫了三四遍重複的代碼以後纔會意識到。

儘快抽象出這些模式,並運用到你的 Sass 中去。

將複用的值設爲變量:

$base-font-size: 16px; $gutter: 1.5em;

將複用的視覺樣式設爲佔位符:

%dotted-border { border: 1px dotted #eee; }

爲須要傳參的模式編寫混合宏:

//transparency for image features @mixin transparent($color, $alpha) { $rgba: rgba($color, $alpha); $ie-hex-str: ie-hex-str($rgba); background-color: transparent; background-color: $rgba; filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie-hex-str},endColorstr=#{$ie-hex-str}); zoom: 1; }

若是擬採用了這一方法,就會發現,Sass 文件和生成的 CSS 文件,都會更小且易於管理。

5. 功能賽過表現

命名約定,要專一於 HTML 的功能,而不是視覺表現。

使用 Sass 的變量,能夠很是簡單的主題化網站。然而,我經常會看到這樣的代碼:

$red-color: #cc3939; //red $green-color: #2f6b49; //green

將變量與表現效果聯繫在一塊兒,只有一時的成效。若是設計效果改變了,紅色被替換爲了其餘顏色,就會混淆變量和值的關係。

$red-color: #b32293; //magenta $green-color: #2f6b49; //green

更好的方式是基於特定的功能來命名這些顏色變量:

$primary-color: #b32293; //magenta $secondary-color: #2f6b49; //green

Presentational classes with placeholder selectors

當咱們不能將視覺樣式和功能性類名聯繫起來的時候,又該如何作呢?假設一個站點中有兩個 box,分別是 「Contact」 和 「References」。設計師將兩個 box 都設置爲了藍色的邊框和背景。咱們想最大程度的保持靈活性,但又要儘可能縮減冗餘的代碼。

咱們能夠在 HTML 中串聯這些類名,但須要嚴格限制:

<div class=「contact-box blue-box」> <div class=「references-box blue-box」>

牢記,咱們要專一於功能而不是表現效果。幸運的是,使用 Sass 的 @extend 指令和佔位符,將會使這種方式變得很是簡單。

%blue-box { background: #bac3d6; border: 1px solid #3f2adf; } .contact-box { @extend %blue-box; … } .references-box { @extend %blue-box; … }

生成結果以下所示,其中並無 %blue-box 的代碼,只有確實須要的代碼被實現了。

.contact-box, .references-box { background: #bac3d6; border: 1px solid #3f2adf; }

這種方式切斷了與 HTML 中描述性類名的聯繫,但在 Sass 文件中仍然能夠被理解。爲通用樣式設計功能性類名,好比 base-box,將會更有意義。

6. 一致賽過新奇

避免向編譯後的 CSS 引入沒必要要的改動。

若是你但願將 Sass 引入本身的工做流中,且沒有新項目的話,你可能會疑問,如何在已有代碼庫中使用 Sass。Sass 徹底支持 CSS,因此最基本的轉變就像是將擴展名從 .css變爲 .scss 同樣簡單。

一旦完成了這種轉換,你也許會嘗試深刻理解代碼,或者重構整個文件,化整爲零,將選擇器嵌套,引入變量和混合宏。對於接替後續開發的人來講,前面的轉變必定會帶來諸多問題。雖然重構不會影響網站的顯式效果,但會生成徹底不一樣的 CSS 文件,並且任何改動的影響都不是孤立的。

轉換爲 Sass 工做流的最佳方法是按需更新文件。若是你須要改變導航的樣式,能夠在使用前將其分離爲部件。這有助於保護現有的級聯樣式,而且後續的改動也會很是容易。

展望

最近,我喜歡思考使用 Sass 的難點。這些都是咱們使用新的工做方式,所要面臨和亟待解決的癥結。隨着對 Sass 理解的深刻,咱們最終將會找到合理的答案。

這就是個人願景,相信這份宣言將有助於調整咱們的姿態,繼續向前:使用它,改變它,甚至書寫本身的宣言。要以專一於書寫代碼的方式爲始,而不是書寫的內容。

致謝

 

http://www.jianshu.com/p/aa1be52204a7

 

本文翻譯自 ALISTAPART 的 A Vision for Our Sass,很是感謝 Felicity Evans 的傑出工做。

相關文章
相關標籤/搜索