前面的話
每次寫HTML結構涉及到CSS命名時,都要掙扎一番。關于CSS命名的規范,市面上有不少,如OOCSS、SMACSS、BEM和MVCSS等。在這里面最火的應該算BEM了。本文將詳細介紹CSS命名
主流命名
【BEM】
說起CSS命名,當然要提到BEM。BEM的意思就是B模塊(block)、E元素(element)、M修飾符(modifier)。模塊和子元素之間用兩個下劃線分隔,子元素和修飾符之間用兩個中劃線分隔
關于子元素E,有兩種寫法。一種是按照層級嵌套來寫,如block-ele1-son-inner
,但是這樣寫會導致命名過長;另一種是扁平化,一個模塊B下的所有子元素,無論相互層級如何,都直接連接B,如block-inner
,但是這樣就無法表示層級關系,命名時也可能會出現沖突
BEM的命名是很好的,不然也不能成為最流行的命名方法。但是,BEM對子元素的命名,無論是層級長命名還是扁平化短命名,都有缺陷
【NEC】
相較于BEM以模塊B為頂級元素,子元素類名中包含繼承關系的命名,網易的NEC規范使用后代選擇器方式
NEC將元素分為了5類:布局(grid)(.g-);模塊(module)(.m-);元件(unit)(.u-);功能(function)(.f-);皮膚(skin)(.s-);狀態(.z-)。而后代選擇器不需要完整表現結構樹層級,盡量能短則短
.m-list{margin:0;padding:0;} .m-list .itm{margin:1px;padding:1px;} .m-list .cnt{margin-left:100px;}
個人認為,網易對于元素分類的做法很好。關于一些全局可復用的功能性的模塊進行區分,結構更為清晰。但是,對于使用后代選擇器的方式,個人不太認同。當嵌套層級較深時,命名沖突依舊是一個問題
【JD】
京東的命名規則采用表示層級嵌套關系的長命名。當子孫模塊超過4級或以上的時候,考慮在祖先模塊內具有識辨性的獨立縮寫作為新的子孫模塊
<div class="modulename"> <div class="modulename_cover"></div> <div class="modulename_info"> <div class="modulename_info_user"> <div class="modulename_info_user_img"> <img src="" alt=""> <!-- 這個時候 miui 為 modulename_info_user_img 首字母縮寫--> <div class="miui_tit"></div> <div class="miui_txt"></div> ... </div> </div> <div class="modulename_info_list"></div> </div> </div>
京東這種因子元素名字過長而采用首字母縮寫的做法非常贊,至今市面上沒有其他更好的解決長命名的方案
命名方式
【后代選擇器還是類名】
關于CSS命名,最大的爭論就是使用后代選擇器還是使用類名。以下例所示
<ul class="list"> <li class="list-item"></li> <li class="list-item"></li> <li class="list-item"></li> </ul> <ul class="list"> <li class="item"></li> <li class="item"></li> <li class="item"></li> </ul> <ul class="list"> <li></li> <li></li> <li></li> </ul>
如果采用第一種長類名的方式,為<li>元素設置樣式,只需如下設置即可
.list-item{}
如果采用第二種短類名的方式,則為<li>元素設置樣式,需如下設置
.list .item{}
如果采用第三種后代選擇器的方式,則為<li>元素設置樣式,需如下設置
.list li{}
如果從簡易角度來看,第三種后代選擇器的方式最簡單,無需花時間去給子元素起名,且在sass中書寫很容易
.list{
li{}
}
但是,它有一個很嚴重的問題,就是如果HTML結構層級較深,往往出現選擇器層級過長,如.list li span a{}
而且,因為后代選擇器強烈地依賴HTML結構,為了避免因為少寫一層結構,導致選擇器特殊性降低,樣式無法生效的情況,也不得不這樣寫
一個不得不提的問題是,CSS選擇器的解析順序是從右到左。而使用后代選擇器.list li{},瀏覽器需要遍歷出所有的li,再找出.list下的li,效率是最低的
因此,個人認為第三種后代選擇器的方式并不是好選擇
下面介紹第二種短類名的方式
1、選擇器解析效率比第三種方式好,畢竟.item比li的范圍小很多
2、短類名.list .item同樣存在依賴HTML結構的情況,很可能出現選擇器層級過長
3、使用較簡易,在sass中書寫容易,且起名也較簡單
4、由于給li增加了類名,于是增加了HTML文件大小
最后介紹第三種長類名的方式
這種方式的選擇器效率最高,因為.list-item這個類型頁面中只出現一次,可類比于id選擇器的解析速度
由于使用長類名的方式,可以完全不使用后代選擇器,則無需考慮選擇器特殊性較低,樣式無法生效的情況,也不會出現選擇器層級過長,因為它僅有一級
但是,相應地,它最大的缺點是類名較長,大大地增加了HTML文件大小。于是,可借鑒京東,當子孫模塊超過3級時,采用首字母縮寫,并將縮寫后首字母大寫的做法,在如將.list-item-link-title縮寫為.Lil-title
最終,選擇可縮寫的長類名作為CSS命名的主要方式
【分隔符】
一般地,classname分隔符有3種,中劃線-,下劃線_,以及首字母大寫,以分隔list和item為例
//中劃線
list-item
//下劃線
list_item
//首字母大寫
listItem
1、中劃線
中劃線可以用來表示層級關系
<div class="box"> <ul class="box-list"> <li class="box-list-item"></li> <li class="box-list-item"></li> <li class="box-list-item"></li> </ul> </div>
2、下劃線
下劃線可以用來表示不同的狀態
<div class="box"> <button class="box-btn box-btn_default" type="button"></button> <button class="box-btn" type="button"></button> </div>
3、首字母大寫
首字母大寫可以用來表示因為樣式的需要,而不得不增加的HTML結構。一般地,如果在外層增加結構,可以增加Wrap,在內層增加結構,可以增加Inner,且不影響原先的classname的命名
<div class="boxWrap"> <section class="box"> <h2 class="box-title"></h2> <p class="box-content"></p> </section> </div>
【組件】
通過上面的長命名方式和分隔符的使用,解決了基礎結構的命名。但是,在頁面中,很可能出現一些組件的應用,這些組件可以復用到頁面的多個位置。這時,再使用上面的方式就不太合適
于是,可以以m-為前綴,來表示這是一個組件
<div class="box"> <button class="m-btn m-btn_error" type="button"></button> <button class="m-btn" type="button"></button> </div>
命名推薦
有了合適的命名方式,還需要語義化命名,且有不影響語義的情況下,可以簡寫
【布局】
文檔 doc
頭部 header(hd)
主體 body
尾部 footer(ft)
主欄 main
側欄 side
容器 box/container
【通用部件】
列表 list
列表項 item
表格 table
表單 form
鏈接 link
標題 caption/heading/title
菜單 menu
集合 group
條 bar
內容 content
結果 result
【組件】
按鈕 button(btn)
字體 icon
下拉菜單 dropdown
工具欄 toolbar
分頁 page
縮略圖 thumbnail
警告框 alert
進度條 progress
導航條 navbar
導航 nav
子導航 subnav
面包屑 breadcrumb(crumb)
標簽 label
徽章 badge
巨幕 jumbotron
面板 panel
洼地 well
標簽頁 tab
提示框 tooltip
彈出框 popover
輪播圖 carousel
手風琴 collapse
定位浮標 affix
【語義化小部件】
品牌 brand
標志 logo
額外部件 addon
版權 copyright
注冊 regist(reg)
登錄 login
搜索 search
熱點 hot
幫助 help
信息 info
提示 tips
開關 toggle
新聞 news
廣告 advertise(ad)
排行 top
下載 download
【功能部件】
左浮動 fl
右浮動 fr
清浮動 clear
【狀態】
前一個 previous
后一個 next
當前的 current
顯示的 show
隱藏的 hide
打開的 open
關閉的 close
選中的 selected
有效的 active
默認的 default
反轉的 toggle
禁用的 disabled
危險的 danger
主要的 primary
成功的 success
提醒的 info
警告的 warning
出錯的 error
大型的 lg
小型的 sm
超小的 xs
實踐
<header class="hd"> <nav class="hd-navbar m-navbar m-varbar_primary"> <div class="hd-navbar-tel">聯系方式:400-888-8888</div> <ul class="hd-navbar-nav"> <li class="Hnn-itm m-btn m-btn_info"><a href="#">登錄</a></li> <li class="Hnn-itm m-btn"><a href="#">快速注冊</a></li> <li class="Hnn-itm m-btn"><a href="#">關于</a></li> <li class="Hnn-itm m-btn"><a href="#">幫助</a></li> </ul> </nav> ... </header>
【幻燈片】
<div class="carousel"> <div class="carousel-banner"> <a class="carousel-banner-item Cbi_slide1 Cbi_active" href="#"></a> <a class="carousel-banner-item Cbi_slide2" href="#"></a> <a class="carousel-banner-item Cbi_slide3" href="#"></a> <a class="carousel-banner-item Cbi_slide4" href="#"></a> </div> <a class="carousel-control carousel-control_prev" href="javascript:;"><</a> <a class="carousel-control carousel-control_next" href="javascript:;">></a> <div class="carousel-indicators"> <span class="carousel-indicators-item Cii_active"></span> <span class="carousel-indicators-item"></span> <span class="carousel-indicators-item"></span> <span class="carousel-indicators-item"></span> </div> </div>
關于CSS命名,并沒有最佳實踐之說,根據項目的復雜程序進行合適的命名才是可取的
歡迎交流
文章列表
留言列表