是什么使BEM优于使用LESS之类的可嵌套样式表语言?


27

我的一位同事在他主持的项目中大力推动CSS 的BEM(块元素修改器)方法,而我只是无法理解是什么使它比我们多年来编写的LESS CSS更好。

他声称“性能更高”,但是我无法想象性能甚至对我们在此代码店中编写的各种Web应用程序有多重要。我们不在这里制作Twitter或Facebook。如果我们使用率最高的应用程序每月点击量超过10000 ,而大多数都低于1000,我会感到非常惊讶。

他声称具有“可读性”和“重用性”,但我认为LESS已经做得更好。而且我认为BEM会为这些超长类名添加许多额外的专用字符,从而严重破坏了标记,从而从根本上降低了可读性。

他声称“嵌套CSS是一种反模式”。“反模式”到底是什么意思,为什么嵌套CSS不好?

他声称“每个人都在使用BEM,因此我们也应该这样做。” 我的计数器是“如果每个人都从桥上跳下来,您会跟随吗?” 但是他仍然对此完全坚决。

有人可以详细解释什么使BEM优于LESS吗?我的同事完全无法说服我,但是我不知道我是否只能选择跟随。我真的很希望能够欣赏BEM,而不是勉强地接受它。


1
BEM和LESS具有不同的用途。我同时使用BEM和LESS。
zzzzBov

4
请注意,BEM并非主要与CSS有关,而是与识别设计中的重复封装模式,并在一个中央位置收集该块所需的所有内容(行为,模板,样式)有关。即使仅限于CSS,BEM仍然是组织样式并可靠地防止名称冲突的好方法。这完全与诸如LESS或SASS之类的预处理器完全独立,后者比纯CSS更具生产力,因为它们提供了宏和变量以及简写符号和各种出色的功能。LESS = win,BEM = win,但是LESS×BEM =win²!
阿蒙2015年

Answers:


29

我的一位同事在他主持的项目中大力推动CSS的BEM(块元素修改器)方法,而我只是无法理解是什么使它比我们多年来编写的LESS CSS更好。

BEM是一种CSS方法。其他包括OOCSS和SMACSS。这些方法用于编写模块化,可扩展,可重用的代码,这些代码可以很好地执行。

LESS是CSS预处理程序。其他包括Sass和Stylus。这些预处理器用于将其各自的源转换为扩展的CSS。

BEM和LESS彼此之间没有“更好”的可比性,它们是服务于不同目的的工具。您不会说螺丝刀比锤子要好,除非考虑使用实用程序来解决特定问题。

他声称“性能更高”。

需要在以下经典CSS样式之间衡量性能:

.widget .header

和BEM风格:

.widget__header

但是一般来说,CSS选择器的性能并不是瓶颈,并且不需要进行优化。

BEM的“性能”通常与开发人员的性能编写代码有关。如果始终如一地正确使用BEM方法,则对于开发人员来说,很容易同时编写不同的模块而不会发生样式冲突。

他声称具有“可读性”和“重用性”。

我不知道我会告诉新开发人员BEM更具可读性。我可以说它为类的含义和结构提供了一些定义明确的指南。

看到像

.foo--bar__baz

告诉我,状态中存在一个foo块,bar其中包含一个baz元素。

我绝对会说BEM比经典模型更可重用。

如果两个开发人员创建了块(foobar),并且两个块都具有标题,则他们可以在不同的上下文中安全地重用其块,而不必担心命名冲突。

这是因为,在经典情况下,这可能会发生冲突,.foo .heading.bar .heading可能会根据具体情况引入需要解决的特异性冲突。

在BEM站点中,这些类将是.foo__heading.bar__heading,它们永远不会冲突。

他声称“嵌套CSS是一种反模式”。“反模式”到底是什么意思,为什么嵌套CSS不好?

“反模式”是一种编码模式,对于没有经验的开发人员而言,它比更合适的替代方法更容易学习和使用。

至于嵌套CSS不好的原因:嵌套可以提高选择器的特异性。特异性越高,花费的精力越多。没有经验的开发人员经常担心他们的CSS可能会影响多个页面,因此他们使用如下选择器:

#something .lorem .ipsum .dolor ul.sit li.amet a.more

当有经验的开发人员担心他们的CSS 可能不会影响多个页面时,他们使用如下选择器:

.more

他声称“每个人都在使用BEM,因此我们也应该这样做。”

那是一个流行的谬误,因此请忽略它作为一个不好的论点。不要陷入谬论谬误的陷阱,因为支持BEM的错误论据并不能成为认为BEM不好的理由。

