什麼鬼,又不知道怎麼命名class了

本文由 IMWeb 首發於 IMWeb 社區網站 imweb.io。點擊閱讀原文查看 IMWeb 社區更多精彩文章。php


相信寫css的人都會遇到下面的問題:
css

  • 糟糕,怎麼命名這個class,好像不太貼切,要是衝突了怎麼辦,要不要設計成通用一點...html

  • 而改別人css代碼的時候則會一直有個疑問:這個class究竟是隻在這個地方用了,仍是其餘地方都用了?前端

因而就有了下面的作法:web

  • 最後終於被逼出了個class,簡潔也好,中英混搭也罷,看着一頭霧水也不要緊,反正最後頁面顯示出來的。後端

  • 這個class應該是隻有這個地方用到,我能夠放心寫。上線以後。若是沒問題,則暗自自我欣賞,看吧問題就這麼簡單,分分鐘搞定呀;若是衝突了,則無限感慨,哎,改的時候我就隱隱不安啊,媽蛋,深坑,這是誰寫的,誰寫的!!!app

  • 很差,這個class說不定其餘地方也用到了,我得加個限制範圍,加個父元素?要不從新再命名個class吧,比較保險。最後若是沒問題則表示還比如較機智,怎麼說哥也是混過的,仍是有幾斤幾兩的;若是有問題則表示防不慎防啊,這也太太太坑了吧。框架

因而可知,class的命名真不是一件簡單的事,尤爲還要兼顧可辨別性與可讀性。前後端分離

class命名到底有多難

第一,class跟id不同,class原本就是設計用來能夠重複利用的,而id纔是設計惟一的(若是遵循BEM,class幾乎也都是惟一的了)。ide

第二,樣式是能夠覆蓋的,並且先按照權重,再按照定義的前後順序。也許你花了十分鐘設計定義的一個class樣式,人家分分鐘就給你幹掉了,這得多惱火;也許這個頁面好好的,跑到另外一個頁面就跟原先的樣式有了衝突。

因此class命名的難就難在既要重複利用,又要避免樣式的衝突。若是要重複利用,那麼固然是越簡單越好,越抽象可用的地方越大,太具體了就完蛋了。而若是要避免樣式衝突。BEM的方式最簡單,class都惟一了,那還衝突個毛線;其次就是經過父元素限定做用域,能夠搞幾個層級,而不是單獨一個class定義樣式;還有就是追加class,來實現差別化;最後不一樣的頁面不一樣的文件,你用你的我用個人。

 
 
  1. // BEM

  2. .imgslide__item__img{}


  3. // 父元素限定

  4. .imgslide .item .img{}


  5. // 追加class

  6. .img{}

  7. .img--special{}


  8. // 不一樣頁面不一樣文件

  9. // a.html & a.css

  10. .img{}

  11. // b.html & b.css

  12. .img{}

總之,無論有多難,咱們仍是得試試去解決問題,去尋找一些規律。

class命名的發展歷程

關於class的命名,其實跟人名也差很少,若是要想別人看得懂,那關鍵仍是在於可識別性。到目前爲止class的命名大概經歷了下面幾個重要階段:

  • 混沌階段,沒有規則就是最好的規則

  • 原子類階段,彙集神龍現身手

  • 模塊階段,以職能劃分,添加前綴

  • BEM階段,規則有序

混沌階段

這個沒什麼好說的,剛開始學html的都是這樣,名字先簡單的來,不夠再添加1,2,3什麼後綴,或者中英混搭等等,以下:

h1.titleh2.title2h2.title2-1h2.title2-2div.hddiv.hd-sdiv.hd2div.hd-xiangxi

一個字,太亂。徹底無章程,規律可循,想怎麼寫就怎麼寫,寫到哪裏是哪裏。看class去猜意思極可能就是錯誤的,如 .red{color:red;font-size:14px;},明明說好的紅色,卻順帶定義了個字體大小。

原子類階段

這個關鍵在於拼湊組合,足夠多的原子類拼成一個完整的樣式:

.fl{float:left;}.fr{float:right;}.pr{position:relative;}.pa{position:absolute;}.tal{text-align:left;}.tac{text-align:center;}.tar{text-align:right;}.fs12{font-size:12px;}
div.fs12.fl.pr.tacdiv.pa.tal

這種有兩個缺點,第一是稍微複雜點的樣式都要使用不少class組合,第二是若是要修改樣式的時候得修改html文件,而不是css樣式,而純靜態的頁面是不多的,因此若是是先後端分離的,由php或後端語言渲染頁面的話,改個樣式還要通知後端同事去修改文件,那估計人家得瘋掉。

