首頁 > web前端 > css教學 > CSS體系結構:Block-Element-Modifier(BEM)和Atomic CSS

CSS體系結構:Block-Element-Modifier(BEM)和Atomic CSS

尊渡假赌尊渡假赌尊渡假赌
發布: 2025-02-10 10:55:15
原創
389 人瀏覽過

CSS Architecture: Block-Element-Modifier (BEM) & Atomic CSS

本文節選自Tiffany新書《CSS大師,第二版》。我們將探討兩種CSS命名方法論。這兩種方法都是為了改進大型網站和大型團隊的開發流程而創建的;然而,它們同樣適用於單人團隊。您可以選擇其中一種、兩種都不選,或者混合使用,這取決於您自己。介紹它們的目的是幫助您思考編寫自己的CSS的方法。

關鍵要點

  • BEM(塊-元素-修飾符)是一種CSS方法論,它鼓勵開發人員將網站視為可重用組件塊的集合。它提供了一個清晰的命名系統,使理解網站不同部分之間的關係更容易,對於大型開發團隊尤其有利。
  • 相反,原子CSS專注於創建高度細粒度、可重用的樣式,而不是為每個組件創建規則集。它減少了特異性衝突,並允許快速HTML組件開發。但是,它更適合小型團隊或單個開發人員。
  • BEM和原子CSS可以一起使用,將BEM的結構與原子CSS的可重用性結合起來。這可以產生一個高度組織化和易於維護的CSS代碼庫。
  • 儘管它們有好處,但在開發人員無法完全控制標記(例如使用CMS)的情況下,BEM和原子CSS可能都沒有用。在這種情況下,開發人員可能需要使用冗長且特定的選擇器來實現其目標。

塊-元素-修飾符(BEM)

BEM,或塊-元素-修飾符,是一種方法論、命名系統和一套相關的工具。 BEM誕生於Yandex,旨在由大型開發團隊進行快速開發。在本節中,我們將重點關注概念和命名系統。 BEM方法論鼓勵設計師和開發人員將網站視為可重用組件的集合,這些塊可以混合和匹配以創建界面。塊只是文檔的一部分,例如標題、頁腳或側邊欄,如下圖所示。也許令人困惑的是,“塊”在這裡指的是構成頁面或應用程序的HTML片段。

CSS Architecture: Block-Element-Modifier (BEM) & Atomic CSS

塊可以包含其他塊。例如,標題塊可能還包含徽標、導航和搜索表單塊,如下所示。頁腳塊可能包含站點地圖塊。

CSS Architecture: Block-Element-Modifier (BEM) & Atomic CSS

比塊更細粒度的是元素。正如BEM文檔所解釋的:

元素是執行特定功能的塊的一部分。元素依賴於上下文:它們只有在其所屬的塊的上下文中才有意義。

例如,搜索表單塊包含文本輸入元素和提交按鈕元素,如下圖所示。 (為了明確起見,我們使用的是設計元素意義上的“元素”,而不是HTML元素意義上的“元素”。)

CSS Architecture: Block-Element-Modifier (BEM) & Atomic CSS

另一方面,主要內容塊可能具有文章列表塊。此文章列表塊可能包含一系列文章推廣塊。每個文章推廣塊可能包含圖像、摘錄和“閱讀更多”元素,如下所示。

CSS Architecture: Block-Element-Modifier (BEM) & Atomic CSS

塊和元素共同構成了BEM命名約定的基礎。根據BEM規則:

  • 塊名稱在一個項目中必須唯一
  • 元素名稱在一個塊中必須唯一
  • 塊的變體——例如,具有深色背景的搜索框——應該在類名中添加修飾符

塊名稱和元素名稱通常用雙下劃線(.block__element)分隔。塊和元素名稱通常用雙連字符與修飾符名稱分隔(例如,.block--modifier或.block__element--modifier)。以下是使用搜索表單示例的BEM外觀:

