探索 SMACSS:CSS 的可擴展和模塊化架構
已發表: 2022-03-11當我們在處理大型項目或與開發人員組一起工作時,我們經常會發現我們的代碼很混亂、難以閱讀、難以擴展。 隨著時間的流逝,尤其如此,當我們回來重新審視它時,我們必須努力保持與我們寫作時相同的心態。
所以很多人所做的是他們創建了 CSS 架構來幫助設計代碼樣式,從而使 CSS 變得更具可讀性。 SMACSS — 即CSS的可擴展和模塊化架構— 旨在做到這一點。 這是我採用的來自 Jonathan Snook 的一組特殊的 CSS 架構指南。
現在,SMACSS 的架構方法與 Bootstrap 或 Foundation 之類的 CSS 框架有點不同。 相反,它是一組規則,更像是一個模板或指南。 因此,讓我們深入研究一些 CSS 設計模式,以了解如何使用它們來使我們的代碼更好、更簡潔、更易於閱讀和更模塊化。
每個 SMACSS 項目結構都使用五個類別:
- 根據
- 佈局
- 模塊
- 狀態
- 主題
根據
在 SMACSS 中,基本樣式定義了元素在頁面任何位置的外觀。 它們是默認值。 如果您使用重置樣式表,這可以確保您生成的樣式在各個瀏覽器中都是相同的,儘管它們內部的硬編碼基本 CSS 默認值之間存在差異。
在基本樣式中,您應該只包含裸元素選擇器,或帶有偽類的選擇器,但不能包含類或 ID 選擇器。 (您應該有充分的理由將類或 ID 放入其中,也許只有在您為第三方插件的元素設置樣式並且您需要覆蓋該特定元素的默認樣式時。)
以下是基本文件單元的外觀示例:
html { margin: 0; font-family: sans-serif; } a { color: #000; } button { color: #ababab; border: 1px solid #f2f2f2; }
因此,它應該包括默認大小、邊距、顏色、邊框以及您計劃在您的網站上使用的任何其他默認值。 您的排版和表單元素應該具有統一的樣式,這些樣式出現在每個頁面上,並給人一種感覺和外觀,它們是同一設計和主題的一部分。
不管是否使用 SMACSS,我強烈建議盡可能避免使用!important
,並且不要使用深度嵌套,但我將在本文後面詳細討論。 此外,如果您的實踐是使用重置 CSS,那麼您應該在此處包含它。 (我更喜歡使用 Sass,所以我只是將它包含在文件的頂部,而不必復制它或將它與每個頁面的<head>
元素分開引用。)
佈局
佈局樣式會將頁面劃分為主要部分——不是導航或手風琴等部分,而是真正的頂級部分:
這些佈局將包含多個 CSS 模塊,如框、卡片、無序列表、畫廊等,但我將在下一節中詳細討論模塊。 讓我們考慮一個示例網頁,看看我們可以分成哪些佈局:
這裡我們有頁眉、主頁和頁腳。 這些佈局在頂部的標題上有鏈接和徽標等模塊,在主頁面上有框和文章,在頁腳有鏈接和版權。 我們通常給佈局一個 ID 選擇器,因為它們不會在頁面上重複並且它們是唯一的。
此外,您應該在佈局樣式的規則前面加上字母l
以將它們與模塊樣式區分開來。 通常在這裡,您會設置特定於佈局的樣式,例如邊框、對齊方式、邊距等。頁面該部分的背景也可能有意義,即使它看起來不像特定於佈局。
以下是它的外觀示例:
#header { background: #fcfcfc; } #header .l-right { float: right; } #header .l-align-center { text-align: center; }
您還可以為對齊添加這些幫助器,您可以通過將適當的類添加到其子級或對齊其文本來輕鬆定位元素。
再舉一個例子,您可以在佈局框上使用一些默認邊距,例如.l-margin
的邊距為20px
。 然後,無論你想為某個容器、元素、卡片或盒子填充什麼,你只需將l-margin
類添加到它。 但是你想要一些可重用的東西:
.l-full-width { width: 100%; }
不是這樣的內部耦合:
.l-width-25 { width: 25px; }
我想花點時間談談 SMACSS 中的命名約定。 如果您從未聽說過 CSS 中命名空間的概念,它基本上是將名稱添加到另一個元素的開頭,以幫助將其與其他元素區分開來。 但是我們為什麼需要這個?
不知道你有沒有遇到過下面的問題。 你正在編寫 CSS 並且你有一個標籤——你可以放入任何你喜歡的樣式,並調用你的類.label
。 但是稍後您會遇到另一個元素,並且您也希望它是.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> <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 組織方法論
我已經介紹了這個 CSS 架構理念的一些關鍵概念。 如果你想了解更多關於這個概念的信息,你可以訪問 SMACSS 的官方網站並深入了解它。
是的,您可能可以使用更高級的方法,例如 OOCSS 和 BEM。 後者幾乎涵蓋了完整的前端工作流程及其技術。 BEM 選擇器可能對某些人很有效,但有些人可能會發現它們太長且難以使用,而且使用起來也太複雜。 如果您需要一些更簡單、更容易掌握並融入您的工作流程的東西,並且還需要為您和您的團隊定義基本規則的東西,那麼 SMACSS 是完美的選擇。
新團隊成員不僅可以很容易地了解以前的開發人員做了什麼,而且可以立即開始工作,而編碼風格沒有任何差異。 SMACSS 只是一個 CSS 體系結構,它按照它在錫上所說的去做——不多也不少。