有人可以详细解释什么使BEM优于LESS吗?

我之前已经讲过,BEM和LESS不可比。苹果和橘子等

我的同事完全无法说服我,但是我不知道我是否只能选择跟随。

我建议看一下OOCSS,SMACSS和BEM,并权衡每种方法的优缺点... 作为一个团队。我之所以使用BEM,是因为我喜欢BEM格式上的严格性,并且不介意丑陋的选择器,但是我无法告诉您什么适合您或您的团队。不要让一个直率的人来主持这个节目。如果您对BEM不满意,请注意,还有其他替代方案可能会更容易为您的团队提供支持。您可能需要与同事捍卫自己的职位,但长期而言,这可能会对您的项目成果产生积极影响。

我真的很希望能够欣赏BEM,而不是勉强地接受它。

我在StackOverflow上写了一个答案,描述了BEM的工作方式。要了解的重要一点是,理想的选择器应具有的特殊性,0-0-1-0以便易于覆盖和扩展。

选择使用BEM并不意味着您需要放弃LESS!您仍然可以使用变量,仍可以使用@imports,当然可以继续使用嵌套。不同之处在于您希望呈现的输出成为单个类,而不是后代链。

你可能曾经在哪里

.widget {
    .heading {
        ...
    }
}

使用BEM,您可以使用:

.widget {
    &__heading {
        ...
    }
}

此外,由于BEM围绕各个块进行,因此您可以轻松地将代码分成单独的文件。widget.less将包含该.widget块的样式,而component.less将包含该.component块的样式。尽管您可能仍希望使用源映射,这使查找任何特定类的源变得更加容易。


4
@CoreDumpError,问题是当您开始在模块内嵌套模块时。“每个开发人员只能将其特定的窗口小部件的代码嵌套得更深一层”是不正确的,每个开发人员都必须将其特定的窗口小部件的代码嵌套得越来越深,否则命名冲突会以通常无意的方式级联。避免命名冲突的唯一方法是使用某种命名空间,而BEM提供了一种简便的方法来一致地命名空间类。
zzzzBov

3
@CoreDumpError,请考虑以下示例。没有BEM的作者需要花费更多的精力来验证可能在其模块中添加的每个模块的每个组合。使用BEM的作者没有。
zzzzBov 2015年

1
@CoreDumpError,肯定是。我发现BEM易于培训新开发人员,并且使代码审查变得容易,但是SMACSS和OOCSS是不错的选择。我强烈建议您研究这些选项。我会说我使用BEM进行自己的开发,这样我就不会与自己,特别是与未来的我发生冲突,因为我这个愚蠢的人会忘记事情。
zzzzBov

1
我发现BEM在涉及任何复杂性的任何项目中都非常出色。您可以拥有一个网站,该网站位于WordPress上,并且仅使用Javascript来触发滚动事件,但仍然像CSS中的Web应用程序一样复杂。重要的是不要落入以为“我的网站并不复杂”的陷阱,仅仅是因为它的大部分工作纯粹是在视觉领域(就像许多营销网站一样)
Toni Leigh

1
@CoreDumpError我以前的大多数项目都是个人尝试,而我靠自己的能力达到了BEM的大部分:特异性和独特的选择器。维护代码库是一个巨大的问题,对于BEM来说,这变得尤为明显。代码是维护。建造东西很容易。保持完美的模式非常困难,尤其是在离开代码库几个月之后。特异性问题会随着时间的流逝而加剧。好处适用于任何规模的IMO团队!
富田

8

编辑2017

如果您要在2017年阅读本文档,那么Shadow DOM和shadow DOM polyfills以及组件可以解决所有这些问题,同时使您的代码紧凑,紧凑且模块化。不要在未开发项目IMO上使用BEM。

除了BEM以外,我们还有ViewEncapsulation,Polymer,StyledJSX,SASS模块,Styled Components等工具。

如果您没有面向组件的体系结构,请考虑使用BEM。如果您有支持的旧代码;或者,如果您不愿手动进行任何操作而又无须工具,那该死了。


BEM使您的样式独立于DOM嵌套。它通过为您可能要设置样式的大元素类属性提供每个元素,该属性在页面上可能是唯一的。然后,大多数样式都在类上完成。

这使您的代码更具模块化,因为不再考虑嵌套,而以大量的冗长为代价。

没有BEM

没有BEM,我们可能会这样写:

<div class="widget">
  <a>Hello!</a>
  <ul>...</ul>
</div>

标准CSS样式可能如下所示:

.widget {
  border: 1px solid red;
}

