EM
Meet.js Poznań #32
Who am I?
const me = Object.freeze({
name: 'Sergey Bolshov',
position: 'FrontEnd Developer',
workPlace: 'Apptension',
email 'bolszow@gmail.com',
githubUsername: '@bigsergey',
country: 'Kazakhstan'
});
What is BEM?
Block Element Modifer - is a component-based approach to web development. The idea behind it is to divide the user interface into independent blocks.
Created by Yandex in 2005
Code that is hard to maintain
<!-- How those classes are related? -->
<div class="media user premium">
<img class="img photo avatar" src="" />
<p class="body info">…</p>
</div>
... and code that is easy to maintain
<!-- It's BEM baby -->
<div class="media user user--premium">
<img class="media__img user__photo avatar" src="" />
<p class="media__body user__info">…</p>
</div>
What is wrong with CSS?
- global selectors
- no explicit dependenciеs
- selectors specificity / priority
- complex selectors
- isolation from parent element / cascade
- isolation from global selectors
- code duplication
- removing unused code
- …
BEM Block
Source: https://en.bem.info/methodology/
BEM Element
Source: https://en.bem.info/methodology/
BEM Modifier
Source: https://en.bem.info/methodology/
Yandex naming convention
.{block-name}
.{block-name}__{element-name}
.{block}_{block-modifier}
.{block-name}__{element-name}_{element-modifier}
<div class="menu menu--theme-xmas">
<span class="menu__item"></span>
<span class="menu__item menu__item--hidden"></span>
</div>
Harry Roberts' style
<div class="block-name__element-name--state_active">
BEM EXAMPLE
DOM-Tree
BEM-Tree
HTML
<ul>
<li>
<a>
<span></span>
</a>
</li>
</ul>
CSS
.ul {}
.ul > li {}
.ul > li > a {}
.ul > li > a > span {}
HTML
<ul class="menu">
<li class="menu__item">
<a class="menu__link">
<span class="menu__text"></span>
</a>
</li>
</ul>
CSS
.menu {}
.menu__item {}
.menu__link {}
.menu__text {}
BEMMix
- Combine the behavior and styles of multiple entities without duplicating code.
- Create semantically new UI components based on existing ones.
<!-- several blocks -->
<div class="menu head-menu"></div>
<!-- a block and an element of another block -->
<div class="menu">
<div class="link menu__link"></div>
</div>
<!-- block with modifiers -->
<div class="link link--active link--theme-xmas"></div>
BEM: The Good Parts
.signup__account__user-name__input { ... }
How to fix block__elem__elem?
BEFORE
AFTER
<div class="block">
<div class="block__elem1">
<div class="block__elem1__elem2"></div>
</div>
</div>
<div class="block1">
<div class="block1__elem1 block2">
<div class="block2__elem2"></div>
</div>
</div>
<!-- OR -->
<div class="block1">
<div class="block1__elem1">
<div class="block1__elem2"></div>
</div>
</div>
CSS styles
HTML
CSS
<div class="block">
<div class="block__element">
</div>
</div>
.block .block__element {
...
}
Wrong CSS styles
HTML
CSS
<div class="block">
<div class="block__element">
</div>
</div>
/* bad */
.block .block__element {
...
}
/* good */
.block {
...
}
.block__element {
...
}
Why the modifier CSS classes are not represented as a combined selector?
<div class="block mod">...</div>
or
<div class="block block--mod">...</div>
- Namespace - .block.mod or ul li {} ul > li > ul >li
- Mixes - <div class="menu__item button active">
- Code searching - find active or button--active
Avoid Sass' @extend
<div class="menu menu--hidden">...</div>
or
<div class="menu--hidden">...</div>
/* good */
.menu,
.menu--hidden,
.menu--other-modifier {
// base styles
}
/* better */
.menu {
// base styles
}
.menu--hidden {...}
.menu--other-modifier {...}
-
CSS (clean)
-
Descriptive
-
Flexibility and consistency (same styles applied twice for two modifiers)
Can I create a global modifier applicable to any block?
visible, invisible, opacity50 and etc.
CSS
.hidden { display: none }
/* ... */
.block { display: block }
HTML
<div class="block hidden">
you still see me
</div>
<div class="block mod1 mod2">
you have no control over the block
</div>
Can I create a global modifier applicable to any block?
.menu {
@include reset-list;
}
.menu__item {
@include reset-list-item;
}
...
.list {
@include reset-list;
}
.list__item {
@include reset-list-item;
}
How to reuse a button?
<form class="search-form">
<input type="text" class="input">
<button type="submit" class="search-form__button button button_theme_lite">
Search
</button>
</form>
<form class="auth">
<input type="text" class="login">
<input type="password" class="password">
<button type="submit" class="auth__button button button_theme_dark">
Sign in
</button>
</form>
.search-form__button {
margin: 30px;
}
.auth__button {
margin: 40px;
}
.button_theme_lite {
background: #fff;
}
.button_theme_dark {
background: #000;
}
OOCSS
- Separate structure and skin
- Separate container and content
SMACSS
- Base
- Layout (.layout-)
- Module (.example)
- State (.example.is-active)
- Theme
SUIT CSS
- u-utilityName
- ComponentName
- ComponentName--modifierName
- ComponentName-descendentName
- ComponentName.is-stateOfComponent
Atomic
- quarks (.links)
- atoms (.buttons)
- molecules (.banner)
- utilities (.reset)
BEM
- block
- block__element
- block--modifier
Benefits
- Modularity - independent blocks.
- Reusability - composing independent blocks in a different way and reusing them.
- Structure - simple and understandable structure in your CSS code.
Full stack BEM
- ENB
- bemhint
- bem-tools
- bemmet
- bem-sdk
- BEMJSON
- BEMHTML
- BEMTREE
- i-bem.js
- gemini
- Angular-BEM
- postcss-bem-linter (SUIT and BEM)
Thank You! Stay BEMed!
Source: The Principles Of OOCSS
Useful resources
BEM Meet.js
By Sergey Bolshov
BEM Meet.js
- 1,164