多網站項目的 CSS 架構
- 2019 年 10 月 8 日
- 筆記
複雜的 CSS 架構,可不是你在科班裡能學到的東西。
我在互聯網行業的第四份工作,是在中國一家領先的媒體新聞公司中任職一名 CSS/HTML 專家,我的主要職責就是開發可重用的、可擴展的、用於多網站的 CSS 架構。

在本文中,我將與大家分享我在構建多網站架構領域中積累的知識和經驗。
附註:如今,正規的項目都會用到 CSS 預處理器。而在本文中,我會使用 Sass 預處理器。
本文是我寫的討論 CSS 架構的系列文章中的第三篇。建議大家最好先讀讀此系列的第二篇 —— 《CSS 架構:文件夾和文件結構》,有助於加深對本文的理解。
用層構建世界
在開始開發一個大型項目之前,我們應該放眼全局,把多個網站的共同之處提煉出來。高樓大廈始於一磚一瓦,而項目的基石就是樣式規格化、混入(Mixins)、通用圖標以及局部模組層(元素、組件、圖形邏輯、實體、頁面……不一而足)等。
為了使多重項目(即多個網站)正常運轉,我們必須決定哪些樣式是通用樣式、哪些是專有樣式 —— 通用樣式寫進基礎層,而專有樣式寫在與其對應的層中。這是一條充滿摸索和碰壁的實踐之路。每當思考的角度發生變化,我們都需要逐層地挪動樣式程式碼,直到我們覺得順眼為止,這都是家常便飯了。
理解了這項原則後,我們就可以開始著手構建作為基礎的全局層了。這個全局層是整個多重項目(多個網站)的起始點。
下面的示例圖向我們演示了彼時我司的項目需求。

基礎層要保持輕量,其中只包含 CSS 初始化、基本的 SASS mixins、通用圖標、通用字體(如需)以及功能類,如果某些網格布局適用於所有網站,就將其作為通用網格添加到基礎層中。在 _partials.scss
層(元素、組件等)中,我們主要用到的是 _elements.scss
層,該層中包含諸如通用彈窗、通用表單和通用標題等此類局部模組。我們應該在基礎樣式中添加的是所有(或者大多數)底層樣式共有的部分。(更多關於文件夾和文件結構的細節,參見我的上一篇文章)
如何組織多個層
在我們的架構中,每個層都至少包含三個文件:兩個私有文件(局部樣式文件和配置文件,稱之為私有是因為它們不會被編譯成一個 CSS 文件)和一個公共文件(本層的主文件)。每層的配置文件 _config.scss
通常包含變數。 _local.scss
文件則包含內容樣式,為當前層充當控制器或者包管理器的角色。而第三個文件(layer-name.scss)會調用前二者。
layer-name.scss 文件:
@import "config"; @import "local";
另外一個我們要給自己定下的原則就是,儘可能把每個文件都拆分成儘可能小的部分(小文件)。這個原則會讓重構非常方便。
在每一層中,都要保證只編譯 layer-name.scss 文件,即使某些層代表的是一個「虛擬項目」(如上面示例圖中的「基礎層框架」)。
對於不會被編譯成單獨文件的私有文件,我們用一個下劃線( _
)作為其文件名的前綴。這裡的下劃線代表著此文件不能單獨存在。
注意:當導入私有文件時,我們書寫其文件名時可以不必帶上前綴下劃線。
層架構示例:

