CSS中class的命名规范

作者: csRyan | 来源:发表于2017-03-31 15:30 被阅读220次

    避免以视觉效果来命名类

    尽量避免以类的视觉效果来命名:如.half。因为如果使用响应式布局,你的页面会有多种布局来适应多种显示设备的需求。一个元素可能要在台式电脑上占据一半的宽度,但在移动设备上你可能需要它占据全部的宽度.half的语义却把这个元素的宽度定死了:

    <div class="row">
      <div class="column half">
        <!-- Your Content -->
      </div>
      <div class="column half">
        <!-- Your Content -->
      </div>
    </div>
    

    如果这样命名,那么在移动设备上你就需要用js删除.half类然后增加.full类!

    更好的方式是:类名仅描述类的功能,对于那些需要响应式变化的类,我们使用媒体查询,让这个类在不同的环境中做出不同的布局表现。

    @media (min-width: 500px) {
        类名 {
            // 窄显示设备下的样式
        }
    }
    @media (max-width: 500px) {
        类名 {
            // 宽显示设备下的样式
        }
    }
    

    以类的功能来命名

    类名应该反映这个类的目的类之间的层次结构,而不是布局表现。

    BEM 命名方式

    BEM 是Block Element Modifier的缩写,它将一个类名分成这三个部分:模块、模块元素、描述符。模块规定整个组件的样式;模块元素规定这个组件中子元素的样式;描述符描述一种特殊的种类,给模块或模块元素增加特别的样式,以表示这个元素处于某种特别的状态(比如说被选中的状态)。

    使用BEM的类名清楚地展示了这个类的作用和层次结构关系,并且有效避免了类名重复导致样式覆盖。

    BEM的写法

    使用__连接模块与模块元素,使用--来连接描述符,如果一个名字由多个单词组成,用单词分隔符-来分割。

    // Block (Highest level)
    .block {...}
    
    // Element (Descendent of block)
    .block__element {...}
    
    // Modifier (Different state or version)
    .block--modifier {...}
    .block__element--modifier {...}
    

    BEM例子

    .person {}
    .person__hand {}
    .person--female {}
    .person--female__hand {}
    .person__hand--left {}
    

    看到这个样式表,我们马上可以知道

    • person就是整个部件;
    • person__hand描述person的手(元素);
    • person--female描述person中的女性(一个种类);
    • person--female__hand描述person--female的手(元素);
    • person__hand--left描述person__hand的一个种类:左手。

    如果我们不使用BEM:

    .person {}
    .hand {}
    .female {}
    .female-hand {}
    .left-hand {}
    
    • 类与类之间的结构不清晰(比如,female到底是放在person的子标签中,还是放在同一个标签中?如果使用BEM,带描述符的类与不带描述符的类就一定放在同一个标签中,见下面的例子)
    • 类名容易重复(比如female可以指不同的动物,如果出现了重名、样式覆盖,会导致动物的样式应用到人身上!)

    另一个例子:

    <div class="shopping-cart">
      <div class="shopping-cart__item">
        <!-- Your Content -->
      </div>
      <div class="shopping-cart__item shopping-cart__item--selected">
        <!-- Your Content -->
      </div>
    </div>
    

    以上例子描述了一个购物车组件的组成:
    shopping-cart规定了购物车组件的总体样式;组件中有元素shopping-cart__item,规定了购物车中的商品条目的样式shopping-cart__item--selected表示这是一个特别的商品条目(被用户选中的条目),我们可以给它添加特别的样式,比如红色的边框。

    用了这种方式,我们看到类名就可以知道它规定了谁的样式,并且类与类之间的关系也清晰了。


    再看一个例子:搜索栏组件
    反例:

    <form class="site-search  full">
        <input type="text" class="field">
        <input type="Submit" value ="Search" class="button">
    </form>
    

    使用BEM以后:

    <form class="site-search  site-search--full">
        <input type="text" class="site-search__field">
        <input type="Submit" value ="Search" class="site-search__button">
    </form>
    

    这里的site-search--full其实犯了我们开始说的错误:用视觉效果来给类命名,这里应该使用媒体查询而不是用一个类来让搜索栏占满宽度。这个例子仅用来学习使用BEM。

    什么时候不必使用BEM

    • 有一些样式是在任何组件中都通用的:
    .caps { text-transform: uppercase; }  // 字母大写显示
    
    • 有一些元素只是碰巧在这个组件中,与这个组件没有什么必然的联系,这个元素可以出现在很多其他的组件,比如:
      我们只需要定义一次网站logo的样式:
    .site-logo {}
    

    网站logo可以放在网站的header,footer,任何地方,他不应该作为某一个组件的子元素:

    .header {}
    .header__logo {}
    

    logo和header没有必然联系,他只是恰好出现在了header中,我们完全可以使用之前定义的.site-logo。假如我们还要在footer中假如logo,难道我们还要定义一个footer__logo吗?这太多余了!

    因此我们在使用BEM的时候要考虑清楚:这个元素是这个模块的组成部分吗?还是说这个元素只是恰好出现在这个模块中?如果是后者,不必使用BEM。


    参考文章:
    http://adamkaplan.me/blog/grid-retrospective
    https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/


    补充:对照真实的项目来理解

    如果没有项目的体验,确实很难理解BEM的意义。BEM其实就是将类名分成三个部分来描述这个类的作用。微信的样式库也是这么做的,可以对照看看:https://github.com/weui/weui/blob/master/dist/style/weui.css

    只用看其中和weui-cell有关的类名就可以了。注意微信的样式库对连接符的使用和我这篇文章讲的有点不一样,一个下划线_后面是描述符,两个下划线__后面的是元素。

    感兴趣的话还可以看看他们的DEMO,是如何使用的。


    后续我会写更多关于响应式布局的内容。

    相关文章

      网友评论

      • 陈小窝:太复杂啦
        csRyan:如果感兴趣的话,可以看我刚刚更新的补充部分,对照微信官方样式库来理解吧!

      本文标题:CSS中class的命名规范

      本文链接:https://www.haomeiwen.com/subject/rxqvottx.html