首頁 > web前端 > html教學 > 譯文:Nesting Your BEM?

譯文:Nesting Your BEM?

WBOY
發布: 2016-12-05 13:26:27
原創
1272 人瀏覽過

原文連結:http://csswizardry.com/2016/11/nesting-your-bem/

在我開始這篇文章之前,我必須說這不是一個建議或是新的「練習指南」。這只是我自己的一些思想狂潮。

我是一個[BEM](http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/)的支持和支持者。並且已經持續了很多年。這是有點有趣的期待。當然, 它給我提供了很多的東西:

* **軟封裝** 這有助於減少命名衝突。
* **自訂的CSS** 這幫助我理解DOM節點彼此之間的關係。
* **目標的選擇** 這有助於減少子樹之間的衝突,並且避免捕獲太多的節點。
* **管理方式的特殊性** 這是一個很大的亮點。
* **嚴格的實作規則** 這能夠防止我使用給定上下文以外的classes。

除了最後一點只有一半是真的......

BEM告訴我們,一個class, 例如: `.widget__title`, 僅只能用在`.widget`內。 但是這僅僅是通過了協議的規定。開發人員可能會把`.widget_title`放在`.model`之內,並且仍能正常運作。這是因為:

* 他們之前沒有見過BEM,或者是不知道執行它的方法
* 他們很懶惰,並且發現———即使是不應該,但是他們可以重用`.modal`內的`.widget_title`樣式的,然後這樣能夠提早5分鐘完成工作

他們能夠做到這一點,它也能為他們工作:東西仍舊能夠正確顯示。不會因此導致額外的錯誤,因為 BEM 只是一個規定,並且規定需要一致的認同。

為了規避這一點,我們可以像下面這樣寫CSS:

```
.widget { }

.widget .widget__title { }
```

現在開發者不能在`.modal`內使用`.widget_title`,因為我們告訴了我們的CSS:`wideget_title`僅在我們把它放到`.widget`中才能起效。現在我們開始執行這些事情,它將防止濫用。

這裡還有一個問題:巢狀

## CSS中的巢狀


