How to name subelements according to BEM? - html

I have a question regarding BEM (Block Element Modifier) class naming conventions.
What if I need to have 3 nested divs, how should I name the class of the 3rd one?
.one{} //block
.one__two{} //block element
//?
<div class="one">
<div class="one__two">
<!-- How should I rename class "three"? -->
<div class="three"></div>
</div>
</div>
I want to rename ".three" to "one__two__three", or "two__three", but I'm not sure that this is right, because as I understand, according to BEM nesting elements inside of elements is not allowed.

To me, it's about relationships, particularly key-value relationships, so I would approach it that way.
Without exploring contextual naming paradigms, it could be suggested to use one__three.
Alternatively, if one is simply a container for two, then one could be renamed two__container and three renamed to two__item. Of course that doesn't make a whole lot of sense using numbered labels like this, but I hope you can see where it could lead.

Nesting elements is fine; build the structure to your needs. The important thing is to not couple the classnames to your nesting. The classname schema does really only recognize two types of DOM elements: the block itself and the elements of that block; of the latter all are equal regarding the naming schema, no matter how deeply nested in the block.
Here is an example:
<div class="product-card">
<div class="product-card__img-area">
<img class="product-card__product-picture" src="https://example.com/cabulator.jpg"/>
</div>
<div class="product-card__header">
<span class="product-card__main-headline">Encabulator</span>
<span class="product-card__sub-headline">The turbo shmeerf of all Shmoof</span>
</div>
<div class="product-card__text-body">
Lorem ipsum shmeerf of Shmoof quooz bar moof bla bla
</div>
<div class="product-card__footer">
<a class="product-card__cta" href="https://example.com/buy.html">Buy it!</a>
</div>
</div>
And modifiers are added as needed:
<div class="product-card__footer">
<a class="product-card__cta product-card__cta--bargain" href="http://exmpl.com/buy">
Buy it! 50% off for first-time customers!!!!!! OMG!!!!
</a>
</div>

Related

what's the difference between block__element__element and block__element-element in BEM

For example:
<div class="menu">
<div class="menu__item">
<div class="menu__item-title">
</div>
</div>
</div>
There's some solution like menu__title.
But if menu has its own title, then how to recognize menu's title and menu item's title?
The main difference is that block__element__element is not a valid BEM selector. The markup you showed in your question is the CORRECT way of naming your elements.
Create a block
If a section of code might be reused and it doesn't depend on other
page components being implemented.
Create an element
If a section of code can't be used separately without the parent
entity (the block).
The exception is elements that must be divided into smaller parts –
subelements – in order to simplify development. In the BEM
methodology, you can't create elements of elements. In a case like
this, instead of creating an element, you need to create a service
block.
More info in the official documentation: https://en.bem.info/methodology/quick-start/#should-i-create-a-block-or-an-element
If you want to have Menu title, the markup should look something like this:
<div class="menu">
<h2 class="menu__title">..</h2>
<div class="menu__item">
<div class="menu__item-title">
</div>
</div>
</div>
BEM gets a bit tricky when you have "children" of an element. But either use the menu__item-title naming convention or rethink your element, perhaps it can be separated and reused as a Block?

Where to put semantically meaningfull blocks in twitter bootstrap skeleton?

this is my first question, so please, do not judge strictly. The essence is in follows: I imagine block structure of document as a printing press - but very remotely, of course - because press already hase content and semantic, while div's structure of document - only skeleton for it, and both mentioned subjects must be added. An object of concern to me is where I should put this semantic in document skeleton, formed with twitter bootstrap and defining structure - for example:
<div class="container">
<div class="row">
<div class="col-xs-12">
Content, which must be wrapped in some semantically meaningfull element - like, for example - article-preview class
</div>
</div>
</div>
I see two different ways, but dont know, what way is better practice in marking down html documents:
1) Adding semantic class to element, which already have class that forming my document structure - col-xs-12 - or press in my analogy.
<div class="container">
<div class="row">
<div class="col-xs-12 article-preview">
'Content, which must be wrapped in some semantically meaningfull element like, for example - article-preview class'
</div>
</div>
</div>
2) Or adding brand new semanit block under structuring block and putting my content here:
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="article-preview">
Content, which must be wrapped in some semantically meaningfull element - like, for example - article-preview class
</div>
</div>
</div>
</div>
I apologize if the question seems a little stupid to you, but I thinking about it for really long time and from now on can not do anything until it is resolved.
Thank you!
I will prefer the second way. Because bootstrap cols have their own styles and structure, so if you have additional styles or codes try to do like second way.
I think we should keep the bootstrap structure.
Go with the first approach because I feel the second approach will make your code long unnecessarily.
With the first approach as well you can add your custom styles. just add your stylesheet after the bootstrap css.

Unsure of correct BEM style syntax

