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