css的组织方式:BEM规则

why?

无论选择了什么样的css组织方法,你都会从更加结构化的css 和 Ui 结构中获益。有些方式不那么严格,更加灵活。而另一些方法则更加易于理解,适用于团队协作。

为什么要选择bem呢?它不像其他语法(smacss)那么复杂,但是仍然可以提供给我们优良的代码结构和易于识别的术语。

模块化

block永远不依赖于页面上的其他元素,因此不会遇到级联问题。而且易于从旧项目中迁移。只要从某一个块级元素开始即可。

可复用

以不同的方式组合独立的块级元素,重用它们,减少可维护的代码量。甚至可以构造一个基于block的库。

结构

bem法让css代码有良好的组织结构,既简单,又易于理解。

what?

概念

  • b – block
    一个本身就是有意义的独立实体。尽管一个block可以和其他block嵌套和共同发挥作用,但语义上所有blocks是平等的,并没有等级或者优先级之分。没有表现为DOM的整体实体(例如控制器或模型)也可以是块。

    块名称可以包含拉丁字母,数字和短划线。

    任何有class name的dom节点都可以成为block。

    在一页中,没有对其他Blocks、elements的依赖。

    e.g: header, container, menu, checkbox, input

  • e – element
    Block的一部分,没有独立的意义,而且在语义上依附于Block存在。
    e.g: menu item, list item, checkbox caption, header title

    元素名称可以包含拉丁字母,数字,短划线和下划线。主要是以两个下划线接在block之后,来表示从属关系。

    在一个block下的任何dom节点都可以是element。

    没有对同一页上其他blocks/elements的依赖。

    // 好例子
    .block__elem {
      color: #fff;
    }
    
    //坏例子
    .block .block__elem {
      color: #042;
    }
    div.block__elem {
      color: #042;
    }
    
  • m – modifier
    修饰符,一个block或者element上的flag,体现了外观或者行为的变化。

    修饰符名称可能包含拉丁字母,数字,短划线和下划线。以两个短划线接在element/block的类名之后,诸如.block--mod, .block__elem--mod.block--color-blackblock--color-red。在复杂修饰符中的空格用短划线来代替。

    e.g: disabled, highlighted, checked, fixed, size big, bg yellow

    修饰符是您添加到块/元素DOM节点的额外类名。仅将修饰符类添加到它们修改的块/元素,并保留原始类名。是添加不是替换

     <!-- 好例子 -->
    <div class="block block--mod">...</div>
      <div class="block block--size-big
      	block--shadow-yes">...</div>
    
    <!-- 坏例子 -->
    <div class="block--mod">...</div>
    

    在block层级的修饰符下的元素,可以这么写

    
    .block--mod .block__elem {}
    
    

    例子:

    <form class="form form--theme-xmas form--simple">
      <input class="form__input" type="text" />
      <input
        class="form__submit form__submit--disabled"
        type="submit" />
    </form>
    
    .form { }
    .form--theme-xmas { }
    .form--simple { }
    .form__input { }
    .form__submit { }
    .form__submit--disabled { }
    

例子

http://getbem.com/assets/github_buttons.jpg

如上图,可以在按钮上应用任何想要的标签,如Button,a, div 等,可使用block--modifier-value语法。