Let's say I have a product within a collection. Is it appropriate to call the product "feature-collection__product" so it's still an element within the block of "feature-collection" or call it "feature-collection-product" so it becomes it's own block, as it has other elements within it, or something different.
<div class="feature-collection">
<div class="feature-collection__product">
<h2 class="feature-collection__product-title"></h2>
<h2 class="feature-collection__product-price"></h2>
</div>
</div>
OR
<div class="feature-collection">
<div class="feature-collection-product">
<h2 class="feature-collection-product__title"></h2>
<h2 class="feature-collection-product__price"></h2>
</div>
</div>
Most likely the correct answer is both:
<div class="feature-collection">
<div class="feature-collection__product product">
<h2 class="product__title"></h2>
<h2 class="product__price"></h2>
</div>
</div>
The situation when you have different entities on the same DOM node is called mix. In this case it's reasonable to have independent block product and also an element of feature-collection to set some styling for production inside feature-collection.
For more info about mixes please take a look at https://en.bem.info/methodology/key-concepts/#mix and https://en.bem.info/methodology/faq/#mixes

BEM Methology: Elements outside Block

Wonder if that is correct the BEM way. Let's say I have a component/block "box".
<div class="box">
<div class="box__title">Box Title</div>
</div>
This box can be used everywhere. But then for example this box can also be used in a list ex.
<ul>
<li>
<div class="box">
<div class="box__title">Box Title</div>
</div>
</li>
</ul>
It is correct to call the DOM-Classes like that?
<ul class="box__list">
<li class="box__item">
<div class="box">
<div class="box__title">Box Title</div>
</div>
</li>
</ul>
So "box__list" and "box__item" is somehow outside of the block "box".
"box__item" then have some specific stuff.
.box__item {
margin-bottom: 20px;
}
It is "allowed" to do it this way or do I need here completly something different like "box-wrapper__list" and "box-wrapper__item".
Thanks for commenting. :)
Since the elements are outside of the .box then no, it does not make sense to give them these classes.
You have to think what your base components/blocks (think 'building blocks') are.
A component/block is something you can (ideally) place anywhere inside your layout and still have it look/behave the same way, regardles of parent or adjacent elements. The BEM naming convention tries to enforce CSS "modularity" in this sense.
To me it looks like you definitely have a .box component. If you think the list should be another component/block, then name it something else, as you would name a block and not an element.
References:
BEM key concepts
BEM naming conventions
so this makes now more sense - thanks!
<ul class="box-wrapper">
<li class="box-wrapper__item>
<div class="box">
<div class="box__title">Box Title</div>
</div>
</li>
</ul>
I completely understand the thought process behind your question and it is something I have attempted to resolve.
The solution I came up with is stopping using the __wrap naming convention and changing to __inner or content. Essentially a word that best describes the inside, rather than outside as wrap did.
From there we can create an example like so.
This does mean that you will have to change the way you apply classes slightly, but i did find that it helps encapsulate the entire block, rather than having to deal with the ambiguity haing box__wrap on the outside creates.
<div class='box'>
<div class='box__inner'>
<div class='box__head'>head</div>
<div class='box__main'>main</div>
<div class='box__foot'>foot</div>
</div>
</div>
Hopefully my answer helps you in some way,
Yes, #b_ element can be placed outside his block in DOM. Also different blocks & elements can intersections in DOM-tree: https://en.bem.info/forum/43/ (proof from authors of BEM-methodology).
But in your current case you shouldn't use that for positioning, your version with wrappers is correct.

How to name nested elements using BEM and SMACCS

I just started out using BEM and SMACCS for my stylesheets but have run into some trouble as far as naming deeply nested elements in the DOM. Say for instance I have a div called .main-container. Nested inside the first level of the main-container is an additional div which by convention would be named .main-container__article.
<div class="main-container>
<div class="main-container__article></div>
</div>
This is where things get confusing. Inside that article div let's say I have a header followed by a paragraph that has a nested span tags. Do I continue prepending classes with main-container__article as so?
<div class="main-container>
<div class="main-container__article>
<h1 class="main-container__article__header">Heading</h1>
<p class="main-container__article__copy">
<span class="main-container__article__copy__intro-text>Example text.</span>
</p>
</div>
</div>
How far down does the rabbit hole go when it comes to naming parent/child elements? Is there a point where you reset at the second-level element and go from there?
<div class="main-container>
<div class="article>
<h1 class="article__header">Heading</h1>
<p class="article__text">
<span class="article__text__intro-text>This is example text.</span> for a paragraph
</p>
</div>
</div>
BEM naming shouldn't resemble DOM structure because otherwise you won't be able to change markup without changes in CSS.
So for your example I'd make it like this:
<div class="main-container">
<div class="article">
<h1 class="article__header">Heading</h1>
<p class="article__copy">
<span class="article__intro-text">Example text.</span>
</p>
</div>
</div>
There's also a quite powerful thing called mixes, which gives possibility to mix different BEM entities on the same DOM node:
Heading
Example text.
So now you may apply CSS to article block and main-container__article element separately which is very useful when you need to reuse article outside main-container.
.main-container__article__copy__intro-text
definitely doesn't help the readability and maintainability of your stylesheets.
I suggest to break such giant blocks into several smaller blocks. If you do this, you can reuse your styles - in your example you couldn't use the article-block somewhere else.
I would "reset" everytime you can encapsulate a block which can potentially be used in several places in your app/website.