Why does BEM often use two underscores instead of one for modifiers?
Double Underscore is used to define sub element of a block.
i.e:
<nav class="main-nav">
<a class="main-nav__item" href="#">Text</a>
</nav>
Where main-nav
is a block & main-nav__item
is a sub element.
This is done because some people might name their block like this main_nav
which will create confusion with single underscore like this : main_nav_item
Therefore double underscore will clarify stuff like this: main_nav__item
.
Confusion with BEM modifiers
The answer depends on many things.
First, how much logic and appearance have "panel--with-chrome" and "panel--fullscreen" modifiers. And also on what kind this logic is.
If "panel--with-chrome" brings a lot of CSS properties and special JS functionality, I would toggle it in JavaScript when applying "panel--fullscreen".
It also depends on a JavaScript framework you use. In "i-bem.js" which we use at Yandex it's easy to react to appending a modifier:
- A square changes size modifier when after a click
- Reacting on applying a modifier
But if the framework you use doesn't allow to express such a reaction handy, this answer won't work that great for you.
In the other case, when "panel--with-chrome" has not very much properties and doesn't bring any JavaScript logic to a page, I would redefine those CSS properties in "panel--fullscreen" class.
To sum up, there is no universal solution and strict rules to follow. You should decide yourself what will be useful in your case. The decision should depend on many things:
- if you expect your project to be maintained in the future, which solution will be easier to support?
- capabilities of the JavaScript framework you use
- performance stuff
Not in this particular case, but sometimes we measure speed of rendering for variants we are choosing from. - opinion of the other guys, if you work in team
- file structure of your project
We, here at Yandex, store CSS and JavaScript for a block in the same block folder. So, it is not a problem to share logic between CSS and JavaScript since they all are in one place.
But if you keep your JavaScript files separately, this can influence on how comfortable it is to support shared logic.
And so on...
The css BEM concept
First of all naming and structure is a personal thing. Although BEM concept is quite clear. It's a guideline, not a law.
Block:
How many blocks, element or modifiers you have depends on how much you like to reuse your own code. The number of blocks (repeating elements) can be as big or small as what you desire in your own project. My own guidelines are that I only use a block when I know the situation will be repeated.
CSS guidelines for blocks:
- Use class name selector only
- No tag name or ids No dependency on
- other blocks/elements on a page
Element:
The element part of BEM is the block it's "static" content. This can be non-repeated elements like single use heading styles, list styles, graphical elements etc. You never mix an other blocks elements inside it's own block.
Example:
GOOD:
<div class="logo">
<img src="/" class="logo__image">
</div>
BAD:
<div class="logo">
<img src="/" class="branding__logo">
</div>
CSS guidelines for elements
- Use class name selector only
- No tag name or ids
- No dependency on other blocks/elements on a page
Modifier:
Modifiers can be used on blocks and elements depending on how much you want to change the layout when an action happens. This can be highlighting something to completely change the designs look. Or just hide stuff.
CSS guidelines for modifiers
- To alter elements based on a block-level modifier
- To alter elements based on a element modifier
More about BEM can be found here: http://getbem.com/
Example of your code:
<!-- Begin block: topbar --><div class="topbar"> <div class="topbar__content"> <!-- Begin block: user --> <div class="user"> <img class="user__image" src="image/1.jpg" alt="Sample Image"> <div class="user__meta"> <h3 class="user__username user__username--red"> Trump </h3> </div> </div>
<!-- Begin block: nav --> <ul class="nav"> <li class="nav__item nav__item--active"><a class="nav__link">One</a></li> <li class="nav__item"><a class="nav__link">Two</a></li> <li class="nav__item"><a class="nav__link">Three</a></li> </ul> </div></div>
CSS trends with naming class and id with dash underscore?
The double underscore follows the BEM methodology. It is basically a way of naming classes so that later it becomes easy for the user to understand.
The guiding principle behind BEM seems to be "when designing a page, think in terms of reusable widgets". Which is pretty much the standard way you should be writing your semantic HTML.
Learn more about BEM here: BEM methoodology
How to avoid redundant for something like BEM modifiers
This is a typical weakness of BEM. I have search for long, but do not seen any good solution for this so I make my own.
At first I would change the class name. Because UL element should be call 'product-desc-list'. The LI element 'product-desc', as this is in fact exactly a product description for a product.
The more important is the condition of the product. Therefore the selection of the element should be mentioned first. This allows several blocks to be used for one component.
The first is the component definition. The next define possible states like selected, in progress etc.
Here is an example for illustration
// your product in default definition. .product-desc { &--link { text-decoration: underline; }}
// your product in mark state definition.mark { .product-description { &.--link{ font-weight: bold; } }}
<ul class="product-desc-list"> <li class="product-desc"> <a class="product-desc--link">Param1</a> </li> <li class="product-desc mark"> <!--add class .mark--> <a class="product-desc--link">Param1</a> </li></ul>
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:
- 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 anotherbtn
modifier withmargin-top
property set to, let's say40px
. How will you name it? - 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 onpageB
- just addbtn--margin-top
class to yourpageB
markup. - 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.
What is BEM methodology?
BEM is a naming methodology. It stands for Block Element Modifier and it's aim is to facilitate modularity and make styles and classes a lot easier to maintain.
It's not easy to explain it in a reply, but I can give you the basic idea.
So if you're thinking of a menu, then the whole element / component structure would be:
Block: menu
Element: item
Modifier(s): horizontal, vertical
And by following standard BEM conventions, you would write something like this in CSS:
html,body { height: 100%;}
.menu { display: block;}
.menu__item { display: inline-block; line-height: 30px; width: 100px;}
.menu--horizontal { width: 100%; height: 30px;}
.menu--vertical { width: 100px; height: 100%;}
.menu--horizontal .menu__item { border-right: 1px solid #e5e5e5; text-align: center;}
.menu--vertical .menu__item { border-bottom: 1px solid #e5e5e5; text-align: left;}
<div class="menu menu--horizontal"> <div class="menu__item">Home</div> <div class="menu__item">About</div> <div class="menu__item">Contact</div></div>
Related Topics
Using CSS How to Change Only The 2Nd Column of a Table
CSS: Creating Textured Backgrounds
Overlap Notification Badge on Glyph in Bootstrap 3
CSS: Lighten an Element on Hover
Outward Border Radius Like Given in Below Picture..
Selecting Parent Menu Should Show Child Menu
Position Fixed Not Working for Header
CSS: Position Loading Indicator in The Center of The Screen
How to Get Linear Gradient Effect on Mozilla Firefox
Have an Issue with Box-Shadow Inset Bottom Only
Why Calc Is Not Reevaluated When It Is Used for Font-Size
Make Radio Buttons Over Power Background Image
Cannot Get CSS to Work in Itextsharp (5.4.3) When Making Pdf