Trouble naming children of BEM modifiers - css

So I have the following BEM classes:
.block
.block--modified
.block__child
Now from what I have seen most people would name the child of the modified .block like so:
.block--modified__child
Which I get that makes sense, but is there a reason you could not name it like this:
.block__child--modified
I think this looks better and keeps the modification more isolated / explicit, I also like this because then you can have multiple modified children that are not dependant on the parent being modified i.e
We can have a .block and .block .block--modified elements.
And both can have .block__child and .block__child--modified which still follows the naming convention but makes the child elements (modified or not) more flexible.
For a better example say I have the following classes:
.alert
.alert--warning
.alert--urgent
.alert__call-to-action
.alert__call-to-action--warning
And I want to layout my HTML as follows:
<div class="alert">
<button class="alert__call-to-action">
Action! (No Modifier)
</button>
</div>
<div class="alert alert-warning">
<button class="alert__call-to-action alert__call-to-action--warning">
Action! (Warning Modifier)
</button>
</div>
<div class="alert alert-urgent">
<button class="alert__call-to-action alert__call-to-action--warning">
Action! (Warning Modifier)
</button>
</div>
So you will see I want to re-use the .alert__call-to-action--warning modifier twice in the .alert--warning and .alert--urgent because for what ever reason the styling is the same. Does this make sense from what I can see it makes the modifiers much more usable?
Is there a reason we don't do this? Sorry if there is a better place to post about this please let me know.

Actually BEM methodology says you shouldn't reflect block modifiers in elements naming. Use nesting for such occasions.
See second paragraph of https://en.bem.info/faq/#why-should-i-avoid-using-nested-selectors
That's important because:
There can be quite a lot of modifiers on same block/element
Modifiers represent state of a block/element which may be changed in runtime with JS.
So if you go with modifiers reflected in elements naming it'd be much harder to handle.

Which I get that makes sense, but is there a reason you could not name it like this:
.block__child--modified
Yes, the modifier needs to be attached to what it modifies.
If you've got a state for a block, you attach the modifier to the block:
.message--warning
If you've got a state for an element, you attach the modifier to the element:
.widget__content--expanded
If you attempt to mix the two the meaning gets lost:
//this is a message that is in the warning state
.message--warning
//this is a heading of a message. The heading is in the warning state
.message__heading--warning
So you will see I want to reuse the .alert__call-to-action--warning modifier twice in the .alert--warning and .alert--urgent because for whatever reason the styling is the same.
Don't mix and match modifiers
Does this make sense from what I can see it makes the modifiers much more usable?
You may be able to save some bytes of CSS with this invalid BEM usage, but this sort of micro-optimization has never been the goal of BEM.
It seems to me what you have is not a set of blocks with modifiers. What it looks like you have are a series of blocks that inherit from a similar base block.
Raw CSS doesn't allow for this sort of inheritance to be made explicit, which is unfortunate. Using a preprocessor does though. I will use LESS in this example.
Instead of defining .alert, .alert--warning, and .alert--urgent, consider making three separate blocks:
alert.less
.alert {
..default styles..
&__call-to-action {
..default styles..
}
}
warning.less
#import (reference) 'alert';
.warning {
.alert;
..override styles..
&__call-to-action {
..override styles..
}
}
urgent.less
#import (reference) 'warning';
.urgent {
.warning;
..override styles..
&__call-to-action {
..override styles..
}
}
Note that urgent is a warning, and warning is an alert. Defining your classes like this allow you to use descriptive names in your HTML:
<div class="warning">
<button class="warning__call-to-action" ...>...</button>
</div>
and allow you to get the most out of your styles, because you only have to override the few properties that change.
Of course, this entire example relies on being able to use a preprocessor to reduce the amount of CSS you write. Writing raw CSS is much more verbose.

Related

Reactjs, Bem naming nested structure with SCSSModule