.widget a {
  color: green;
}

与SASS相同的东西看起来像这样:

.widget {
  border: 1px solid red;
  a {
    color: green;
  }
}

如果您是一个小团队,每个人都可以按照高标准编写CSS,并且该项目足够小以至于您可以完全了解它,那么这是一个很好且合理的解决方案。

使用BEM

但是,如果您的代码变得更大,并且您拥有庞大的混合能力团队,那么这可能不是一个简单的解决方案。例如,如果要在另一个小部件中使用绿色锚点,该怎么办。因此,我们将锚定为模块化,并消除了后代选择器。

现在,我们的HTML更加冗长:

<div class="widget">
  <a class="widget__anchor">Hello!</a>
  <ul class="widget__ul">...</ul>
</div>

我们的CSS没有子代选择器:

.widget {
  border: 1px solid red;
}

.widget__anchor {
  color: green;
}

但是我们现在可以这样做:

<div class="widget__2">
  <a class="widget__anchor">Hello!</a>
</div>

widget__anchor是模块化的。该页面上不太可能存在.widget__anchor的另一个定义。

权衡:

BEM:

  • 为您提供更多的模块化代码。您可以孤立地拍摄任何作品。
  • 允许任何人编写CSS。您无需了解主样式和自定义替代。在大型团队中,这很好。
  • 消除任何特异性问题。
  • 明显更冗长。

标准CSS(依赖于后代选择器的使用):

  • 意味着您的样式取决于上下文。
  • 需要了解级联。一次放置的代码可能会影响其他地方的代码。在一个小团队中,这是一件好事。
  • 可能会遇到新手开发人员难以调试的特定性问题。
  • 明显更紧。

第三种方式-真实组件。

如果您使用类似React,Angular 2或任何其他现代前端框架字之类的东西,那么您将有另一种解决方案。您可以使用工具强制执行封装。

这个例子使用了React和StyledJSX,但是有很多选择。这是一个小部件:

const Widget = () => 
  <div>
    <a>Hello</a>
  </div>
  <style jsx>
    div {border:red }
    a { background: pink }
  </style>

然后,您将像这样使用新的小部件:

<Widget />

小部件中声明的所有样式都将被封装,并且不适用于组件外部的元素。我们可以自由地直接对div和进行样式设置,a而不必担心会意外对页面上的其他样式进行样式设置。


1
我不喜欢任何一方的优点和缺点。
阿德里安·莫伊萨

我认为说“这样编写代码,使不懂级联的人可以理解它”确实让我有些伤心。这就像在说“我写我的代码时没有任何数组,因为团队中的一名初级成员不了解数组是如何工作的”。我个人更喜欢简洁的方法,该方法支持级联样式表的自然级联方面。
Matt Fletcher

@MattFletcher-我认为这与项目规模有关。级联本质上是全局的。设置值,然后遍历树并向下遍历。如果您有一个具有完全可见性的较小项目,那很好,但是在较大项目上,它将变得很脆弱。人们变得害怕改变事物,因为更高的级联改变会破坏其他地方的随机事物。实际上,在大型项目中组件封装确实很棒。一切正常。
superluminary

2

没有办法是完美的。恕我直言,我们应该获得每种方法(BEM,SMACSS,OOCSS,DRY)中最好的部分。使用SMACSS在CSS中组织文件夹结构-特别是用于定义整个CSS的逻辑级别细分。尝试创建您的实用程序库,或者可能是常用的修饰符库,有时会与基于BEM的类结合使用。面向组件的OOCSS。而BEM为小型组件或子组件。这样一来,您就可以分配复杂性,并可以自由地在大型团队中工作。

在不了解其本质的情况下使用任何东西都将导致不良后果。

虽然BEM对于较大的团队是不错的方法,但它也有一些缺点。1,有时导致大型HTML结构中的名称很长。导致CSS文件很大。2.对于嵌套2-3级以上的html,定义名称变得很麻烦。

如果我们考虑组件结构以及一组非常基本的基本样式,就可以轻松解决冲突解决方案。它仅是两级继承。组件内的每个元素要么具有全局样式规则,要么特定于该组件。这是较容易的选择之一。


极好的论点。开发人员应该能够自己思考并分析问题的范围。盲目地遵循方法仍然会给您带来麻烦。我的同事们根本不考虑页面上所做更改的影响,无论我们采用哪种方法,事情都会及时解决。我正在努力提高团队中的CSS意识水平。带有本地样式和全局样式的嵌套SASS足以使项目保持简洁易读。
阿德里安·莫伊萨
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.