<div class="search">
  <label for="s" class="search__label">Search for: </label>
  <input type="text" id="s" class="search__input">
  <button class="search__submit">Search</button>
</div>
登入後複製
登入後複製

具有深色背景的此表單的變體可能使用以下標記:

<div class="search search--inverse">
  <label for="s" class="search__label search__label--inverse">Search for: </label>
  <input type="text" id="s" class="search__input">
  <button class="search__submit search__submit--inverse">Search</button>
</div>
登入後複製
登入後複製

我們的CSS可能如下所示:

.search {
    color: #333;
}
.search--inverse {
    color: #fff;
    background: #333;
}
.search__submit {
    background: #333;
    border: 0;
    color: #fff;
    height: 2rem;
    display: inline-block;
}
.search__submit--inverse {
    color: #333;
    background: #ccc;
}
登入後複製
登入後複製

在我們的標記和CSS中,search--inverse和search__label--inverse是附加的類名。它們不是search和search__label的替代品。類名是BEM系統中使用的唯一選擇器類型。可以使用子選擇器和後代選擇器,但後代也應該是類名。元素和ID選擇器是被禁止的。強制執行塊和元素名稱的唯一性還可以防止命名衝突,這在團隊中可能會成為問題。這種方法有幾個優點:

  • 新團隊成員很容易閱讀標記和CSS,並理解其行為
  • 添加更多開發人員可以提高團隊生產力
  • 一致的命名減少了類名衝突和副作用的可能性
  • CSS獨立於標記
  • CSS高度可重用

BEM的內容遠不止本章節中的一節所能容納的。 BEM網站更詳細地描述了這種方法,並且還提供了工具和教程來幫助您入門。要了解有關BEM命名約定方面的更多信息,另一個極好的資源是Get BEM。

原子CSS

如果說BEM是行業寵兒,那麼原子CSS就是它的叛逆者。雅虎的Thierry Koblentz在其2013年的文章“挑戰CSS最佳實踐”中命名並解釋了原子CSS,它使用一個緊湊的類名庫。這些類名通常是縮寫的,並且與它們影響的內容脫節。在原子CSS系統中,您可以知道類名是什麼作用——但是類名(至少,樣式表中使用的類名)和內容類型之間沒有關係。讓我們用一個例子來說明。以下是我們在所謂的傳統CSS架構中可能稱之為的一組規則。這些規則集使用描述其應用內容的類名——全局消息框,以及“成功”、“警告”和“錯誤”消息框的樣式:

<div class="search">
  <label for="s" class="search__label">Search for: </label>
  <input type="text" id="s" class="search__input">
  <button class="search__submit">Search</button>
</div>
登入後複製
登入後複製

要創建錯誤消息框,我們需要將msg和msg-error類名都添加到元素的class屬性:

<div class="search search--inverse">
  <label for="s" class="search__label search__label--inverse">Search for: </label>
  <input type="text" id="s" class="search__input">
  <button class="search__submit search__submit--inverse">Search</button>
</div>
登入後複製
登入後複製

讓我們將其與原子系統進行對比,在原子系統中,每個聲明都成為它自己的類:

.search {
    color: #333;
}
.search--inverse {
    color: #fff;
    background: #333;
}
.search__submit {
    background: #333;
    border: 0;
    color: #fff;
    height: 2rem;
    display: inline-block;
}
.search__submit--inverse {
    color: #333;
    background: #ccc;
}
登入後複製
登入後複製

這是更多的CSS。現在讓我們重新創建我們的錯誤消息組件。使用原子CSS,我們的標記變為:

.msg {
    background-color: #a6d5fa;
    border: 2px solid #2196f3;
    border-radius: 10px;
    font-family: sans-serif;
    padding: 10px;
}
.msg-success {
    background-color: #aedbaf;
    border: 2px solid #4caf50;
}
.msg-warning {
    background-color: #ffe8a5;
    border-color:  #ffc107;
}
.msg-error {
    background-color: #faaaa4;
    border-color: #f44336;
}
登入後複製

