BEM block, naming & nesting
There are a number of variants on how to write BEM classes, so be aware that are multiple competing standards. It started as a set of loose guidelines. Since posting this answer, Yandex has significantly overhauled their official standard (it's quite an improvement). The version of BEM I use is based heavily from an article by Nicolas Gallagher.
At this point I use "Atomic OOBEMITLESS", which is really just a way of saying that classes are modular and namespaced, selectors have low specificity, and states may be toggled with classes which allows CSS to be scaled, on top of a CSS preprocessor to make the code more concise and expressive.
All that said, I will be using the following BEM standard:
- hyphenated class names as blocks:
foo-bar
- block name followed by
__
followed by hyphenated class names for elements:foo-bar__fizz-buzz
- block or element names followed by
--
followed by hyphenated class names for modifiers:foo-bar--baz
,foo-bar--baz__fizz-buzz
,foo-bar__fizz-buzz--qux
BEM short form: block-name__element-name--modifier-name
You have three different blocks in your examples:
sidebar
, which has asidebar__nav
elementcontent
, which has acontent__nav
elementnav
, which hasnav__item
andnav__link
elements
The sidebar
and content
blocks appear to be variations on the same block, and could be represented as .region.region--sidebar
and .region.region--content
.
The nav
block is implicit on the ul
element, and you should make it explicit:
<ul class="nav"><!-- could be content__nav or sidebar__nav as well if you choose -->
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
Once you've specified that the ul
element is a nav
block, it makes sense to have the nav
block be modified:
<ul class="nav nav--content">
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
</ul>
Once you've set up the CSS classes, styling all nav__item
elements is simply:
.nav__item {
...styles here...
}
and overriding those styles for the content nav__item
elements is:
.nav--content__item {
...styles here...
}
BEM naming convention for nested tiny parts
BEM is a methodology about reusable blocks. If you see a visual pattern that is repeated in the UI, then you should consider to see it as a block, not an element. Elements are the block details.
For your wireframe, I suggest two blocks: the lineup
block is responsible for the global layout:
<ul class="lineup">
<li class="lineup__item"></li>
<li class="lineup__item"></li>
…
</ul>
In each <li>
, there is an instance of a product
block:
<article class="product">
<img class="product__img">
<h3 class="product__title">…</h3>
<div class="product__text">…</div>
</article>
If you want to keep your current HTML structure, then you have a mix on <li>
markups:
<ul class="lineup">
<li class="lineup__item product">
<img class="product__img">
<h3 class="product__title">…</h3>
<div class="product__text">…</div>
</li>
…
</ul>
Here the lineup__item
CSS class is responsible for positioning the child block product
in the parent block linup
. A block should not position by itself (it wouldn't be reusable).
Then, your element product__title
has two children en
and non-en
. With BEM, an element cannot be parent of other elements. But it can nest brother elements. You can do:
<h3 class="product__title">
<span class="product__title-en"></span>
<span class="product__title-non-en"></span>
</h3>
In the BEM tree, title
, title-en
, title-non-en
are all child elements of the product
block. It is the light solution.
But maybe you'll realize that this kind of dual titles is a visual pattern used outside the product
block, or maybe just for clarity, you can decide to make a dual-title
block for that.
<h3 class="product__title dual-title">
<span class="dual-title__en"></span>
<span class="dual-title__non-en"></span>
</h3>
Here the CSS class product__title
is responsible for positioning the child block dual-title
in the parent block product
.
CSS BEM, nest child elements or create new block?
“BEM methodology doesn’t recommend to use elements within elements in class names. You don’t need to resemble DOM structure in naming. Having one level structure makes refactoring much easier.” -Vladimir Grinenko, Yandex
Refer to the Grandchild Solution:
Instead of darpi-form__field__label
you should just use darpi-form__label
.
BEM: Nested Blocks, what is the best approach?
You want to have clean reusable blocks. Ask yourself which part you might want to reuse.
Multi level nesting of blocks are frowned upon. And that's for a good reason. In case of reusability there should only be one block as root reference. Everything below that one block is, from a bem syntactic point of view, simply an element of that block. Not a sub-block, not a sub element, but only an element.
So, BEM doesn't care about your HTML structure. It's much more a question of what purpose a block or an element has.
I can't really tell from your example what the purpose of your nested footers might be, but it looks to me as if you consider the role attribute of your outer footer element as part of BEM-naming. But it's not. Keep in mind the idea of separation of concerns. role="footer" is HTML semantic. You should not use it as BEM naming reference because you might want to change that HTML attribute one day and then your BEM semantic would go up in smoke.
So, here's what I would do.
Let's say you want your outer footer to be the reusable element then you might want to name your classes like this (just as an example):
<footer class="footer" role="footer">
<footer class="footer__textbox">
<div class="footer__text footer__text--left"> <!-- left as modifier -->
<div class="footer__text footer__text--right"> <!-- right as modifier -->
</footer>
</footer>
Now you can take your footer and use it in any appropriate section of the page and anyone reading your code can get grasp an idea about the purpose of this css structure.
Bem nested naming
You don't need any prefixes for card
block but I'd rather go with something like this:
.control
.control__panel
.control__results
.card
.card__title
.card__body
So there's two blocks: control
with card
inside of it.control
has two elements: panel
and results
. And card
has title
and body
.
If you want to connect card
with control
you may add a mix with control__card
so the final markup will be:
.control
.control__panel
.control__results
.card .control__card
.card__title
.card__body
For more info about such approach please see https://en.bem.info/methodology/css/#mixes
naming BEM sub blocks
I think the logo, main header, and phone fit in the definition of block
which is given in BEM website as:
A block is an independent entity, a "building block" of an application. A block can be either simple or compound (containing other blocks).
What you have got is three simple blocks (logo, main_nav, and phone) within a compound block (site_header). It is actually very similar to the HEAD compound block that is given as an example on the BEM methodology definitions page.
So I would write it this way:
<div class="logo">
<a class="logo__link">
<img class="logo__image">
</a>
</div>
<nav class="main_nav">
<ul>
<li class="main_nav__item">
<a class="main_nav__link">Home</a>
</li>
<li class="main_nav__item">
<a class="main_nav__link">About Us</a>
</li>
<li class="main_nav__item">
<a class="main_nav__link">Contact Us</a>
</li>
</ul>
</nav>
<div class="phone">
<p class="phone__number">
555.555.5555
</p>
</div>
If you think that "logo" is way too generic as a name and wouldn't represent the other types of logos in the project feel free to give it a different name like "company_logo".
In terms of styling, BEM suggests using block modifiers and element modifiers to represent their different styles. For example if you wanted to have your phone number in bold, then you can create a class modifier for it in CSS and apply it to your HTML as follows:
.phone__number--bold {
font-weight: bold;
}
<div class="phone">
<p class="phone__number phone__number--bold">
555.555.5555
</p>
</div>
Modifiers are the preferred way over styling blocks within other blocks. So don't do this:
.site_header .phone__number {
font-weight: bold;
}
I think there is one exception to this which is when you want to give "location-dependant styles" to the block inside. Let's say that you want to give a left margin to the "logo" block. Instead of creating a modifier like:
.logo--push_20 {
margin-left: 20px;
}
it is better to follow OOCSS second principle - Separate container and content - and leave the job to the container:
.site_header .logo {
margin-left: 20px;
}
Naming convention nested blocks and elements in BEM in CSS
BEM is very ease to learn and implement. Also there is some point keep in your mind.
1. You should use short name for parent class if you want use modifier later something like this.
<div class="t-topic"><div>
2. choose simple Element name to you can remember it later. like (unit, thumb, list, item).
This your code.
<div class="t-topics">
<div class="container">
<div class="row">
<div class="col-2">
<a class="t-topics__link" href="#">
<img class="t-topics__image" src=""/>
<span class="t-topic__span">Lorem ipsum</span>
</a>
</div>
<div class="col-2">
<a class="t-topics__link" href="#">
<img class="t-topics__image" src=""/>
<span class="t-topic__span">Lorem ipsum</span>
</a>
</div>
</div>
</div>
There Also other way if you want nested block like this
<div class="t-topics">
<div class="container">
<div class="row">
<div class="col-2">
<a class="link t-topics__link" href="#">
<img class="link__image" src=""/>
<img class="link__image link__image--other" src=""/> // Different image
<span class="link__span">Lorem ipsum</span>
</a>
</div>
<div class="col-2">
<a class="t-topics__link" href="#">
<img class="t-topics__image" src=""/>
<span class="t-topic__span">Lorem ipsum</span>
</a>
</div>
</div>
</div>
You can learn more about BEM from this links.
https://www.toptal.com/css/introduction-to-bem-methodology.
https://www.smashingmagazine.com/2012/04/a-new-front-end-methodology-bem/
Guidelines for how deep to nest BEM style class names
You should completely flatten your block structure to use BEM convention.
It might look something like this:
.abc {}
.abc__main {}
.card {}
.card__item {}
.card__heading {}
.card__icon {}
.card__text {}
.card__text--em {}
.card__text--green {}
It's in the FAQ here: http://getbem.com/faq/#css-nested-elements
Related Topics
CSS 100% Height with Absolute Positioning Top 0 Bottom 0
How Position Absolute and Fixed Block Elements Get Their Dimension
How to Replace Radio Buttons with Images
How (And Why) to Use Display: Table-Cell (CSS)
Angular Performance: Dom Event Causes Unnecessary Function Calls
How to Center The <Legend> Element - What to Use Instead of Align:Center Attribute
How to Use an Image from My Local File System as Background in HTML
Style a Checkbox in Firefox - Remove Check and Border
Why Does Perspective Changes Fixed Position in CSS
Why Using Absolute Position Causes The Div to Be on Top
Accessibility: Recommended Alt-Text Convention for Svg and Mathml
How to Write Content That Screen Readers Will Ignore
Youtube Iframe Embed - Full Screen
How Organize Pagination with a Large Number of Pages in Django Project