.button {
	display: inline-block;
	border-radius: 3px;
	padding: 7px 12px;
	border: 1px solid #D5D5D5;
	background-image: linear-gradient(#EEE, #DDD);
	font: 700 13px/18px Helvetica, arial;
}
.button--state-success {
	color: #FFF;
	background: #569E3D linear-gradient(#79D858, #569E3D) repeat-x;
	border-color: #4A993E;
}
.button--state-danger {
	color: #900;
}

faq:

  1. 为什么要选择bem作为css模块化的解决方案?

精髓在于 块的独立性。

如果仅谈论CSS模块化解决方案,BEM的关键特性是块的独立性。 遵循CSS建议可以将块放入页面上的任何位置,并确保它不会受到周围环境的影响。 此外,如果您最近需要将另一个块嵌套到当前块中,则可以保证它们完全兼容。 换句话说,在维护Web应用程序时,您可以在页面中移动块,添加其他块并组合它们。

BEM CSS明确地定义了哪个CSS属于一个界面,因此使用它可以回答诸如“我可以删除这段代码吗?” 和“如果我改变这段代码,会发生什么以及哪些接口部分会受到影响?”的问题。

  1. 为什么要使用block–modifier,而不是将modifier直接和Block同时作用于一个元素上?

也就是说,为什么要避免使用menu__item button active?

    1. 因为同一个dom节点可以既是Block,又是element,所以需要确认一个修饰符是基于block的还是基于element的。如果写成<div class="menu__item button active"></div>,就无法区分menu__itme.active还是button.active了。而加上前缀后,button--active则明确地指出了active仅仅影响的是按钮。
    1. 另一点是CSS的优先级。组合的选择器比单一的类选择器优先级更高。写的时候还要注意计算优先级的问题。但如果使用了前缀式的修饰符,就可以肯定层叠的选择器会Overwrite 修饰符。(这一点在应用了scoped后不用考虑)。
    1. 结构更加分明。比如<div class="block block--mod">,可以清晰地看到Block的结构。但<div class="block mod">却不能起到同样的效果。当全局搜索block--mod时,尤其会感谢这种实践方式。
  1. 如何命名修饰符?能否直接把它的css作为依据命名修饰符?

不能。首先,.block__element--border-bottom-5px看上去奇丑无比,其次,在实践中,如果把5px改成了6px,那么还要连带选择器的名一起改,麻烦。而且,不能保证修饰符会永远只拥有某一个CSS属性,而且永远拥有它。所以,尽量还是选择语义上有意义的名字来命名修饰符。

  1. 类似block__elem1__elem2__elem3的元素嵌套元素怎么命名选择器?

根据BEM方法,块结构应尽量平整,您需要反映块的嵌套DOM结构。所以,对元素嵌套元素,可以都摊平到块级之下的子元素。如:

<div class='block'>
    <div class='block__elem1'>
        <div class='block__elem2'>
            <div class='block__elem3'></div>
            <div class='block__elem4'></div>
        </div>
    </div>
</div>

css结构应该为:

.block {}
.block__elem1 {}
.block__elem2 {}
.block__elem3 {}

这样,每一个element都只依赖于外层的block,可以很轻松地在block内部迁移代码,如下所示。

<div class='block'>
    <div class='block__elem1'>
        <div class='block__elem2'></div>
    </div>
    <div class='block__elem3'></div>
    <div class='block__elem4'></div>
</div>

【笔者言:】我对这一点有异议。假如block__elem2中是flex布局子元素elem3, elem4,那么在迁移在后者时,仍然需要改动其父级元素。建议根据具体情况灵活采用,必要时,可以把内部的element作为一个block,再进行新的嵌套。

  1. bem不支持全局的css重置吗?

BEM不会禁止使用css全局reset,但用BEM的方式重置会更有效。

BEM认为每一个块都是独立的,不依赖于global reset css存在,而且global reset通常是以tag作为选择器,这也违反了规则。相反,bem建议在每个块上进行重置。利用Mixin的方式,假设Menu__item 和 list__item都是li元素,则二者都需要引入li的重置代码。 您可能会担心具有相同重置规则的多个块将在结果代码中重复出现。 但这就是CSS优化器应该为您做的事情。 作为开发人员,您可以独立开发每个块,就好像同一页面上没有其他块一样。

.menu {
    @include reset-list;
}
.menu__item {
    @include reset-list-item;
}

/* ... */

.list {
    @include reset-list;
}
.list__item {
    @include reset-list-item;
}

另外,以这样的方式去reset 全局,还可以避免在引入第三方库的时候,reset代码和第三方库的代码起了冲突。

【笔者言:】这样做的坏处是增加了代码量,需要开发者控制每一个Block的样式,给每一个都加上mixin。从实践上来讲,我不反对全局加入css reset。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值