我們的標記也更冗長。但是當我們創建警告消息組件時會發生什麼?

<p class="msg msg-error">An error occurred.</p>
登入後複製

兩個類名發生了變化:bg-d和bc-d被bg-c和bc-c替換。我們重用了五個規則集。現在,讓我們創建一個按鈕:

.bg-a {
    background-color: #a6d5fa;
}
.bg-b {
    background-color: #aedbaf;
}
.bg-c {
    background-color: #ffe8a5;
}
.bg-d {
    background-color: #faaaa4;
}
.bc-a{
    border-color: #2196f3;
}
.bc-b {
    border-color: #4caf50;
}
.bc-c {
    border-color:  #ffc107;
}
.bc-d {
    border-color:  #f44336;
}
.br-1x {
    border-radius: 10px;
}
.bw-2x {
    border-width: 2px;
}
.bss {
    border-style: solid;
}
.sans {
    font-style: sans-serif;
}
.p-1x {
    padding: 10px;
}
登入後複製

嘿!在這裡,我們重用了四個規則集,並且避免向我們的樣式表中添加更多規則。在一個強大的原子CSS架構中,添加新的HTML組件(例如文章側邊欄)不需要添加更多CSS(儘管實際上,它可能需要添加更多內容)。原子CSS有點像在CSS中使用實用程序類,但達到了極致。具體來說,它:

  • 通過創建高度細粒度、高度可重用的樣式來保持CSS簡潔,而不是為每個組件創建規則集
  • 通過使用低特異性選擇器系統來大大減少特異性衝突
  • 一旦定義了初始規則集,就可以進行快速的HTML組件開發

但是,原子CSS並非沒有爭議。

反對原子CSS的論點

原子CSS與我們學習的幾乎所有關於編寫CSS的內容都背道而馳。它感覺幾乎和到處粘貼樣式屬性一樣糟糕。事實上,對原子CSS方法論的主要批評之一是它模糊了內容和演示之間的界限。如果將元素浮動到左側並添加十像素的邊距,當我們不再希望該元素浮動到左側時該怎麼辦?當然,一個答案是將fl類從我們的元素中刪除。但是現在我們正在更改HTML。使用CSS的全部原因是為了使標記不受演示的影響,反之亦然。 (我們也可以通過從樣式表中刪除.fl {float: left;}規則來解決此問題,儘管這會影響每個類名為fl的元素。)儘管如此,更新HTML可能是為了獲得更簡潔的CSS而付出的少量代價。在Koblentz的原始文章中,他使用了諸如.M-10(margin: 10px)和.P-10(padding: 10px)之類的類名。這種命名約定的問題應該很明顯。更改為五像素或20像素的邊距意味著我們需要更新我們的CSSHTML,否則可能會導致類名無法準確描述其效果。使用諸如p-1x之類的類名,如本節所述,解決了這個問題。類名中的1x部分錶示比率,而不是定義的像素數。如果基本填充是五像素(即,.p-1x { padding: 5px; }),則.p-2x將設置十像素的填充。是的,這不太能描述類名所做的工作,但這同時也意味著我們可以更改CSS而無需更新HTML,並且不會創建誤導性的類名。原子CSS架構不會阻止我們使用描述內容的類名在我們的標記中。您仍然可以向代碼中添加.button-close或.accordion-trigger。對於JavaScript和DOM操作,此類類名實際上更可取。

BEM與原子CSS

當您有大量開發人員並行構建CSS和HTML模塊時,BEM效果最佳。它有助於防止大型團隊創建的錯誤和bug。它可以很好地擴展,部分原因是命名約定具有描述性和可預測性。 BEM不僅僅適用於大型團隊,但它非常適合大型團隊。當有一個小型團隊或一名工程師負責開發一組CSS規則,並由一個更大的團隊構建完整的HTML組件時,原子CSS效果更好。使用原子CSS,開發人員只需查看樣式指南——或CSS源代碼——即可確定特定模塊所需的類名集。