We are using SCSS, SCSSModule and BEM naming methodology. I have researched the best structure for nested elements. I've seen different syntaxes and still have question mark in my head. I saw the symbol differences, for example some teams use "block__element_modifier", some use "block__element--modifier". I know basic usage of BEM. We shouldn't nest the elements with multiple underscored syntax(block__element__nested is wrong). Currently we are using BEM like
block__element--modifier
and nested elements are written with extra hyphen prefix.
Think that the card component structure like below
card
----header
----------title
----------subtitle
----body
----footer
and we code the sass like
// example.scss
.card {
&__header {
// some css
&-title {
// some css
}
&-sub-title {
// some css
}
}
}
and its classes' output is:
card
card__header
card__header-title
card__header-subtitle
Most of the answers in stackoverflow and also some of articles don't suggest BEM as above. They suggest like this:
.card {
&__header {
// some css
}
&__title {
// some css
}
&__sub-title {
// some css
}
}
and its output turn into this:
card
card__header
card__title
card__subtitle
But If I apply as in option 2, I can't figure out which element is in which when I only read scss file. On the other hand, we can understand that in the first option. But the disadvantage of the first option is that the elements become more dependent on each other. For example, when a new div comes between nested elements, I need to refactor related nested class names in the jsx file.
(But still think that it is very useful to understand which elements are nested in the scss file.)
The question is, is my BEM naming wrong or is there such a use in community?
Note: I said we use "module.scss" but I didnt give example in that format. I know, I didnt want to confuse with camelCase things in js.
Your naming is not wrong; it works and it satisfies the BEM pattern; but personally I would not recommend it, and would instead recommend the popular approach.
Your current approach encodes the DOM nesting of elements into the class names. If you need to make changes with regard to the nesting -for example you need an additional wrapper somewhere, which from my experience is a rather common occurence- you will need to change all nested class names. I would be immensely annoyed by that.
And a second drawback of your current approach is that it produces rather long class names.
But what I think is really the biggest drawback of it:
It forces you to nest your SCSS exactly like the DOM nesting to be able to build up the class names. This -in my opinion- makes the SCSS unnecessairily complicated.
With the popular approach your nesting depth for the styles can stay shallow and therefore easier to handle by humans, without messing up the braces { } or needing to nest and unnest rules when the DOM structure changes.
In one of my projects we started with your approach and later changed to the popular approach, and I experienced it as an improvement.
One example:
<div className="card">
<div className="card__header">
<div className="card__branding">
<Logo className="card__logo" />
<span className="card__brandname">Nutrax</span>
</div>
<h2 className="card__title">Recommendation for hard working web devs!<h2>
<div>
<div className="card__body">
Try Nutrax for Nerves!
<div>
<div className="card__footer">
<Button className="card__button">Find nearest store</Button>
<Button className="card__button card__button--promoted">Buy online</Button>
<div>
</div>
.card {
&__header {}
&__body {}
&__footer {}
&__branding {}
&__logo {}
&__brandname {}
&__title {}
&__button {
&--promoted {}
}
}
Now move the branding into the body, no problem, the changes are minimal, and you don't even need to change the SCSS.
PS: You mentioned that you use SCSSModules; I'm not sure I understand what that means. I'm well aquainted with css-modules and I use them usually in my react projects, which completely removes the need for BEM and I can just use rather simple class names that will be automatically scoped to my component only.
If that is also the case with SCSSModules in your project I don't see the need to apply BEM.

Benefits of using CSS modules with React/Vue

I would like to understand the benefits of using CSS Modules with React/Vue.
Currently in my company developers use the following in development:
return (
<div className={styles.User}>
<div className={styles.name}>...</div>
</div>
)
While using a CSS module file, something like:
.User {
background-color: var(--bg-color, red);
.name { color: white; }
}
What should an HTML output such as:
<div class="_User_xyz_1">
<div class="_name_abc_1">...</div>
</div>
Which is a bit confusing for me, as this "encodes" all the class names and creates a great deal of difficulty if I need to do a parent-level modification. Eg.:
<div class="SomeParent">
<User name="David" />
</div>
So:
.SomeParent {
> .User {
--bg-color: blue; // Will not words, because .User is not .User, in fact.
}
}
In personal projects, I prefer to name the primary element of the template by defining it as a "major class", the main. Eg.:
return (
<div className="User">
<div className="name">...</div>
</div>
)
And a regular CSS/SCSS:
.User {
background-color: var(--bg-color, red);
> .name { color: white; }
}
So a parent element's code can affect a child element under expected and controlled conditions.
My question here is: what are the benefits of using the model that my company uses that I am not able to see? Am I missing something using a more "moderate/primitive" model?
Another possibility is: can I modify the style of child elements through the parent element, even with the name of the classes being encoded this way?
CSS modules generate custom classnames for each style and therefore prevent the problem you are facing in your solution. Because each css module style has its own classname you cannot accidentially change a child components style.
SCSS module styles are applied by very unique classes thanks to the hash, and therefore have no real risk of unintended style collisions. This allows you to use short, meaningful class names without having to think of any global styles you might be colliding with. You can confidently style without fear of breaking things elsewhere in your application.
You could, in theory, add generic class names which are not applied via your scss modules to give your parent component a class name with which to work.
Personally I think the React components should be as modular and generic as possible. I think the way to go is such that types are exported from one component. Styles should be inline or at the bottom at a styles object.
hash className, preventing other developers from quickly decompiling your style scheme.

Using BEM CSS with Angular Directives