模塊階段

到了這個時候,css通過這麼多年的發展,頁面的複雜性已經翻了好幾倍了,那些無規劃的混沌根本不夠用,滿眼的class看起來長得都差很少,後面全是1,2,3都不知道標到多少了,殊不知道究竟是啥區別;而原子類已經不適合頻繁的修改調整更新,每更新下都是先後齊心合力。因而按職能劃分的class命名規則就出現了

// l表示layout,  g表示global,  m表示mod,.l-960.l-left.l-right.g-red.g-title.g-price.m-login.m-breadcrumb.m-slide

這種命名方式在必定程度解決了混亂不堪的問題,全部的按照職能劃分看起來很美好,不過動不動加個前綴確實不怎麼優雅,再者隨着mod的增長,這個以m開頭的前綴根本就不夠用,因而又亂了,有加二級前綴的,也有另起前綴的。

BEM

這個估計地球上作前端的都知道吧,實在是太火了,因此不用來解釋了。優勢就是你只管寫你本身的,99.99%的概率不會去幹掉別人的樣式,class實在太長了,能同樣那得多高的概率啊。缺點仍是class太長,太長,太長,重要的事情說三遍。通常都記不住本身定義的class,寫css的時候只好對着去拷貝。而後最痛苦的就是去修改更新,明明很簡單的東西,而後你還要搞個超長的class,那叫一個煩躁,想一想都懶得動手。

他山之石

其實每一個命名的發展經歷都有其特定的歷史意義,也固然有其價值。因此吸收之長,棄之短缺就很好了。比喻寫簡單demo的時候,咱們就能夠用到混沌階段的命名,足夠簡單,不須要糾結思考;而原子類尤爲是一些簡單的樣式,如一行代碼就能夠搞定,起個class名甚是糾結,還不如直接上原子類;至於模塊類,說真的應用的場景就更多了,如佈局,js操做類等;而BEM咱們一樣可借鑑其思想,如 .class.class--name使用 --表示特殊化,以區分 -

這裏咱們站在前人的肩膀上,試着去開闢一條道路,能夠兼顧簡潔可讀性及可理解辨別性。固然class的簡潔確定離不開關鍵詞的應用,這裏咱們先來過一遍常見的class關鍵詞。

常見class關鍵詞:

  • 佈局類:header, footer, container, main, content, aside, page, section

  • 包裹類:wrap, inner

  • 區塊類:region, block, box

  • 結構類:hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span

  • 列表類:list, item, field

  • 主次類:primary, secondary, sub, minor

  • 大小類:s, m, l, xl, large, small

  • 狀態類:active, current, checked, hover, fail, success, warn, error, on, off

  • 導航類:nav, prev, next, breadcrumb, forward, back, indicator, paging, first, last

  • 交互類:tips, alert, modal, pop, panel, tabs, accordion, slide, scroll, overlay,

  • 星級類:rate, star

  • 分割類:group, seperate, divider

  • 等分類:full, half, third, quarter

  • 表格類:table, tr, td, cell, row

  • 圖片類:img, thumbnail, original, album, gallery

  • 語言類:cn, en

  • 論壇類:forum, bbs, topic, post

  • 方向類:up, down, left, right

  • 其餘語義類:btn, close, ok, cancel, switch; link, title, info, intro, more, icon; form, label, search, contact, phone, date, email, user; view, loading...

有了關鍵詞以後,咱們先來制定一些簡單的規則

制定簡單規則:

  • 以中劃線鏈接,如 .item-img

  • 使用兩個中劃線表示特殊化,如 .item-img.item-img--small表示在 .item-img的基礎上特殊化

  • 狀態類直接使用單詞,參考上面的關鍵詞,如 .active,.checked

  • 圖標以 icon-爲前綴(字體圖標採用 .icon-font.i-name方式命名)。

  • 模塊採用關鍵詞命名,如 .slide,.modal,.tips,.tabs,特殊化採用上面兩個中劃線表示,如 .imgslide--full,.modal--pay,.tips--up,.tabs--simple

  • js操做的類統一加上 js-前綴

  • 不要超過四個class組合使用,如 .a.b.c.d

關鍵詞及規則都有了,如今能夠進入本文的核心的核心,實戰操做。

實戰操做

以佈局入手,大概結構以下:

header.header>.inner-centersection.section-feature>.inner-center // ifsection.section-main>.inner-centersection.section-postscript>.inner-center // iffooter.footer>.inner-center

