BEM(Block, Element, Modifier)是由Yandex团队提出的一种前端命名规范。其核心思想是将页面拆分红一个个独立的富有语义的块(blocks),从而使得团队在开发复杂的项目变得高效,而且十分有利于代码复用,即使团队引入新成员,也容易维护。在某种程度上,BEM和OOP是类似的。css
Block是逻辑和功能独立的单元,相似于组件。每一个block包含自身的行为(js)、结构(HTML模板)、表现(css)。block的独立性有利于代码的复用,有利于项目管理。前端
1.block名描述block功能 ("What is it?" — menu or button), 不包含其状态 ("What does it look like?" — red or big)。block能够嵌套、复用。架构
<!-- Correct. The `error` block is semantically meaningful --> <div class="error"></div> <!-- Incorrect. It describes the appearance --> <div class="red-text"></div>
block能够嵌套,而且能够嵌套任意多个blockapp
<!-- `header` block --> <header class="header"> <!-- Nested `logo` block --> <div class="logo"></div> <!-- Nested `search-form` block --> <form class="search-form"></form> </header>
2.block不影响自身布局,也就是说不能设置margin和position属性。ide
3.不能在BEM中使用元素选择器和ID选择器。布局
Element 是block的组成部分,而且不能脱离block使用。code
1.element表示其目的( item, text, etc.), 而不是其状态( red, big, etc.).component
2.Element的命名方式:block-name__element-name. element名字和block名字以双下划线分开。orm
<!-- `search-form` block --> <form class="search-form"> <!-- `input` element in the `search-form` block --> <input class="search-form__input"> <!-- `button` element in the `search-form` block --> <button class="search-form__button">Search</button> </form>
Elements 能够相互嵌套,而且嵌套数量任意。element只能是block的一部分,也就是说element的命名层级不能是block__elem1__elem2。ip
<!-- Correct. The structure of the full element name follows the pattern: `block-name__element-name` --> <form class="search-form"> <div class="search-form__content"> <input class="search-form__input"> <button class="search-form__button">Search</button> </div> </form> <!-- Incorrect. The structure of the full element name doesn't follow the pattern: `block-name__element-name` --> <form class="search-form"> <div class="search-form__content"> <!-- Recommended: `search-form__input` or `search-form__content-input` --> <input class="search-form__content__input"> <!-- Recommended: `search-form__button` or `search-form__content-button` --> <button class="search-form__content__button">Search</button> </div> </form>
block决定了命名空间,确保elements不被其余block影响。
block中的element在css中不须要跟block一块儿使用,而是独立定义规则。这样,当修改bolck的结构时不须要修改css。
<div class="block"> <div class="block__elem1"> <div class="block__elem2"> <div class="block__elem3"></div> </div> </div> </div>
.block {} .block__elem1 {} .block__elem2 {} .block__elem3 {}
The block's structure changes, but the rules for the elements and their names remain the same.
<div class="block"> <div class="block__elem1"> <div class="block__elem2"></div> </div> <div class="block__elem3"></div> </div>
elementy只能做为block的一部分使用,不能独立使用。
<!-- Correct. Elements are located inside the `search-form` block --> <!-- `search-form` block --> <form class="search-form"> <!-- `input` element in the `search-form` block --> <input class="search-form__input"> <!-- `button` element in the `search-form` block --> <button class="search-form__button">Search</button> </form> <!-- Incorrect. Elements are located outside of the context of the `search-form` block --> <!-- `search-form` block --> <form class="search-form"> </form> <!-- `input` element in the `search-form` block --> <input class="search-form__input"> <!-- `button` element in the `search-form` block--> <button class="search-form__button">Search</button>
block不必定含有element。
<!-- `search-form` block --> <div class="search-form"> <!-- `input` block --> <input class="input"> <!-- `button` block --> <button class="button">Search</button> </div>
使用block: If a section of code might be reused and it doesn't depend on other page components being implemented.
建立element:If a section of code can't be used separately without the parent entity (the block).
Modifier定义block和element的外观,状态,或者行为。
Modifier表示其表现("What size?" or "Which theme?" and so on — size_s or theme_islands), 其状态 ("How is it different from the others?" — disabled, focused, etc.) 和其行为 ("How does it behave?" or "How does it respond to the user?" — such as directions_left-top).
modifier命名方法:以单下划线与block 或者 element 隔开。
<!-- The `search-form` block has the `theme` modifier with the value `islands` --> <form class="search-form search-form_theme_islands"> <input class="search-form__input"> <!-- The `button` element has the `size` modifier with the value `m` --> <button class="search-form__button search-form__button_size_m">Search</button> </form>
<!-- You can't use two identical modifiers with different values simultaneously --> <form class="search-form search-form_theme_islands search-form_theme_lite"> <input class="search-form__input"> <button class="search-form__button search-form__button_size_s search-form__button_size_m"> Search </button> </form>
modifier不能单独使用
<!-- Correct. The `search-form` block has the `theme` modifier with the value `islands` --> <form class="search-form search-form_theme_islands"> <input class="search-form__input"> <button class="search-form__button">Search</button> </form> <!-- Incorrect. The modified class `search-form` is missing --> <form class="search-form_theme_islands"> <input class="search-form__input"> <button class="search-form__button">Search</button> </form>
BEM理论也能够应用到工程目录的组织架构中。blocks, elements, 和 modifiers将分开为独立的文件。
Features:
1.A single block corresponds to a single directory.
2.The block and the directory have the same name. For example, the header block is in the header/ directory, and the menu block is in the menu/ directory.
3.A block's implementation is divided into separate technology files. For example, header.css and header.js.
4.The block directory is the root directory for the subdirectories of its elements and modifiers.
5.Names of element directories begin with a double underscore (__). For example, header/__logo/ and menu/__item/.
6.Names of modifier directories begin with a single underscore (_). For example, header/_fixed/ and menu/_theme_islands/.
7.Implementations of elements and modifiers are divided into separate technology files. For example, header__input.js and header_theme_islands.css.
search-form/ # Directory of the search-form __input/ # Subdirectory of the search-form__input search-form__input.css # CSS implementation of the # search-form__input element search-form__input.js # JavaScript implementation of the # search-form__input element __button/ # Subdirectory of the search-form__button # element search-form__button.css search-form__button.js _theme/ # Subdirectory of the search-form_theme # modifier search-form_theme_islands.css # CSS implementation of the search-form block # that has the theme modifier with the value # islands search-form_theme_lite.css # CSS implementation of the search-form block # that has the theme modifier with the value # lite search-form.css # CSS implementation of the search-form block search-form.js # JavaScript implementation of the # search-form block