了解何時走自己的路

在實踐中,您的CSS可能包含多種方法的混合。除了影響佈局的實用程序類名之外,您可能還有一些描述內容或組件的類名。如果您無法完全控制標記(例如使用CMS),那麼這兩種方法都可能沒有用。您甚至可能需要使用冗長且特定的選擇器來實現您想要的目標。

關於CSS架構的常見問題解答:BEM和原子CSS

BEM和原子CSS的主要區別是什麼?

BEM(塊、元素、修飾符)和原子CSS都是組織和構建CSS代碼的方法論。 BEM專注於一種命名約定,使CSS更容易閱讀和理解。它將設計劃分為塊、元素和修飾符,以在CSS和HTML之間創建清晰、嚴格的關係。另一方面,原子CSS是關於編寫反映視覺功能的小型、單一用途的CSS類。它鼓勵可重用性並旨在減少代碼量。

BEM如何提高CSS的可擴展性?

BEM通過在CSS和HTML之間提供清晰而嚴格的關係來提高CSS的可擴展性。它使用特定的命名約定,使理解不同元素之間的關係更容易。這使得代碼更易於維護和擴展,因為更容易添加新功能或修改現有功能而不會破壞任何東西。

我可以同時使用BEM和原子CSS嗎?

是的,可以同時使用BEM和原子CSS。一些開發人員發現,結合這兩種方法可以獲得兩全其美的好處。 BEM的嚴格命名約定可用於構建CSS,而原子CSS的單一用途類可用於設置單個元素的樣式。這種組合可以產生高度組織化和易於維護的CSS代碼庫。

使用原子CSS的好處是什麼?

原子CSS提供了許多好處。它鼓勵可重用性,這可以大大減少您需要編寫的CSS數量。它還提高了設計的一致性,因為相同的類用於不同的組件。此外,原子CSS可以使您的樣式表更易於管理和理解,因為每個類都有一個單一、明確定義的目的。

BEM如何處理CSS特異性問題?

BEM通過鼓勵開發人員使用類選擇器而不是ID選擇器來幫助處理CSS特異性問題。這導致整個項目中的特異性保持一致,因此在必要時更容易覆蓋樣式。此外,BEM的命名約定清楚地表明哪些元素是相關的,從而減少了意外樣式衝突的可能性。

原子CSS適用於大型項目嗎?

是的,原子CSS適用於大型項目。它對可重用性和單一用途類的關注可以幫助保持CSS的可管理性,即使項目不斷發展壯大。但是,它需要一種嚴謹的方法來確保類保持一致和有意義。

BEM如何在團隊協作中提供幫助?

BEM清晰而嚴格的命名約定使團隊成員更容易理解CSS代碼,無論他們何時加入項目。這可以改善協作,因為開發人員可以輕鬆理解和修改其他人編寫的代碼。

使用原子CSS的潛在缺點是什麼?

原子CSS的一個潛在缺點是它可能導致HTML中出現大量類。這可能使HTML更難閱讀和理解。此外,原子CSS需要一種嚴謹的方法來確保類保持一致和有意義。

如何在我的項目中開始實現BEM?

要開始實現BEM,您需要將設計劃分為塊、元素和修飾符。然後,使用BEM的命名約定來命名您的CSS類。這將在您的CSS和HTML之間創建清晰的關係,使您的代碼更易於閱讀和維護。

我可以將BEM或原子CSS與Sass或Less等CSS預處理器一起使用嗎?

是的,BEM和原子CSS都可以與Sass或Less等CSS預處理器一起使用。這些預處理器可以使管理CSS更容易,並且它們與BEM和原子CSS的組織原則非常契合。

以上是CSS體系結構:Block-Element-Modifier(BEM)和Atomic CSS的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板