具體可參考HTML整站結構設計(http://imweb.io/topic/55e1d253771670e207a16bb2),這裏咱們能夠看出都是些簡單的關鍵詞,比較好理解,一看就知道是什麼。

如今問題來了,若是其餘地方也要用到這些關鍵詞怎麼辦?

修飾關鍵詞

以header爲例,咱們能夠添加前綴表示不一樣的header,如區塊頭部 .block-hd(hd爲header簡寫),modal頭部 .modal-hd,文章頭部 .article-hd

一樣標題也能夠分爲,頁面標題 .page-tt(title的簡寫),區塊標題 .block-tt等。

一樣,這給咱們提出了第二個問題,若是要特殊化某個class該怎麼辦?

特殊化class

以上面的tt爲例,大概有三種辦法:

第一種犯法:直接修改class,將 .page-tt修改爲 .page-user-tt(能夠採用scss的 %先定義共用的代碼)。

第二種辦法:追加class特殊化,根據咱們上面定義的規則,在 .page-tt上追加一個class成爲 .page-tt.page-tt--user,注意 .page-tt--user不是一個獨立的class,它是基於 .page-tt這個基礎上的。

第三種辦法:使用父類,給一個範圍,因而造成 .page-user.page-tt

通常咱們使用的是第二種和第三種辦法,由於這兩種都有共同的 .page-tt,能夠比較方便控制一些基礎共有的樣式。

由第三個經過父類控制的辦法,咱們進入第三個要討論的問題,層級結構

層級

最適合層級的例子莫過於 ul>li結構了,以下面的結構:

<ul>    <li>        <a href="#"><img src="" alt=""></a>        <h3><a href="#"></a></h3>        <p></p>    </li></ul>

通常來講咱們也有兩種辦法定義層級,第一種爲繼承式,第二種爲關鍵詞式。

 
 
  1. // 繼承式

  2. ul.card-list

  3.    li.list-item

  4.        a.item-img-link>img.item-img

  5.        h3.item-tt>a.item-tt-link

  6.        p.item-text


  7. // 關鍵詞式

  8. ul.card-list

  9.    li.item

  10.        a.field-img-link>img.field-img

  11.        h3.field-tt>a.field-tt-link

  12.        p.field-text

由上能夠看出繼承式通常子元素接着父元素的最後一個單詞如li接着ul的 list,而li的子元素接着li的 item;至於關鍵詞式則徹底由關鍵詞來表示層級, list>item>filed正好構成三層等級。

最後由咱們的層級進入咱們最後一個問題,如何控制樣式的範圍

樣式範圍

這裏以騰訊課堂(http://ke.qq.com/)的課程詳細頁右邊欄爲例,以下圖:

圖片

三個區塊的基礎框架爲:

.aside-block.block--xxx>    h3.block-tt    .block-bd

其中 .aside-block.block--xxx用到了咱們的特殊化class,而 .block-tt, block-bd則使用了咱們的修飾關鍵詞,至於 .aside-block與它的子元素之間則使用了咱們上面說的繼承式層級。如今根據這個層級結構咱們定義基礎樣式以下:

.aside-block{    .block-tt{}    .block-bd{}}

假設這裏的聯繫機構區塊的標題不同,咱們則能夠:

.block--contact{    .block-tt{}}

固然若是自己有5個區塊,2個標題同樣,另外三個標題又同樣,也許咱們就有須要給 .block-tt追加一個特殊化class,或者給 aside-block特殊化一個class,如:

.aside-block{    .block-tt{        &.block-tt--special{}    }    .block-bd{}}// 或.aside-block{    &..aside-block--special{      .block-tt{}  }}

基礎框架討論完畢以後,就輪到咱們的內容了,以聯繫機構爲例:

使用 ul>li結構,因此樣式是另一個獨立的範圍,不嵌套在以前的 .aside-block裏面,html及css代碼以下:

ul.contact-list    li        i.item-icon.icon-font.i-xxx        a.item-tt        p.gray

這裏咱們li沒有設置class,而p使用了一個全局的class .gray

.gray{}.contact-list{    li{}    .item-icon{}    .item-tt}

同理若是咱們有其餘地方應用這個能夠拷貝過去,而若是須要一點調整,咱們可使用父元素來控制,如這裏咱們可使用 .block--contact來進一步調整contact的樣式,如:

.block--contact{    .contact-list{        li{}    }}

至此,咱們的class命名方法討論完畢,說到底就是先記住一些必備的基礎關鍵詞,而後合理應用上剛纔提出的修飾關鍵詞,特殊化class,層級及最後的樣式範圍就能夠了。

相關文章
相關標籤/搜索