How to Properly Mix Bootstrap and Bem

BEM: how to make sure rules of the right class (parent block) take precedence?

Let me structure everything I've found out.
There are several approaches:

--------- 1

First of all, you can reorganize rules between blocks so they don't need to be overwritten in the first place.
The main use of mixes is an ability to divide css styles between blocks: external stuff is defined in the parent block and internal in the child block you mix the definitions and you get all element styles needed. BEM just like OOP is based on Single responsibility principle. So if you have one style (color) defined both in parent and child block may be this is the problem on its own and should be changed.

------------------ 1.1

One way to do it is modifiers. Define two different styles of the child block in the child block itself and use them depending on the context (and this is exactly what modifiers are needed for):

<div class="menu">
<div class="social social_color_pink">
<h1>social content in a menu</h1>
</div>
</div>

<div class="social">
<div class="menu menu_color_green">
<h1>a menu in social content</h1>
</div>
</div>

/* menu block definition */
.menu {
background: red;
}

.menu_color_green {
background: green;
}

/* social block definition */
.social {
background: blue;
}

.social_color_pink {
background: pink;
}

------------------ 1.2

Another way to do it is what Stefan Bajić suggested - avoid nesting and make a child block a part of the parent block (an element). This will lead to the code duplication, but will allow you to avoid a lot of dependency issues in the future, and, since you can't separate responsibilities of the parent and child block (who defines the color), it is probably the most natural way.

<div class="menu">
<div class="menu__social">
<h1>social content in a menu</h1>
</div>
</div>

<div class="social">
<div class="social__menu">
<h1>a menu in social content</h1>
</div>
</div>

/* menu block definition */
.menu {
background: red;
}

.menu__social {
background: pink;
}

/* social block definition */
.social {
background: blue;
}

.social__menu {
background: green;
}

--------- 2

You can use context. This is not the best way, since it increases rules specificity and makes HTML less readable, but it is allowed by BEM if nothing else fits.

<div class="menu">
<div class="social">
<h1>social content in a menu</h1>
</div>
</div>

<div class="social">
<div class="menu">
<h1>a menu in social content</h1>
</div>
</div>

/* menu block definition */
.menu {
background: red;
}

.menu .social {
background: pink;
}

/* social block definition */
.social {
background: blue;
}

.social .menu {
background: green;
}

--------- 3

You can combine all the ways above, so it fits your specific task the most. For example, if social block is huge and menu is small, you can duplicate some code of menu and make menu an element of the social block, and add modifier to the social block and use it in the menu block definition so you don't need to duplicate social code.

<div class="menu">
<div class="social_color_pink">
<h1>social content in a menu</h1>
</div>
</div>

<div class="social">
<div class="social__menu">
<h1>a menu in social content</h1>
</div>
</div>

/* menu block definition */
.menu {
background: red;
}

/* social block definition */
.social {
background: blue;
}

.social__menu {
background: green;
}

.social_color_pink {
background: pink;
}

Note, that all solutions result in absence of the mixes. This happens just because there is only one css-rule in the example. And thereby, this doesn't mean that you need to get rid of the mixes, you still can and most probably will need to use mixes, but you must avoid overwriting css styles in them, since then the result will depend on the order in which blocks are defined.

Is that compulsory to apply class name to each and every element in HTML while using BEM (Block,Element, Modifiers) naming convention?

first of all, you should have to follow BEM most of the developer followers BEM only because BEM is good at the naming convention and it's shows the standard naming convention for coding. it depends on you if you want to use BEM you can use or else it's your wish but I suggest you follow BEM it's good in standard.

you can use this

<ul class="nav">
<li class="nav__list"><a href="#" class="nav__link>Home"></a></li>
<li class="nav__list"><a href="#" class="nav__link>Services"></a></li>
</ul>

as well as this one

<ul class="nav">
<li><a href="#" class="nav__link>Home"></a></li>
<li><a href="#" class="nav__link>Services"></a></li>
</ul>

now you don't want to give style to li but in future client say you to give style to li that time what you will do again you will change the code so you have to use this below HTML code

<ul class="nav">
<li class="nav__list"><a href="#" class="nav__link>Home"></a></li>
<li class="nav__list"><a href="#" class="nav__link>Services"></a></li>
</ul>

BEM - How to handle intersection of blocks for grid and content

What you have done isn't incorrect, however I would separate the responsibilities of each component. In my mind a page grid's responsibility is to position the components on the page but should not be required to position elements within the component.

Isolation

The important thing is to always build a component in complete isolation. A component should not have knowledge of its container or rely on it. You should be able to put your component on any page, in any position, and it render correctly. This is one of the important points of this technique.

Single responsibility

From looking at your markup, it appears that your teaser component requires knowledge of the grid to render correctly. I would try to avoid this and include the layout needed for the component in the component itself. It actually looks like the classic media object by Nicole Sullivan, so it is worth taking a look at that. This keeps to the principle that components should have one single responsibility. The grid positions the components on the page and the component positions and styles its elements.

By doing this the teaser component can now be used anywhere, with or without the grid.

BEM - Where to include modifiers for specific pages?

I think you're confusing two concepts here - BEM, which is Naming Convention with the problem of structuring your projects. Both have nothing to do with each other, and I think BEM is not opinionated in terms of structuring your SASS files.

But, there's a couple of questions you ask here:

  1. Is it correct to write the modifier this way? - it is correct if you want to stick to BEM convention, although I would say, the name you picked .btn--margin-top might not be very fortunate in a long term - imagine, you'll want to include another btn modifier with margin-top property set to, let's say 40px. How will you name it?
  2. What is the best way to include a modifier like that only for a specific page? - These CSS classes you are usually not making for specific page. Whole point of BEM is to enable you, to write more modular CSS, and having this in mind you should use these CSS classes, by assigning them to your Blocks/Elements/Modifiers respectively. Trick here is to determine what is a block/element/modifier in your markup. What you'll achieve by this is reusable CSS, so you can quickly apply same css, by adding BEM classes.

    Think in terms of Blocks or Components, NOT pages. You want to use it only on pageB - just add btn--margin-top class to your pageB markup.
  3. Should I include that modifier inside the pageB.scss or .buttons.scss? - it depends on how you structure your project, and I would say that usually, buttons and other UI elements, are in most cases common to whole website/webapp, so there is no need of having them "attached" to specific page (which concept I think you need to drop, if you want to take full advantage of BEM). Besides, whatever suits you will be good for you, and unless you're not working within a team of developers, just stick to your own method, so you'll know in future where to look for things.


Related Topics



Leave a reply



Submit