I've been using BEM style CSS to style my angular directives and usually use replace: true to so that my Block level class can be on the "root" of the custom element. This makes it so that I can write all my CSS primarily with classes.
However, replace: true sometimes causes issues (having two ng-if, etc...) and is now marked as deprecated. So I'm starting to try to stay away from replace completely.
But now I'm having trouble applying BEM to these elements that have an actual custom tag the DOM -- now I have to use a tag name instead of a class name, which means I can't really use BEM anymore (since I'll have to use the tag name since I can't apply classes directly to my element in my template). Additionally, using modifiers on my custom element now seems impossible, as does using sibling CSS selectors.
Here's an example that hopefully will illustrate what I mean:
The directive:
angular.module('my.module')
.directive('customElement', function() {
return {
restrict: 'E',
scope: {
isSpecial: '='
},
template: '<div class="custom-element" ng-class="{\'custom-element--special\': isSpecial"></div>'
};
});
The CSS:
.custom-element {
background-color: white;
}
.custom-element--special {
background-color: red;
}
.custom-element--special + .custom-element--special { // this won't work without replace: true
background-color: blue;
}
If I use replace: true everything works as expected (but then it comes with its own headaches).
If I don't use replace, the classes are not applied to the root custom element so the child selector doesn't work.
I could always add classes to the element in the postLink function, but that makes the template much less clear.
Does anyone have any experience using BEM with angular and using classes instead of tag names in your custom directives? What did you do to solve this problem?
i known it's a problem having replace:false for readability purpose.
The actual problem is that we need our OOCSS but you are handling Angular Components with custom tags has CSS Objects, and is not the case.
There is no practical solution for this, i won't recommend you to start adding classes on postLink function.
However what we are use to do is treat the custom tag as is own CSS Object besides the inner object structure. Forcing us to implement an extra CSS class for the custom tag.
block-context
block-context__element
custom-element
Why doing this when block-context__element is a redundant' class?
Because the rest of your BEM structure is the one you will maintain, the custom-element block should have meaning by it self and the block-context__element element is no expected to, you should abstract the CSS Objects from the directive's implementation, if you in some point start changing your html components your classes should still apply.
I hope this answer helps you

Change property of CSS class in GWT at runtime

I'm familiar with assigning CSS classes to GWT elements to control their formatting, but what if I want to change an attribute in one of those CSS classes?
I've got a styled list of data. CSS classes are used to indicate the various data types (important, routine, trivial). I wish to allow the user to hide trivial entries. I'd like to modify the span.trivial CSS class to set display:none
I'm aware I could loop through the entries, see if an entry is trivial and add a noShow class (which itself has display:none) - but then I'm doing the looping, I'd rather let the browser do the work.
Is this possible in GWT?
Ian
I assume we have a structure similar to the following one
<div>
<span class="routine">A</span>
<span class="trivial">B</span>
<span class="trivial">C</span>
<div>
This is how I would solve the problem:
.hideTrivial span.trivial {
display: none;
}
<div class="hideTrivial">
<span class="routine">A</span>
<span class="trivial">B</span>
<span class="trivial">C</span>
<div>
The ".hideTrivial span.trivial" selector applies only to "trivial" spans, if they occur within another element that has the class "hideTrivial". (Note: The span doesn't have to be a direct child of the "hideTrivial" div - it's ok, if you have a deeper element hierarchy.)
So to turn on/off hiding, you simply add/remove the "hideTrivial" class from the outer div.
(This technique can be used with and without GWT.)
AFAIK, javascript can not change the CSS file and have it reapplied. The same goes for GWT (since it compiles down to JS). So, you can not change a CSS rule and have all elements in your DOM reflect the change.
However, you can get a style of a DOM element and change that style. But that is for a particular element. In your case you'd still need to write code to traverses a set of element and make the change.
My suggestion would be to look at gwtQuery (a port, not a wrapper, of jQuery to GWT). It's super-efficient and super-compact. Here is a one-liner to do what you need:
$("span.trivial").hide()
Fot those who need to modify global CSS property values: you can choose StyleInjector for that purpose.
http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/dom/client/StyleInjector.html

css class within another class as a property

I'm wanting to use properties from other css classes without having to rewrite the code...I'm not too savvy with css so please forgive me for the simple question.
Is it possible to do something like this or similar to it in css?
.class_a {
background:red;
}
.class_b{
.class_a;
}
The best way (that I know of) to re-use css classes is to decide on the css attributes you want to re-use, and put this in a seperate class, like so:
.class_a {
background:red;
}
Then, every time you want to re-use these attributes, you add the class to the html element, with spaces in between different class names, like so:
<div class="text class_a">This will be red, and have the properties of the text class</div>
<div class="text">This will only have the properties of the text class</div>
You can use the same property list for more than one selector:
.class_a, .class_b {
background:red;
}
There are CSS tools which allow you to code in the way you describe. You just do some post-processing of your code to produce valid CSS.
Check out LESS.
Not possible using CSS. However, you can achieve this using something like Sass. Sass allows you write CSS with enhancements such as the one you described. Unfortunately, this introduces an extra step since Sass files must be converted to CSS before you can use them on your page. Could help save you a lot of typing though :)

Resources