- 原文地址:Exploring SMACSS: Scalable and Modular Architecture for CSS
- 原文做者:SLOBODAN GAJIC
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:park-ma
- 校對者:老教授 IrisHuang
當咱們在從事大項目或團隊開發工做時,咱們常常會發現咱們寫的代碼,凌亂、難以閱讀而且難以擴展。尤爲是當一段時候後咱們回頭再看本身的代碼,必須回想起當初本身寫的時候的思路才能看懂。css
所以,人們建立了許多 CSS 框架來對 CSS 代碼進行樣式化,使其更具可讀性。好比說,SMACSS,即 Scalable(可擴展) 和 Modular Architecture(模塊化) 的 CSS,就旨在實現這一點。我採用的是 Johnathan Snook 定的那套 CSS 框架指南。html
SMACSS 的架構方法與 Bootstrap 或 Foundation 等 CSS 框架略有不一樣。相反,它是一組規則,更是一套模板或指南。所以,讓咱們來深刻探究下這些 CSS 設計模式,看怎麼用它們來讓咱們的代碼更好、更整潔、更易讀、更具模塊化。前端
每一個 SMACSS 項目結構分爲 5 種規則:android
在 SMACSS 中,基礎樣式定義了元素全局的默認樣式。若是你用了樣式重置代碼,那會讓你的樣式表如今不一樣瀏覽器上保持一致,即使這些瀏覽器內部定義的默認 CSS 有所不一樣。ios
在基礎規則中,你應該只包含基本元素選擇器或者那些僞類選擇器,不該包含類選擇器或者 ID 選擇器。(你應該在理由至關充分時纔將類或 ID 放進去,可能也就只有一種狀況了:你用了第三方插件的節點又想對特色節點的默認樣式進行覆蓋。)git
這是一個基礎規則的文件單元的例子:github
html {
margin: 0;
font-family: sans-serif;
}
a {
color: #000;
}
button {
color: #ababab;
border: 1px solid #f2f2f2;
}
複製代碼
它應該包含計劃在整個網站上使用的默認的大小、邊距、顏色、邊框和其餘默認值。你的排版和表單元素應該在每一個頁面上具備統一的樣式,給人感受它們是統一的設計和主題。web
無論你用不用 SMACSS,我都強烈建議避免使用 !important
,也不要使用深嵌套,關於爲何我會在這篇帖子的後面進行深刻討論。此外,若是你的項目使用了 CSS 重置代碼,那你應該把它放在這一部分(我更喜歡使用 Sass,這樣我就能夠在 SASS 文件頂部方便地將重置代碼引入進來,而不須要將其複製或者在每一個頁面的 <header>
元素單獨引用)。後端
相關資源: Theming with Sass: An SCSS Tutorial設計模式
佈局將會把頁面分紅幾個主要部分 — 不是導航或摺疊面板等部分,而是真正的頂級劃分。
SMACSS 佈局規則包括頂部欄、側邊欄、正文、頁腳等主要部分。
這些佈局包括多個 CSS 模塊例如 boxes、cards、unordered lists 和 galleries 等,但我會將這些模塊放到下一節再詳作討論。讓咱們經過一個網頁例子來看看怎麼對頁面進行佈局劃分:
這些佈局包含一些模塊,好比頂部欄的連接和 logo,正文的盒子結構和文章,頁腳的連接和版權。對於上面的佈局,咱們一般會設置 ID 選擇器,由於他們在頁面上是單獨惟一的。
你還應該使用字母 l
爲佈局規則添加前綴,以區分其餘的模塊樣式。一般你要設置一些和佈局相關的東西,好比邊框,對齊,外邊距等。頁面那些大布局的背景也能夠考慮寫進去,即便它看起來不那麼像是一種佈局樣式。
這是一個佈局規則的例子:
#header {
background: #fcfcfc;
}
#header .l-right {
float: right;
}
#header .l-align-center {
text-align: center;
}
複製代碼
你也能夠將上面這些工具樣式用在對齊上,比方說你想給 header 子節點或節點文本進行對齊定位,那你只需簡單地將合適的類名用在節點上。
另外一個例子,你能夠在佈局框中使用一些默認的外邊距,例如 .l-margin
有 20px
的頁邊距。而後,不管您想要填充某個 container、element、card 或者 box ,只需將 l-margin
類添加到其中便可。不過你要用一些可複用的寫法:
.l-full-width {
width: 100%;
}
複製代碼
不是像這樣內部耦合的東西:
.l-width-25 {
width: 25px;
}
複製代碼
我想花點時間談談 SMACSS 中的命名規則。若是您從未在 CSS 中據說過命名空間的概念,那它基本上就是將名稱添加到另外一個元素的開頭,以幫助區分它與其餘任何元素。可咱們爲何要這麼作呢?
我不知道你是否遇到過下面的問題。你寫 CSS 代碼時發現頁面上有一個標籤,因而你給它加了一些樣式,並命名爲 .lable
類。以後你又遇到一個元素,也想將其命名爲 .label
類,但樣式與前面的不一樣。因而兩個不一樣的東西擁有相同的名稱,這就是一次命名衝突。
命名空間可幫助你解決此問題。最終,它們在同一級別上被稱爲相同的東西,但因爲應用了不一樣的前綴,因而屬於不一樣的命名空間,也就能夠表示兩種不一樣的樣式
.box--label {
color: blue;
}
.card--label {
color: red;
}
複製代碼
正如我前面提到的,SMACSS 是頁面上可重用的小代碼塊,是單一佈局的一部分。這部分 CSS 咱們想要存儲到單獨的文件夾中,由於咱們在一個網頁會有不少這樣的模塊代碼。而且隨着項目的增加,咱們能夠經過文件夾結構來拆分,好比說,模塊/頁面的結構
因而在前面例子中,假如咱們(在頁面上)有一篇文章,它能夠做爲一個獨立的模塊。如何在這裏構建 CSS 呢?咱們應該有一個 .article
的類,它有 title
和 text
的子元素。所以,爲了讓它們保存在同一模塊,咱們須要在子元素上使用前綴:
.article {
background: #f32;
}
.article--title {
font-size: 16px;
}
.article--text {
font-size: 12px;
}
複製代碼
你必定注意到咱們在模塊前綴後面使用兩個連字符。這是由於有時模塊名稱有兩個單詞或者它們的前綴相似 big-article
。咱們須要兩個連字符來描述子元素的位置。好比你能夠試着比較 big-article-title
、big-article--title
和 big-article--text
。
此外,若是特定模塊佔用了大部分頁面,您能夠將模塊嵌套在模塊中:
<div class="box">
<div class="box--label">This is box label</div>
<ul class="box--list list">
<li class="list--li">Box list element</li>
</ul>
</div>
複製代碼
在這個簡單的例子中,你能夠看到 box
是一個模塊 list
是在它裏面的另外一個模塊。使用 list--li
是 list
模塊的子項而不是 box
的。這裏的關鍵概念是每一個 CSS 規則最多有兩個選擇器,但在大多數狀況下只有一個選擇器是帶前綴的。
這樣,咱們能夠避免重複規則,而且在具備相同名稱的子元素上具備額外的選擇器,從而提升速度。它也有助於咱們避免使用不須要的 !important
規則,這些規則是結構不合理的 CSS 項目的標誌。
好的例子(注意單選擇器):
.red--box {
background: #fafcfe;
}
.red-box--list {
color: #000;
}
複製代碼
很差的例子(注意選擇器內的重複和重疊):
.red .box {
background: #fafcfe;
}
.red .box .list {
color: #000;
}
.box ul {
color: #fafafa;
}
複製代碼
在 SMACSS 中狀態規則是描述咱們的模塊在不一樣狀態下顯示外觀的一種方式。因此說這一部分是關於交互性的:咱們須要有不一樣的行爲去描述元素的隱藏、擴展或修改。例如,jQuery 摺疊面板控件就須要定義狀態,來表示節點內容什麼時候可見什麼時候不可見。它有助於咱們在特定時刻定義元素的樣式。
若是狀態規則與佈局規則應用於同一元素上,此時咱們要添加額外的規則來覆蓋前面的規則(若是有的話)。狀態規則優先,由於它是規則鏈中的最後一個規則。
與佈局規則同樣,咱們建議在狀態規則使用前綴。這有助於咱們識別它們並給予它們優先權。這裏咱們使用 is
前綴,如 is-hidden
或 is-selected
。
<header id="header">
<ul class="nav">
<li class="nav--item is-selected">Contact</li>
<li class="nav--item">About</li>
</ul>
</header>
複製代碼
.nav--item.is-selected {
color: #fff;
}
複製代碼
在這裏,!important
是可使用的,由於狀態規則常常被用於 JavaScript 的修改而不是渲染時。例如,你須要一個元素在網頁加載時是隱藏的,而在點擊按鈕時顯示,可是默認類是像下面這樣寫的:
.box .element {
display: none;
}
複製代碼
所以若是你只是添加了下面代碼:
.is-shown {
display: block;
}
複製代碼
即便你經過 JavaScript 添加了 .is-shown
以後它仍是隱藏的,這是由於第一條規則是是二級深度的,將後一條規則覆蓋。
所以你能夠改成這樣定義狀態類:
.is-shown {
display: block !important;
}
複製代碼
這就是咱們如何區分狀態規則和佈局規則,佈局規則僅用於頁面的初始加載。這樣不只能夠達到目的,還能夠保持最少選擇器的優點。
這個應該是最顯而易見的規則,由於它定義了顏色、形狀、邊框、陰影還有其餘等等。這些大多數都是在網站上重複使用的元素。咱們沒必要在每次使用它們的時候都從新定義它們一下,相反,咱們但願定義一個獨特的類而後使用時只需添加上便可。
.button-large {
width: 60px;
height: 60px;
}
複製代碼
<button class="button-large">Like</button>
複製代碼
不要將 SMACSS 主題規則和基礎規則混淆,基礎規則定義了默認外觀,相似於重置瀏覽器的默認設置,而主題規則定義了一組最終外觀的樣式,惟一的顏色方案。
當網站具備多套樣式或者須要在不一樣狀態下使用不一樣主題時,主題規則很是有用,由於當用戶經過頁面上的某些事件例如,主題切換按鈕,觸發時,主題規則能夠很方便地更改和切換。至少,他們將全部主題風格保存在一個地方,以便你能夠輕鬆地更改它們並使它們保持良好的組織結構。
我已經介紹了這個 CSS 架構思想的關鍵概念。若是你想了解更多,請訪問 SMACSS 的官方網站並進行深刻的學習。
你也可使用更高級的方法例如 OOCSS 和 BEM。後者幾乎包含了全部前端工做流程和技術。可是一些人會以爲 BEM 的選擇器太長過重,使用起來太複雜。若是你須要更簡單易懂,並容易將其歸入你的工做流程 — 以及爲你和你的團隊定義基本規則的東西 — SMACSS 很是適合。
這不只讓團隊新成員很容易的理解之前開發者的工做,還幫助他們快速上手項目,並無任何代碼風格上的差別。 SMACSS 只是一個 CSS 框架,它完成了它所描述的工做,很少也很多。
有三種不一樣的類型。內聯 CSS 直接放在 HTML 元素的樣式屬性上。內部 CSS 位於 HTML header
內部 style
標籤內。外部 CSS 是獨立的文件並經過 HTML 來索引到,避免網站在不一樣網頁內編寫重複的代碼。
CSS 模板一般是用來定義特定的佈局以便咱們在不一樣網頁甚至不一樣網站上使用它們。可是除了佈局,它們有時也用來爲特定元素例如模態框和按鈕甚至它們的組合而定義的一組規則。其餘一些則用來定義 HTML 元素的默認樣式。
CSS 在現代網頁中絕對是必須的。沒有它,網頁只是空白頁面上的一堆純文本和圖片。它不只給網頁提供樣式,還組織布局和提供動畫效果 — 所以它對互交性也很重要。
一個主要的優勢是將全部的樣式放在一塊兒而不是讓它們分散在整個網站的每個元素上。它爲咱們提供了更多的格式選項,有助於優化頁面加載時間和增長代碼的複用性。
通常來講,隨着項目增加,可擴展性帶來的可伸縮性和可維護性很是重要。特別是在CSS中,若是咱們編寫的代碼不具有可擴展性和模塊化,它會迅速失去控制,變得難以理解和工做,特別是對於新手而言。 所以咱們須要 SMACSS。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。