在很長的一段時間內,我曾[積極主張](http://cssguidelin.es/#specificity)CSS中的嵌套是一件壞事情,因為:

* 增加了特性(這些應該始終要管理好);
* 引入了對存儲位置的依懶(不靈活系統的一個標誌);
* 減少了可移植性(這意味著我們不能隨意移動它) ;
* 增加了脆弱性(嵌套意味著選擇器出錯的可能性增加了)。

總和, [保持你的CSS選擇器的簡短性](http://csswizardry.com/2012/05/keep-your-css-selectors-short/).

但是在使用了嵌套BEM的情況中,我們看到了嵌套為我們帶來了實實在在的好處。但是我們要如何處理這些缺陷呢?

## 特異性

注意,通常情況下始終保持低特異性是很重要的。這完全正確,而且這是一個很好的建議。但是,這裡和我們熟知的那些是有一點差別的。人們在說特異性應當在任何情況下都處理好的時候,真正的意思是,我們應當保持一致性,並且選擇器之間的區別很小。

理論上(但是,親愛的,請不要嘗試這樣做),一個項目的唯一選擇器是ID選擇器,這將很好地管理特異性:特異性普遍是高的,但至少所有都符合併且相等。

當我們在討論如何處理好一致性的問題時:我們指的是它的[特異性圖](http://csswizardry.com/2014/10/the-specificity-graph/ )盡可能的平緩。

如果我們觀察下面這一系列的CSS組件:

```
.nav-primary { }

.nav-primary__item { }

.nav-primary__link { }

.masthead { }

.masthead__media { }

.masthead__text { }

.masthead__title { }

.sub-content { }

.sub-content__title { }

.sub-content__title--featured { }

.sub-content__img { }
```

…我們發現,他們每個class之間有著完全相同的特異性。這是一個很漂亮的平緩特異性圖:

![Graph showing low and flat specificity](http://p0.qhimg.com/t01298e8f9265d223bb.png)

[看大圖](http://csswizardry.com/wp-content/uploads/2016/11/graph-specificity-01.png)

一旦我們像下面這樣去嵌套這些classes:

```
.nav-primary { }

.nav-primary .nav-primary__item { }

.nav-primary .nav-primary__link { }

.masthead { }

.masthead .masthead__media { }

.masthead .masthead__text { }

.masthead .masthead__title { }

.sub-content { }

.sub-content .sub-content__title { }

.sub-content .sub-content__title--featured { }

.sub-content .sub-content__img { }
```

…我們看到的特異性圖將會是這樣的:

![Graph showing changes in specificity](http://p0.qhimg.com/t01afba20a956d400fc.png)

[看大圖](http://csswizardry.com/wp-content/uploads/2016/11/graph-specificity-02.png)

哦,天啊! 峰值(Spikes)! 峰值正是我們想要避免的,因為他們代表著項目中非常接近的選擇器之間的特異性的波動。

這裡我們看了嵌套中特異性導致的一些缺陷(Here we are visualising the specificity downside to nesting.)我們能避開它嗎?怎樣做?

## 連結第一個class

如果我們要連結第一個class (the Block) 到它本身, 像這樣:

```
.nav-primary.nav-primary { }

.nav-primary .nav-primary__item { }

.nav-primary .nav-primary__link { }

.masthead.masthead { }

.masthead .masthead__media { }

.masthead .masthead__text { }

.masthead .masthead__title { }

.sub-content.sub-content { }

.sub-content .sub-content__title { }

.sub-content .sub-content__title--featured { }

.sub-content .sub-content__img { }
```

…我們可以使其特異性地匹配所有無副作用的巢狀元素:

* 我們不需要知道這個Block在DOM中的位置,因此我們不會依據一些可能更改的位置而去增加它的特異性
* 我們並沒有連接到另一個不同的或者是特定的元素或者類。這表示Block類別依舊非常輕便。

這種特異性的增加完全依據它自身,現在我們看到了這樣的特異性圖:

![Graph showing higher but still flat specificity](http://p0.qhimg.com/t01cecef3a9​​8ac52bbf.png)

[看大圖](http://csswizardry.com/wp-content/uploads/2016/11/graph-specificity-03.png)

比第一張圖高,但是仍舊非常平緩。儘管我們我們的特異性是兩級的高度,它仍舊被很好的掌控:我們選擇器組件沒有特殊的權重。

## 用Sass簡化

為了讓巢狀以及連結更加簡化,我們可以使用預處理,這裡是Sass:

我們應當都熟悉如何在Sass中嵌套常規選擇器:

```
.nav-primary {

.nav-primary__item { }

.nav-primary__link { }

}
```

這給我們帶來了,正如我們所期待的:

```
.nav-primary { }

.nav-primary .nav-primary__item { }

.nav-primary .nav-primary__link { }
```

但是我們如何快速且有效地將第一個class連結到他自己?像這樣:

```
.nav-primary {

{&} { }

.nav-primary__item { }

.nav-primary__link { }

}
```

透過使用 `{&}`, 我們可以將目前的class連結到它自己。這意味著我們所有Block的樣式(在這種情況下, `.nav-primary`) 都在這裡:

```
.nav-primary {

{&} { /* Block styles */ }

}
```

[看一個關於Sassmeister的小範例](http://www.sassmeister.com/gist/a14e5b242ee6b20932dd44df0a3d215c)

## 實際結果

現在,我們的處境是事實上在強制地使用,並且主動地阻止選擇器的起效——如果我們主動地將它們從DOM中正確的部分移出的話。這可以幫助我們在其他開發者並不知道BEM如何起效的環境下工作,或者是那些傾向於使勁折騰直到一切看起來正常的人。

我們也有一個管理所有classes(雖然是增加的)的特異性

### 缺陷

我們正在增加一些特異性,這通常正是我們應該永遠努力去避免的。

## 用例

如果你想要嘗試延伸這種技術,在開始之前,這裡有必要確認一些關鍵的用例。第一個展現在我腦海中的是 網格系統(grid systems) 一次又一次地,我看見開發者們在`.grid`父類外嘗試去使用`.grid__item`類。所以,如果我打算開始使用這種技巧的話,我會從這裡開始:

```
.grid.grid { }

.grid .grid__item { }
```

## 用還是不用?

我不是很確定,正如我在開頭說的那樣,這不是一項我非常推薦並且致力於推行的技術。我只是想要提出它,給大家作為一個參考,尤其是對那些發現自己正處於一個,其他開發者都在輕易地濫用CSS的環境中的開發者。

但是,我想說的是:如果你已經嵌套了你的BEM,請返回,通過鏈接你的第一個class去拉平你的特異性圖。

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