文件夾結構長這樣:
sass/ | |- base-layer/ |- config/ |- local/ |- _config.scss |- _local.scss |- base-layer.css (編譯後的層樣式) |- base-layer.scss
繼承
假設我們想要從基礎層開始創建一個項目。我們需要根據 base-layer 文件夾的內部結構,用新項目的名稱照貓畫虎地克隆一套出來。在後續例子中,我們把這個新項目稱為 inherited-project。
提示:把所有的層目錄和項目目錄都放在 Sass 的根目錄中。
該項目至少包含一個 _config.scss
文件、一個 _local.scss
文件和此層的核心 Sass 文件 —— 在本例中即為 inherited-project.scss
。
所有的層和項目都位於 Sass 的根目錄中。
sass/ | |- base-layer | |- config/ | |- local/ | |- _config.scss | |- _local.scss | |- base-layer.css (編譯後的層樣式) | |- base-layer.scss | |- inherited-project |- config/ |- local/ |- _config.scss |- _local.scss |- inherited-project.css (編譯後的層樣式) |- inherited-project.scss
項目 inherited-project 的配置文件引入了 base-layer 中的配置文件。這樣一來,我們就能增加新變數或者覆寫上層(base-layer)中的已有變數了。
以下為 inherited-project/_config.scss 的一個例子:
/*載入 base-layer 配置資訊 */ @import "../base-layer/config.scss"; /** 局部的 Config 層 (按需添加或覆寫變數)**/ @import "config/directions.scss";
內容樣式文件 inherited-project/_local.scss 亦同理:
/* 導入 base-layer 局部組件 */ @import "../base-layer/local.scss"; /* 局部字體 */ @import "local/font-almoni.scss"; /* 局部組件 */ @import "local/elements.scss"; @import "local/components.scss";
如果要創建的新層既有通用樣式又有獨特樣式,那麼從 base-layer
文件夾繼承基礎層樣式再合適不過了。
這一層會創建一個名為 inherited-project.css
的 CSS 文件。
在內部層中覆寫變數
使用「層」的方式覆寫變數非常簡單。
比方說在基礎層中有一個名為 $base-color
的變數,其值為 blue( $base-color:blue;
)。要想覆寫此變數,就需要在局部文件 _config.scss
中更新它的值。現在,所有使用該變數的組件 —— 不論是繼承於基礎層還是定義於局部層 —— 都會更新對應變數的的顏色值。
Global Story 全局
某些模組並非在所有層中都會用到,因此如果你在基礎層中定義它們,其他項目就會導入冗餘程式碼。為了解決這個問題,我走了另一條路線,採用了全局模組的概念。
這個概念是說,把僅用於某些層的模組放置於一個新的根目錄( _partials
)中,這個新的根目錄位於所有層之外。然後,任何層都可以從全局目錄 _partials
中導入所需模組。
下圖展示了將模組分離的例子:

每一層都可以按需從全局目錄 _partials
中調用一個或多個模組。
全局目錄 * _partials
示例:*
sass/ | |- _partials/ |- base-layer/ |- inherited-project/
從 * _partials
導入模組的 local.scss 文件:*
/* 導入 base-layer 中的局部組件 */ @import "../base-layer/local.scss"; /* 局部組件 */ @import "local/partials.scss"; /* 添加全局模組 */ @import "../_partials/last-connection";
些許額外忠告
- 組織結構要有條理。要一直記得以滿足需求的方式規劃項目、保持最佳結構。
- 別重蹈覆轍。僅用
@import
即可輕鬆導入另一層的組件。比如說,某些組件定義在一個「體育」項目中,而這些組件與另一個項目中的「新聞」網站有關聯。那我們就可以直接把這些組件@import
進「新聞」網站中。(網站 = 層 = 項目) - 充分利用 IDE 快捷方式。選用一款便於重構的編輯器,免於導致報錯或故障。
- 立新不可破舊。在開發和後續重構中,每次都要把所有 Sass 根文件一同編譯,以免新舊脫節。
總結
在本文中,我向大家展示了針對多網站項目的 CSS 體系結構的構建方法,這套思想提煉於我經年積累的知識和經驗。
本文是系列文章 CSS 架構文章新篇的第三篇,我會每隔幾周跟大家分享後續篇章。
如果覺得本文有趣,歡迎在 twitter 上或者 medium 上關注我。
我的 CSS 架構系列文章:
- 規格化 CSS 還是 CSS 重置?!
- CSS 架構 —— 文件夾和文件架構
- 多網站項目的 CSS 架構
結束語
好了,這次就分享到這裡。衷心希望大家喜歡本文,並能從我的經驗中獲益一二。如果你喜歡本文,請點贊並和大家分享你的心得,我將不勝感激。:-)
- 原文地址:https://medium.com/@elad/css-architecture-for-multiple-websites-ad696c9d334
- 原文作者:Elad Shechter
- 譯文出自:掘金翻譯計劃
- 譯者:Baddyo
- 校對者:xionglong58,lgh757079506