Note: I use the word Module which in BEM is called a Block. Also using modified BEM naming convention BLOCK__ELEMENT--MODIFIER, please use that in your answer as well.
Suppose I have a .btn module that looks something like this:
.btn {
background: red;
text-align: center;
font-family: Arial;
i {
width:15px;
height:15px;
}
}
And I need to create a .popup-dialog module with a .btn inside of it:
.popup-dialog {
...
.btn {
position: absolute;
top: 10px;
right: 10px;
}
}
In SMACSS and BEM, how should you handle positioning a module inside of a module?
In your answer, please identify the correct solution, and analyze the following approaches as well: (note that all of the examples below build upon or modify the above CSS)
Approach 1
[ override the original .btn class inside of .popup-dialog ]
CSS:
.popup-dialog {
...
.btn { // override the original .btn class
position: absolute;
top: 10px;
right: 10px;
}
}
Markup:
<div class="popup-dialog">
...
<button class="btn"><i class="close-ico"></i> close</btn>
</div>
Approach 2
[ add a subclass inside of .popup-dialog ]
CSS:
.popup-dialog {
...
.popup-dialog__btn {
position: absolute;
top: 10px;
right: 10px;
}
}
Markup:
<div class="popup-dialog">
...
<button class="btn popup-dialog__btn"><i class="close-ico"></i> close</btn>
</div>
Approach 3
[ subclass .btn with a modifier ]
CSS:
.btn--dialog-close {
position: absolute;
top: 10px;
right: 10px;
}
Markup:
<div class="popup-dialog">
...
<button class="btn btn--dialog-close"><i class="close-ico"></i> close</btn>
</div>
Approach 4
[ subclass .btn with a layout class ]
CSS:
.l-dialog-btn { // layout
position: absolute;
top: 10px;
right: 10px;
}
Markup:
<div class="popup-dialog">
...
<button class="btn l-dialog-btn"><i class="close-ico"></i> close</btn>
</div>
Having struggled with the issue in a recent large-scale project myself, I applaud you to bringing this to attention on SO.
I'm afraid that there's not a single 'correct' solution to the problem, and it's going to be somewhat opinion-based. However I will try to be as objective as possible and give some insight in regard to your four approaches on what worked for my team and what didn't.
Also I'm going the assume the following:
You're familiar with the SMACCS approach (you read the book and implemented it in at least one project).
You're using only the (modified) BEM naming convention for your CSS classnames, but not the rest of BEM methodology development stack.
Approach 1
This is clearly the worst approach and has several flaws:
It creates a tight coupling between .popup-dialog and .btn by using context-based selectors.
You are likely going to run into specificity issues in the future, supposed you will add additional .btn elements in the .popup-dialog in the future.
If somehow you'd need to use classnames unaltered, I'd suggest at least reducing the depth of applicability by using direct child selectors.
CSS:
.popup-dialog {...}
.popup-dialog > .btn {
position: absolute;
top: 10px;
right: 10px;
}
Approach 2
This is actually quite close to our solution. We set the following rule in our project and it proved to be robust: "A module must not have outer layout, but may layout its submodules". This is in heavily inspired by #necolas conventions from the SUITCSS framework. Note: We're using the concept, not the syntax.
https://github.com/suitcss/suit/blob/master/doc/components.md#styling-dependencies
We opted for the second option here and wrap submodules in additional container elements. Yes, it creates more markup, but has the benefit that we can still apply layout when using 3rd party content where we can't control the HTML (embeds from other sites, etc.).
CSS:
.popup-dialog {...}
.popup-dialog__wrap-btn {
position: absolute;
top: 10px;
right: 10px;
}
HTML:
<div class="popup-dialog">
...
<div class="popup-dialog__wrap-btn">
<button class="btn"><i class="close-ico"></i> close</button>
</div>
</div>
Approach 3
This might seem clean (extends instead of overwrites), but isn't. It mixes layout with module styles. Having layout styles on .btn--dialog-close will not be useful in the future if you have another module that needs to have a different layout for a close button.
Approach 4
This is essentially the same as approach 3 but with different syntax. A layout class must not know about the content it lays out. Also I'm not to keen on the l-prefix syntax suggested in the book. From my experience it creates more confusion than it helps. Our team dropped it completely and we just treat everything as modules. However If I needed to stick with it, I'd try to abstract the layout completely from the module, so you have something useful and re-usable.
CSS:
.l-pane {
position: relative;
...
}
.l-pane__item {
position: absolute;
}
.l-pane__item--top-right {
top: 10px;
right: 10px;
}
.popup-dialog { // dialog skin
...
}
.btn { // button skin
...
}
HTML:
<div class="popup-dialog l-pane">
<div class="l-pane__item l-pane__item--top-right">
<button class="btn"><i class="close-ico"></i> close</button>
</div>
</div>
I wouldn't fault anyone for this approach, but from my experience not all layouts can be abstracted in a reasonable manner and have to be set individually. It also makes it harder for other developers to understand. I'd exclude grid layouts from that assumption, they're easy enough to grasp and very useful.
There you have it. I'd suggest trying the modified Approach 2 for the reasons stated above.
Hoping to help.
BEM
If you don't modify .btn inside .popup-dialog first approach is the best.
If you need some .btn modifications, according to BEM methodology you have to use modificator class, like .btn_size_s
If you have modification not directlly connected with .btn, and you doubt whether may be reusable in future, for example you have to float .btn to right only in popup, you can use mixin like .popup-dialog__btn
SMACSS
Again if you need just place one block inside other -follow first approach.
If you need any modifications, there 2 ways : subclasses and descendant selectors.
If you modification may be reused in future - use subclasses, like .btn-size-s.
If modification is tightly connected with some specific module - better use descendant selectors.
UPDATE:
Add few points to clear my answer:
Firstly, Approach 4 is unacceptable - you mix module with layout it is bad practice, as Layout classes in charge of grids and page sections geometry, Module is independent from Layout and should know nothing about section it placed.
Now let me comment other approach and what is the best usage of it:
Approach 1 - Consider following case: You have Popup Module with 'close' Button Module. Popup do nothing with Button, no modification, no floats or margings, its just its child. This is the case this approach is best.
Approach 2 - Another case: Popup has child Button, but we have to add extra top margin and float Button to the right. As you can see this modification tightly coupled with Popup, and cant be usefull for other modules. Such 'local' modifications best usage of this approach. in BEM this approach as also known as mix
Approach 3 - Final case: Popup with child Button, but we need bigger Button, such modificated button can be reused and may be usefull for other Modules and pages.
In BEM its called modifier
To mark main difference between A2 and A3, lets remove Button from Popup and place it somewhere else . A3 will still affect Button, A2 not.
So to work with module as child you can use A1 or A2, A3 should be used in case on module modification independently from context.
First off, I want to clarify that a button, by definition in BEM, is an ELEMENT not a BLOCK. So if you were to tackle this problem using the BEM methodology then this issue becomes a bit simpler.
Secondly, I agree with mlnmln's solution (Approach 2) as it defines the element variation within the block, which is unique to the block itself. However, if an element variation like this button exists outside of the popup-dialog block, then you would want to take Approach 3 and apply a naming convention that allows for global usage.
There is another convention that maybe suits your needs: https://ncss.io
Goal:
A predictable grammar for CSS that provides semantic information about the HTML template.
What tags, components and sections are affected
What is the relation of one class to another
Example:
<div class="modal-dialog">
...
<div class="wrapper-button-dialog">
<button class="button-dialog">close</button>
</div>
</div>
Related
I have a super simple question, are children elements allowed to be classless in BEM CSS methodology?
So, is this code valid:
<div class="foo__label">
<p class="foo__text">Something <strong>else</strong></p>
</div>
Or maybe it should be written as:
<div class="foo__label">
<p class="foo__text">Something <strong class="foo__text-strong">else</strong></p>
</div>
I will allow myself to quote #Intervalia:
Your first example is fine. In your second example you only need to
add a class if you plan to create CSS for it. class="foo__text-strong"
is needed if you need it to be.
His comment perfectly answers your question. However I would like to add another scenario which may come in handy.
It is regarding user generated content from a CMS (worpdress for example). In this scenario the user is usually writing content in WYSIWYG editor and can not add BEM classes or even the user is not so advanced to know about them.
In this case is perfectly fine to have a "parent" element in which you can style elements by tags.
Examples:
.text ul{}
.text p{}
.text iframe{}
.text img{}
.text strong, .text b{}
.text em, .text i{}
.text a{}
UPDATE 1: Info on using nested selectors:
Nested selectors increase code coupling and make reuse impossible. The
BEM methodology allows using nested selectors, but we recommend
minimizing their use.
https://en.bem.info/methodology/faq/#can-i-use-nested-selectors
So yeah if you think it is overkill you may go with #Rene's suggestion.
UPDATE 2: Helper Classes.
The BEM methodology doesn't have strict rules for creating helper
blocks. A lot depends on specific implementations and the personal
preferences of the developer. An example of a helper block in bem-core is the clearfix block.
https://en.bem.info/methodology/faq/#can-i-create-helper-classes
Perhaps this technique can help? Personally I always have few global helpers which I use a lot.
Example, the famous Screen Reader only styles:
.sr-only{
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
border: 0;
}
In your case you can define for example .accent-color or simply .accent which can turn any element's color into red or whatever :)
You could use a cascade .foo__text strong if you are aware that:
It is not BEM compliant;
It wouldn't be possible to add a nested block with a <strong> element as a children of .foo__text.
Regarding the second point, the semantic of <p> element already has limitations. Your cascade just adds one: no <div>, no <ul> as child (because the parent is a paragraph)... and then in your case no BEM block that could have a <strong> element.
So, if you're not a purist, why not.
See also: BEM And Layout Rich Texts
Well I'm watching videos about oop css with bem. I didn't understand one thing. I have a media object and I use it everywhere like in navbar and content and footer etc. So how shall I change the media object and insiders. I guess 3 ways there are.
1 - I can catch inside other blocks grandchild chooser
it will like ".navbar .media".
This way makes me worrying because of grandchildren is making slow and complicated I think. Don't think about only .media. I have to select media-item etc etc...
2 - I can give another class to .media like .navbar together
it will like ".navbar.media".
This way need more classes to html so it makes me thinking.
3 - I guess there is no third option if there is please let me know :) Which way I shall do.
Thank you already.
You should add an extra class, navbar__media (that's a double underscore for descendant), and add that to the media elements inside of the navbar.
A rule of BEM/OOP CSS is that an element should always have their style defined by the classes they have, and not based on where they are in the DOM.
For reference: http://getbem.com/naming/
Example:
<div class="navbar">
<div class="media navbar__media"></div>
</div>
<div class="media"></div>
With this css:
.navbar {
background: #00f;
}
.media {
background: #f00;
}
.navbar__media {
background: #0f0;
}
Let's say I have a styled checkbox (think material design, where there is a bit going on to achieve the desired checkbox style). Which block is responsible for modifying a parent-dependent child block?
Example Component - Checkbox
So I have the following:
<div class="Checkbox">
<label class="Checkbox__label">
<input class="Checkbox__input" type="checkbox" checked=true />
<span class="Checkbox__icon glyphicon glyphicon-ok"></span>
<span class="Checkbox__text">{label}</span>
</label>
</div>
I style up each element within the block for the base checkbox. Within the context of the application, the checkbox block can live in many other blocks (with their own BEM structures).
Example of other blocks
The checkbox with have slightly difference appearance when say within the "Compact Panel":
<div class="Panel Panel--compact">
<p>Disclaimer.. [text]</p>
<Checkbox label="I Agree" />
</div>
Option One - Parent "knows" about child
So.. should the Compact Panel be "aware" of the various children blocks, and style them, so:
// Checkbox.scss
.Checkbox {
margin: 15px;
// .. other
}
// Panel.scss
.Panel {
&.Panel--compact {
margin: 0;
padding: 2px;
}
&.Panel--compact .Checkbox {
margin: 0;
padding: 1px;
}
}
Option Two - Child "knows" about parent
Or, the panel has zero awareness, and the checkbox checks for parent scope.
// Checkbox.scss
.Checkbox {
margin: 15px;
padding: 15px;
// .. other
}
.Panel.Panel--compact .Checkbox {
margin: 0;
padding: 1px;
}
// Panel.scss
.Panel {
&.Panel--compact {
margin: 0;
padding: 2px;
}
}
Option Three - ?
Maybe there are other options.
Usually with BEM if they look different, they are different.
Usually.
There are a number of different choices for handling context and state with BEM. Each has different pros and cons, so which you use will depend heavily on your use case.
The first option I'll mention is to use descendant selectors. You've already identified this choice, and are running into the usual problem of "where does the code belong?"
For the following examples, I'm going to rely on LESS syntax, this is only to make it easier for me to demonstrate relationships in the code.
Descendant Selector
If you're going to use a descendant selector, I recommend that the code be grouped with the child block.
widget.less
.widget {
&__container {
...
}
...
}
checkbox.less
.checkbox {
&__label {
...
}
...
// using inversion to override checkbox styles in a widget
// this will render to `.widget .checkbox` instead of
// `.checkbox .widget` due to the `&` placement
.widget & {
}
}
The reason I recommend associating the styles with the inner block is because the styles will affect the checkbox, and the cascade order will be important.
If the styles were associated with the parent, reordering the parent styles relative to the child styles could adversely affect how the styles render.
Consider this inclusion order:
site.less
#import 'widget';
#import 'checkbox';
If the styles were part of the widget, they could be overridden by a selector of equal specificity in checkbox.less.
Modifiers
I recommend using modifiers for state. I don't generally consider position or context to be "state", so modifiers may not be appropriate. Additionally, multiple modifiers on the same element can be difficult to reason about and therefor difficult to style.
Assuming you're not using a modifier on the checkbox block, then it may be simpler to add the modifier for the case where it's used in a panel.
.checkbox {
&__label {
...defaults...
}
...defaults...
&--alt {
&__label {
...overrides...
}
...overrides...
}
}
Of course, this requires that the markup be updated for the particular case where it's used in a panel, but then it also opens you up to using the checkbox with the same styles elsewhere.
Different Selector
I'm going to reiterate my first point: If they look different they are different.
This doesn't mean you have to start from scratch on the checkbox. BEM allows for object oriented styles. Come up with a new name, and extend* the checkbox:
checkbox.less
.checkbox {
&__label {
...
}
...
}
checkbox-2.less
#import (reference) 'checkbox';
.checkbox-2 {
.checkbox;
&__label {
...overrides...
}
...overrides...
}
* in LESS I'm using a mixin for this as it's generally better suited toward extending and overriding styles than using the :extend feature of the language. Feel free to use the :extend feature, just be aware that selector order will matter.
Refactor the Need Away
Sometimes I run into cases where I want to use a descendant selector or modifier because I need to bump a block for positioning purposes in a container.
In these cases, I often find that the container itself is what should be changed. I can usually tell that it's the container when I need to update the child to have different:
margins
padding
position
top, right, bottom, left
width
height
flex
Refactoring comes with other challenges, however I often end up using container divs to normalize the insertion region for blocks that contain other blocks; YMMV.
tl;dr: Which Should I Pick?
Can you (reasonably) update the markup?
YES: If you can easily update the markup to use different classes, I'd recommend extending your checkbox block as a new block. Naming things is hard though, so be sure to document which one is which somewhere.
NO: If you can't easily update the classes, using modifiers wouldn't be a great choice either. I'd recommend skipping that one, and falling back to the good ol' descendant selector. In BEM you really want to avoid descendant selectors, but sometimes they're the right tool for the job.
According to this documentation, the use of nested selectors should be avoided in BEM, but "is appropriate for changing elements depending on the state of a block or its assigned theme". This means that you can use a block's modifier to style its elements, but I couldn't find any mention of using a block's modifier to style its child blocks.
I think the best approach would be to add modifiers to both .Pannel and .Checkbox blocks, like: .Panel--compact and .Checkbox--context-compact. This way you won't create a dependency between them, which is a BEM principle.
If somehow you can't add a modifier to .Checkbox depending on it's context, I think the closest option would be the second one, where the child behaves differently depending on the state of its parent.
This is the "right" way:
I'm quite surprised why the accepted answer doesn't mention BEM "mixes".
In these scenarios, that is, when a block should change style when used within another block, the official BEM documentation recommends using a block AND an element class on the same DOM node.
So, in your case, this would be the markup:
<div class="Panel Panel--compact">
<p>Disclaimer.. [text]</p>
<div class="Checkbox Panel__checkbox" /> <!-- Here is the change -->
</div>
And this would be the CSS/SCSS:
// Checkbox.scss
.Checkbox {
margin: 15px;
padding: 15px;
// .. other
}
// Panel.scss
.Panel {
&__checkbox {
margin: 0;
padding: 2px;
}
}
It's really that easy and simple. The other answers are overcomplicating this unnecessarily, and I don't know why, the BEM documentation has a clear answer to this question. You can also find many articles online that explain the very same technique I just described.
I recently started a react project and I would like to share my experience on styling react components.
Cascading styles within react components are really confusing. So first thing is try to write class per element. If you want you can wrap using a main class which defines the component.
.panel {
.checkbox {
}
}
I use css-modules. This is super awesome. This tool can create unique classes so you don't need to worry about duplicating same name in other components. You can learn more from their git page and there are many articles online.
If you are using sass and need to use variables you can define a separate sass file in a different folder (let's say ../assets/variables.scss), in your component scss file you can import it and use all variables. Same goes to mixins and functions.
In your case don't worry about child and parent relationship, write single classes for all elements you need to style. Sometime you may need to target children using parent.
A good read
I gave up on using CSS for form styling when I hit snags like requiring 3 textboxes adjacent to one another (like a phone number) or a dropdown list next to a textbox. I just couldn't come up with a reliable way to style it without good ol' TABLES.
I'm thinking about going back to CSS for form styling; I don't know:
Whether it's more usable to have captions on top or on the left of the field.
How to style the things so they place nicely even with a couple of adjacent form elements.
References? Is this still a pipe dream?
You mean like this?
Basically we create a pseudotable
.mxrow {
clear: both;
width: 100%;
height: 50px;
}
.mxcell {
float: left;
padding-top: 10px;
padding-bottom: 10px;
height: 26px;
}
.mxcell_firstcell{
width: 25%;
}
And the markup would be
<div class = "mxrow">
<div class = "mxcell mxcell_firstcell"><input element /></div>
<div class = "mxcell mxcell_secondcell"><another form element/></div>
</div>
The individual cell classnames serve to apply specific css (my markup is a grid)
There are a couple of CSS templates designed specifically for laying out forms.
vessess.com
Uni-form
I hope this helps point you in a productive and awesome direction. Take care.
No, it is very possible, and I (and many others) have been doing it for years.
Look at float: (left|right) and display: (inline|inline-block).
Other people give you some valid suggestions... if you still have problems you can try a form css framework like formee... http://www.formee.org/
In my web app I use several CSS classes to write less code. I use them quite often in the markup to add single property or two in some cases.
These are the following
.clear { float: none; clear: both; }
.fl_l{ float: left; }
.fl_r{ float: right; }
.ta_l{ text-align: left; }
.ta_r{ text-align: right; }
.no_td:hover { text-decoration: none; }
What similar classes do you use? Have you ever seen this technique in other projects?
Sorry to post an answer on such an old question, but I think this is a bad idea. Maybe for a specific set of problems, it fits the bill. My thinking is that CSS is where the style information should be. By doing what you suggest, you are essentially just using the style attribute in html and therefore mixing content w/ style information. This is a bad idea because if one day you decide to change the style completely, you will have to go in and also update the HTML by removing most of the classes.
For example, if you have HTML like this (say for an abstract that is used many times within the page):
<p class="abstract ta_l mb10">
Lorem ipsum dolor set.
</p>
And one day you decide to change how that abstract looks: for example, you don't want it to be "text-aligned:left" anymore and no margin bottom (that's presumably what mb10 would be... i've seen this being used before), you would have to go in and change the HTML.
Now multiply this by 10 elements you have to change. What if it was 50? What if you were doing a complete redesign? shudder.
CSS provides a way to select multiple elements with one simple query and give them an appropriate style that is easily changed from a centralized location. By using these "helper" classes, you are making the maintenance of this project a nightmare for the next developer.
Instead, if you have HTML like this:
<p class="abstract">
You should sign in or something!
</p>
and CSS like this:
.abstract {
margin-bottom: 10px;
text-align: left;
}
you could just change that one rule to this:
.abstract {
text-align: right;
margin-bottom: 0;
}
and be done w/ it! For all 50 elements!
just my 2 cents
-- from someone who just got burned by this.
yeah, if you don't use common classes like you do then your CSS files get extremely large and every class becomes extremely specific
some other common classes...
.split { float: left; width: 50%; }
.center { text-align: center: margin: auto; display: block; }
.bold { font-weight: bold; }
.top { vertical-align: top; }
.bottom { vertical-align: bottom; }
Restore the flow after a floating element:
.clearfix:after
{
clear:both;
content:".";
display:block;
height:0;
line-height:0;
visibility:hidden;
}
Everyone has their own preferences and it also depends on the nature of your application. That said, I do personally tend to reuse a base.css that I port from application to application as a starter style component. Within it I also implement Eric Meyers css reset statements which make development across browsers much easier.
If you are genuinely interested in finding out how professional css frameworks are formed then its probably worth your while downloading and reviewing the following:
960 grid css framework
Blueprint css framework
I like to stay away from what you describe as common class names, keeping as much style-related information away from the HTML as possible. As mentioned by hunter, this does mean selector lists can sometimes get long, but I don't find it a problem.
If I were to use a common class name for clearing floats (the only one of the examples given that I usually might), I'd more often than not use something like .group - the word group at least has some small amount of semanticity attached to it (a group of things that likely belong together). This was suggested by Dan Cederholm.
There are sometimes other considerations that may mean it's either okay or not okay to use class names like this. For example, if your layout changes depending on viewport size via media queries, you may not want something to be styled the same at all times meaning the class name looses its usefulness as you have to be specific with your selectors anyway. Another example would be if the HTML is content-managed by a non-techie client who may not keep your classes intact.