这篇文章原本是一篇读书笔记,更准确地说,是读文笔记,记录于 2020 年 8 月 29 日,今天重温,决定发布在博客。以下是笔记原文,当然有改动啦。
在一篇文章看到三种 CSS 命名及组织方法论:BEM、ITCSS、OOCSS,第一次了解到 BEM。
后来写小程序,发现小程序官方样式库 WeUI 也采用 BEM 命名规范,了解 BEM 对使用 WeUI 帮助很大,不了解 BEM 会觉得 WeUI 的命名规则很乱很难理解。
BEM 是 block,element,modifier 的缩写。block 就是页面中你看到的可以独立拿出来的一个东西,例如一个按钮,一个表格等,虽然 block 和 block 之间可能有嵌套关系,但在语义上它们是平等的(semantically they remain equal)。element 本身没有意义,只有把它放在某个 block 下理解才有意义,例如某个 list item。而 modifier 是用来改变一个 block 或 element 状态的标签,可以视为这个 element 或 block 的一个变体,或某个条件下的另一个版本,例如大字体版本的标题、小字体版本的标题等。
BEM 的命名规则主要有两种:.block__element--modifier
或 .block--modifier
,也可以省略 modifier:.block__element
或 .block
,有些人还会这样写:.block--modifier__element
。
之所以用两个而不是一个下划线或连字符区分 block、element、modifier,是因为有时候 block、element、modifier 的命名本身就需要用到单个下划线或连字符。
BEM 是俄罗斯 Yandex 公司的作品,Yandex 前员工在一篇文章建议用 b-
前缀表示 block,用 __
连接 block 和 element,例如 .b-text-input__text-field
表示 text-input 这个 block 下的 text-field 元素,这里没有 modifier,你可以看到单个连字符被用于某个 BEM 元素自身的命名。添加 modifier 的方式,他建议在 block 或 element 后添加一个下划线加 modifier 名称,例如 .b-select__option_selected
中的 selected
就是 modifier。
b-
同时充当 namespace 角色。
简单概括:
b-
前缀) 和 elment,一个下划线区分 modifier 和 block(或 element)无论是方案一还是方案二,都把单个连字符用在 BEM 某个元素自身的命名。
2023-03-22 补充:腾讯 TDesign 团队的 BEM 规范说明:
BEM 使用分隔符将类名区隔成三个部分:
[prefix]-[block]__[element]--[modifier]
prefix:全局的前缀,这里指代表 tdesign 的前缀,也就是 t-
Block(块) :组件的最外层父元素,这个类包含最通用和可重用的功能。
Element(元素) :组件内可包含一个或多个元素,元素为块添加了新功能。无需重置任何属性。
Modifier(修饰类) :块或元素都可以通过修饰词来表示为变体。
BEM 的好处是,过一段时间当你重新看回你写的 CSS 时,看名称你就知道它是什么意思,通过看 html 中的 CSS 名称,可以知道这个部分是不是一个独立的 component,还是 component 的子元素等.
给一个组件写 CSS,可以只给它起一个属性名,然后把该组件的所有样式写在这个属性名下,但这可能不是最佳做法。如果这个组件的样式可以划分为 block,element,modifier,那可以给这个组件赋予多个属性名,然后把样式分类放在各属性名下,也许这样更易于理解和维护。
有时候不需要用 BEM 模式去命名 CSS,例如一个 logo 图片,可能不属于任何其他 block,没有子元素,也没有其他变体,此时没必要用 BEM。不是所有位于 block 中的子元素都需要 BEM 命名,它可能只是碰巧位于这个 block.
为什么用 CSS 组织页面元素?为什么不是用 HTML?HTML 标签虽然是语义化的,但 HTML was designed for structured text, not web apps。我们可以通过 CSS 属性名去重新组织 HTML,给这些 HTML 一个新的结构,所以一个 button 可以用 button 或 div 等元素去写,只要我们给它起一个好的 CSS 属性。
BEM 方法论建议尽量只用 Class 选择器定义样式,不要混合使用 Class、ID、Tag 等多类选择器,必要时,不要用 CSS 嵌套,因为慢,250ms 是被视为 instant 的极限。
BEM 当然也有缺点,如何更好地使用 BEM,以及如何避免 BEM 的缺点,可以参考这两篇文章:
CSS 方法论是一种规矩,无规矩不成方圆,有了规矩,遵循了规矩,就方便后续维护。BEM 是一种方法论,具体如何实践这个方法论没有统一标准。