摘要:我發(fā)現(xiàn)使用這些命名空間會使我的代碼非常具有可讀性。跨組件的組建我們面臨的另一個常見的問題是組件的樣式和位置會受到父級容器的影響。
無論你是剛剛發(fā)現(xiàn)BEM或者已經(jīng)是個中熟手(作為web術(shù)語來說),你可能已經(jīng)意識到它是一種有用的方法。如果你還不知道BEM是什么,我建議你在繼續(xù)閱讀這篇文章之前去BEM website了解一下它,因為我會假設(shè)你對這種CSS的方法有一個基礎(chǔ)的理解。
本文旨在對那些已經(jīng)是BEM的愛好者或是想要去更有效率的使用它或是非常好奇并且想去學(xué)習(xí)它的人有所幫助。
現(xiàn)在,我對BEM是一個優(yōu)雅的命名方式已經(jīng)不報有任何幻想。它完全不是。我曾經(jīng)很長一段時間放棄接受它的原因之一就是它的語法看起來非常丑陋。我心中的設(shè)計因子不希望我優(yōu)雅的html結(jié)構(gòu)被丑陋的雙下劃線和連字符弄得一團糟。
而我心中的開發(fā)者因子讓我務(wù)實地看待它。最終,這種用來構(gòu)建用戶界面并且有邏輯性的、模塊化的方式戰(zhàn)勝了我右半邊大腦的抱怨:“但是它不夠漂亮!”我當(dāng)然不會建議你在像起居室這樣小的范圍內(nèi)使用這種方式,但是當(dāng)你需要一件救生衣(就像你遨游在CSS的大海中),我會選擇實用而不是形式。話題拓展的差不多了,以下是10種我已經(jīng)遇到過的困境和一些如何解決它們的技巧。
1. 如何使用子代甚至更深層次的選擇器?首先來解釋這個問題,當(dāng)你需要選擇一個嵌套超過兩層的元素,你就會需要用到子孫選擇器。這些選擇器簡直就是我的夢魘,而且我很確定他們的濫用是人們對BEM產(chǎn)生厭惡的原因之一,看下面這個例子:
Title text here
Lorem ipsum dolor sit amet, consectetur
Adipiscing elit. Pellentesque amet
就像你想的那樣,以這種方式命名會很快就會脫離控制,并且一個組件嵌套的越深,越丑陋也越不可讀的類名就會出現(xiàn)。我已經(jīng)使用了一個短塊名稱c-card和短元素名,比如:body,text,link,但是你可以想象當(dāng)塊和元素的初始部分被命名為c-drop-down-menu會有多么失控。
我認(rèn)為雙下劃線在選擇器名稱中只應(yīng)該出現(xiàn)一次。BEM代表的是Block__Element--Modifier,而不是Block__Element__Element--Modifier。所以,避免多個元素級的命名。如果存在多級嵌套,你可能就需要重新審查一下你的組件結(jié)構(gòu)。
BEM命名和DOM沒有很嚴(yán)格的聯(lián)系,所以無論子元素的嵌套程度有多深都沒有關(guān)系。命名約定只是用來幫助你識別子元素和頂層組件塊的關(guān)系,在這里就是c-card。
這是我對相同card組件的處理:
Title text here
Lorem ipsum dolor sit amet, consectetur
Adipiscing elit. Pellentesque amet
這意味著所有的子元素都僅僅會被card塊影響。所以,我們可以將文本和圖片移動到c-card__header,甚至在不破壞語義結(jié)構(gòu)的情況下添加一個c-card__footer元素。
2. 我應(yīng)該使用命名空間嗎?現(xiàn)在,你可能已經(jīng)注意到我的代碼示例中使用了c-。這代表“組件”和形成了我命名BEM類名的規(guī)范。這個想法來自于致力于提升代碼可讀性的Harry Robert"snamespacing technique
這是我采用的規(guī)范,很多前綴會貫穿這篇文章的代碼示例。
TYPE | PREFIX | EXAMPLES |
---|---|---|
Component | c- | c-card c-checklist |
Layout module | l- | l-grid l-container |
Helpers | h- | h-show h-hide |
States | is- has- | is-visible has-loaded |
JavaScript hooks | js- | js-tab-switcher |
我發(fā)現(xiàn)使用這些命名空間會使我的代碼非常具有可讀性。即使我不能強求你使用BEM,這也絕對是一個值得你使用的關(guān)鍵點。
你可以采用很多其它的命名空間,像qa-可以用作質(zhì)量保證測試,ss-用作服務(wù)器端的鉤子,等等。但是上面的列表是一個好的開始,當(dāng)你覺得這項技術(shù)還不錯,你可以把它介紹給其他人。
在下個問題中,會有一個比較實用的關(guān)于樣式命名空間的示例。
3. 我該如何命名包裹容器?一些組建需要一個掌控子元素布局的容器。在這種情況下,我通常會嘗試把布局抽象到一個布局模塊中,比如l-grid,并且將每一個組件作為l-grid__item的內(nèi)容插入。
在我們card的示例中,如果我們想要去生成擁有四個c-card的列表,我會使用下面的html結(jié)構(gòu):
你現(xiàn)在應(yīng)該理解布局模塊和組件的命名空間是如何一起工作的。
不要害怕使用一些額外的標(biāo)記會非常令人頭痛。沒有人會拍拍你的背然后告訴你去把 在一些情景下,布局模塊是不可能的完全滿足要求的。比如說你的網(wǎng)格沒有能給你想要的結(jié)果,或者你只是想要去語義化的命名一個父元素,你應(yīng)該怎么做?在不同的場景我傾向去選擇contaniner或者list。還是我們card的例子,我可能會用 我們面臨的另一個常見的問題是組件的樣式和位置會受到父級容器的影響。就這個問題Simurai有很多詳細的解決辦法。我這里說一個拓展性最好的方式。 假設(shè)我們想要在之前的示例的card__body中加入一個c-button。這個按鈕本身已經(jīng)是一個組件并且結(jié)構(gòu)如下: 如果和常規(guī)的按鈕組件沒有樣式差別,那么就沒有問題。我們只要像下面這樣直接使用: Lorem ipsum dolor sit amet, consectetur Adipiscing elit. Pellentesque. 舉個例子,如果我們想要讓按鈕變小一點并且完全是圓角,而這些樣式只是c-card組件的一部分。也就是說,當(dāng)它有一些微小的不同時我們應(yīng)該怎么辦? 之前我說過,我找到一個最好用的跨組件類名的解決方式。 Lorem ipsum dolor sit amet, consectetur Adipiscing elit. Pellentesque. 這就是BEM官網(wǎng)上著名的“mix”。但是,參考了一些從Esteban Lussich的評價之后,我改變了對這種方式的看法。 在上面的例子中,c-card__c-button類嘗試去改變一個或多個c-button中存在的屬性,但是成功應(yīng)用這些樣式取決于他們的源順序(或者特殊的指定)。c-card__c-button類只會當(dāng)它在源代碼里聲明在c-button類之后才會生效。在你構(gòu)建更多跨組件的組件時會很快失控。(當(dāng)然,使用!important也是一種選擇,但是我不建議你這樣做) 一個真正模塊化的UI元素的父元素應(yīng)該是完全不可知的-無論你在何處使用它,效果都應(yīng)該是一致的。像“mix”方式那樣為另一個組件添加具有特定樣式的類名,違反了組件驅(qū)動設(shè)計的開/關(guān)原則,即樣式在各模塊之間不應(yīng)該有依賴關(guān)系。 最好的辦法就是在這些微小的樣式差別中使用同一個類,因為你會發(fā)現(xiàn)隨著項目的增長你會在別的地方對它進行復(fù)用。 即使你不會再使用這些類,為了應(yīng)用這些修改,至少也不能把他們和父容器、特殊屬性和源順序耦合在一起。 當(dāng)然,另一個選擇就是回到你的設(shè)計師崗位,告訴他們這個按鈕應(yīng)該和網(wǎng)站上的其他按鈕保持一致,這樣就可以完全避免這個問題。但這是另一碼事了。 決定組件的起止是一個大問題。在c-card這個示例里,你可能之后會創(chuàng)建另一個叫c-panel的組件,他們兩個樣式相仿,只有一些細微的差別。 但是是什么決定他們應(yīng)該是兩個組件呢?c-panel和c-card這個塊名,或者僅僅是因為一個修飾器在c-card里應(yīng)用了特殊的樣式。 這樣很容易過度模塊化并且讓一切都變成一個組件。我建議從修飾器開始,但是如果你發(fā)現(xiàn)你特定組件的CSS文件正變得很難維護,這時候就可以停止使用修飾器。當(dāng)你發(fā)現(xiàn)你為了適應(yīng)你新的修飾器而不得不去重置這個“塊”所有的CSS時,就是需要新組件的好時機-起碼對我來說是這樣的。 如果你和其它開發(fā)者或者設(shè)計師協(xié)作,最好的方式是去詢問他們的意見并且花幾分鐘去討論。我知道這樣可能有點逃避責(zé)任,但是對于一個大型項目來說,理解哪些模塊是可復(fù)用的并且在組件的構(gòu)成上達成一致是至關(guān)重要的。 這是一個常見的問題,特別是當(dāng)你給一個活躍狀態(tài)的組件編寫樣式的時候。讓我們假設(shè)cards有一個活躍狀態(tài),當(dāng)我們點擊它時,它們會被添加上一個好看的邊框。你會怎么去命名這個類? 在我看來你有兩種選擇:獨立的狀態(tài)鉤或者是一個在組件級類似BEM方式命名的修飾器。 盡管我更傾向于保持一致性的類似BEM的命名方式,獨立類名的好處是使用JavaScript來在任意一個組件中應(yīng)用一般的狀態(tài)鉤更容易。當(dāng)你不得不使用腳本去應(yīng)用特定的基于修飾器的狀態(tài)類時,類BEM的方式就很讓人頭疼了。這當(dāng)然是完全可行的,但是意味著你需要為每種可能性去編寫更多的JavaScript代碼。 堅持使用一系列標(biāo)準(zhǔn)的狀態(tài)鉤是有意義的。Chris Pearece有一個編譯好的列表,我推薦你去了解一下。 我可以理解很多人在需要構(gòu)建一個復(fù)雜UI的時候面臨的痛苦,特別是他們不習(xí)慣去在每個標(biāo)簽上添加一個類。 通常,我會在需要特殊樣式的部分上下文添加類名。我會把p標(biāo)簽級的舍棄,除非在這個組件中有特殊的需求。 可以預(yù)見,這意味著你的html中會包括非常多類名。最終,你的組件可以獨立運行并且在沒有副作用的條件下在任何地方使用。 由于CSS的全局特性,在所有部分都添加類讓我們可以完全控制我們組件的渲染。最初的心理不適在一整個模塊化的系統(tǒng)完成后是完全值得的。 假設(shè)我們想要在c-card組件中展示一個選項列表,下面這是一個反面教材: I would like to buy: 這里有很多問題。第一個是我們在第一點里提到的子孫選擇器。第二點是所有應(yīng)用c-card__checklist__item樣式都被限定使用,不能復(fù)用。 我更傾向于這里需要打破在這個布局模塊中的列表本身,而是應(yīng)該把選項列表多帶帶抽象成一個組件,這樣就可以在其它地方獨立使用它們。這里我們使用l-命名空間。 I would like to buy: 這樣你就不用重復(fù)哪些樣式,同時也意味著我們可以在項目中的其它地方使用l-list和c-checkbox。可能這意味著更多的標(biāo)記,但是對于可讀性,封裝性和可復(fù)用性來說代價可以忽略。你可能已經(jīng)注意到這些是共同的主題! 有些人認(rèn)為每個元素有大量類名是不好的,--modifiers會越積越多。就我個人而言,我不認(rèn)為這是個問題,因為這意味著代碼更具有可讀性,我也能更清楚的知道它是用來實現(xiàn)什么的。 舉個例子,這是一個具有四個類的按鈕: 我第一眼看到的時候覺得語法不是最簡潔的,但是非常清晰。 如果這讓你非常頭痛,你可以查看Sergey Zarouski提出的拓展技術(shù),我們可以在樣式表中使用.className [class^="className"]和[class*=" className"]來效仿vanilla CSS的拓展功能。如果語法看起來很眼熟,可能是因為和Icomoon處理它的icon選擇器的方式非常類似。 使用這種技術(shù),你的代碼可能會看起來像下面這樣: 我不知道使用class^=和class*=選擇器是否比獨立的類名表現(xiàn)更好,但是理論上來說這是一個不錯的選擇。我喜歡使用復(fù)合類名,但我覺得這值得那些傾向于尋找替代品的人注意一下。 這是Arie Thulank給我提出的問題,我花費了很多心思去想出一個100%具體具體的解決辦法。 一個例子就是下拉菜單在給定斷點處轉(zhuǎn)換為選項卡或者是隱式導(dǎo)航在給定斷點處轉(zhuǎn)換為菜單欄。本質(zhì)上是一個組件在媒體查詢的控制下有兩種不同的樣式表現(xiàn)。 我傾向于給這兩個例子去構(gòu)建一個c-navigation組件,因為他們在兩個斷點處的行為本質(zhì)是相同的。但這讓我陷入沉思,如果是圖片列表在大屏幕上轉(zhuǎn)化為輪播圖呢?這對我來說是一個邊緣情況,只要它有可行的文檔及評論,我認(rèn)為這是合理的。可是使用明確的命名(像c-image-list-to-carousel)來為這種類型的UI構(gòu)造一次性的獨立組件。 Harry Roberts寫過一篇響應(yīng)式后綴來解決這個問題。他的做法是為了適應(yīng)更多布局和樣式的變化,而不是整個組件的變化。但我不明白為什么這項技術(shù)不能被應(yīng)用在這里。所以,你會發(fā)現(xiàn)作者寫的樣式像下面這樣: 對于不同的屏幕尺寸,這些類就會保留各自的媒體查詢。提示:在CSS中你需要在@前加上來進行轉(zhuǎn)義,像下面這樣: 我沒有太多構(gòu)造這種組件的示例,但是如果你需要構(gòu)造這種組件,這將是一個對開發(fā)者非常友好的方式。下一個加入的人應(yīng)該可以輕松理解你的想法。我不提倡你使用像small-screen和large-screen這樣的命名,他們只是單純?yōu)榱丝勺x性。 BEM在我創(chuàng)建一個模塊化和組件驅(qū)動的應(yīng)用時幫了大忙。我已經(jīng)使用它大概有三年了,上面的這些問題是我在探索時遇到的阻礙。我希望你認(rèn)為這篇文章是有用的。如果你還沒有想要體驗BEM,我非常鼓勵你去嘗試一下。 本文根據(jù)@David Berner的《Battling BEM (Extended Edition): 10 Common Problems And How To Avoid Them》所譯,整個譯文帶有我自己的理解與思想,如果譯得不好或有不對之處還請多多指點。如需轉(zhuǎn)載此譯文,需注明英文出處:https://www.smashingmagazine.... 文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。 轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/49954.html 摘要:我發(fā)現(xiàn)使用這些命名空間會使我的代碼非常具有可讀性。跨組件的組建我們面臨的另一個常見的問題是組件的樣式和位置會受到父級容器的影響。
無論你是剛剛發(fā)現(xiàn)BEM或者已經(jīng)是個中熟手(作為web術(shù)語來說),你可能已經(jīng)意識到它是一種有用的方法。如果你還不知道BEM是什么,我建議你在繼續(xù)閱讀這篇文章之前去BEM website了解一下它,因為我會假設(shè)你對這種CSS的方法有一個基礎(chǔ)的理解。
本文旨在對那... 摘要:我發(fā)現(xiàn)使用這些命名空間會使我的代碼非常具有可讀性。跨組件的組建我們面臨的另一個常見的問題是組件的樣式和位置會受到父級容器的影響。
無論你是剛剛發(fā)現(xiàn)BEM或者已經(jīng)是個中熟手(作為web術(shù)語來說),你可能已經(jīng)意識到它是一種有用的方法。如果你還不知道BEM是什么,我建議你在繼續(xù)閱讀這篇文章之前去BEM website了解一下它,因為我會假設(shè)你對這種CSS的方法有一個基礎(chǔ)的理解。
本文旨在對那... 摘要:上例中打印的結(jié)果是對中的名都做了處理,使用對象來保存原和混淆后的對應(yīng)關(guān)系。結(jié)合實踐在處直接使用中名即可。如因為只會轉(zhuǎn)變類選擇器,所以這里的屬性選擇器不需要添加。
showImg(http://gtms01.alicdn.com/tps/i1/TB15w0HLpXXXXbdaXXXjhvsIVXX-600-364.png);
CSS 是前端領(lǐng)域中進化最慢的一塊。由于 ES2015/201... 摘要:本篇介紹幾種命名規(guī)范。使用的網(wǎng)站四其他命名規(guī)范等減少對結(jié)構(gòu)的依賴增加重復(fù)性的使用幾種命名規(guī)范比較與在命名上相反的點可以放心使用,以為都是在模塊內(nèi)但不推薦當(dāng)前我們的網(wǎng)站略有思想更概括,中的,相當(dāng)于的,相當(dāng)于的,相當(dāng)于的中文
本篇介紹幾種CSS命名規(guī)范。 (規(guī)范詳細請參考底部References)
一、NEC (nice easy css)
網(wǎng)易前端CSS開源項目
1.1 樣式分類
重...[…]
或者是[…]
,這取決于使用的條件。關(guān)鍵是要和你的命名約定保持一致。``
Title text here
Title text here
``
Title text here
Title text here
``
``
`
`
.c-image-list@small-screen {
/* styles here */
}
相關(guān)文章
和BEM的戰(zhàn)斗:10個常見問題及如何避免
和BEM的戰(zhàn)斗:10個常見問題及如何避免
CSS Modules詳解及React中實踐
CSS命名規(guī)范
發(fā)表評論
0條評論
閱讀 2067·2021-10-12 10:12
閱讀 788·2021-09-24 09:47
閱讀 1187·2021-08-19 11:12
閱讀 3461·2019-08-29 13:06
閱讀 681·2019-08-26 11:43
閱讀 2563·2019-08-23 17:20
閱讀 1146·2019-08-23 16:52
閱讀 2593·2019-08-23 14:27