This is sort of a theoretical question, but it bugs me for a couple of hours now.
I'm learning BEM and it's great so far, but I have a problem. Let's say I have this code:
<div class="section-hi main-section">
<h2 class="main-section_header">Blah</h2>
<p>Generated from the CMS</p>
</div>
How do I target the p to make it good with BEM? Can I just go with
.main-section p
or this would be against the rules? I coudn't find any answers to this, since every example and article about BEM focuses only on classes, and I can't expect my CMS to add different class to every groups of paragraphs.
One of the concepts of BEM is to create reusable components, using an element such as p goes against that.
Why?
By specifying p we are restricting the ways in which our component can be used. To display correctly the p tag must be used. For example the following markup would not work with the component.
<div class="section-hi main-section">
<h2 class="main-section_header">Blah</h2>
<span>Generated from the CMS</span> <!-- this will not pick up the styles -->
</div>
Specificity
Another important point is BEM aims to keep specificity to a minimum, using single class names. Creating a style with a p increases specificity.
.main-section p
It is now hard for me to override this style with a utility class, as it has a higher specificity than a single class.
More on CSS specificity
The solution
So instead the idea is to use class names to describe the element. That way we can choose to use whatever markup we like and the component will display as expected. e.g.
<div class="section-hi main-section">
<h2 class="main-section_header">Blah</h2>
<h3 class="main-section_subHeader>Generated from the CMS</h3> <!-- This will work -->
</div>
Must I always use class names?
You will find occasions when it is OK or necessary to create styles for elements and not use class names. For example you may have a component that you only want to be used with certain markup. Then it is perfectly valid to do so.
Summary
As a general rule always try and keep to the single class rule unless there is a valid reason not to do so. Otherwise it will trip you up later on down the line.
For further reading on BEM I recommend this post http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
If we just look on this code - you can do that, but what if you have more <p> elements? If you can't add class to every element, you can always add id and call element by
#element_id{ }
Related
Let's say I have a structure like this:
<article class="product">
<header class="product__header">
<h1 class="product__headline">Headline</h1>
<img class="product__hero" src="" alt="">
</header>
<p class="product__description">Content</p>
</article>
As the Block element article brings all the styles it needs by default, it actually doesn't have any CSS. So I'm not defining it in the CSS like this, because it only clutters the styles:
.product { }
But I'm unsure about the HTML. Should it be
<article class="product"></article>
… anyways or simply …
<article></article>
… as there are no styles attached?
What is the right thing to do when usin BEM?
As I understand it, the idea with BEM is to use a standard and have a markup ready for any present or future CSS, so you would always include the class, even if you don't use it right now.
Another good reason is that the parent class improves readability and order for anyone looking at the markup. I would even suggest you to include the class in your CSS and left it blank, functioning almost like a subtitle, with the potential to be useful later on.
Finally, BEM recommends against nesting elements in the stylesheet, which means preferring the use of classes even in the smallest children (like a strong tag inside a p). Seems natural, then, to have a class in the parent as well.
Keep the class to keep your independence. Future changes might require you style . This approach has several advantages:
In 2 months you'll still be able to determine the module components and structure without further ado
You and everybody else will know that is the component container even if you add further wrapping elements in-between.
You might be able to alter the layout without touching the HTML
No dependency between HTML semantics and layout.
All present structure is mirrored into the layout so you can see all variants and elements in the CSS. Get things out of your head
Finally, I agree with you that CSS clutter isn't nice but it could be useful, especially when you're working on a larger codebase with a larger team where you need to rely on standards.
On your parser/IDE: it will probably be configurable to ignore such entries. Your build process should be able to remove these empty selectors so it doesn't make its way into production CSS.
I have come across a similar scenario, If you are following BEM, then keep that class in the article element, since it will help in maintenance(such as removing unused styles, better understand markup).
for example(in product.scss):-
.product {
&__header {
font-size: 1.7rem
// etc...
}
}
Hope this helps. Happy coding....
Note:- Depends upon your markup, you can hoist block element class responsibility to the parent element and updated child class with new parent class.(eg:- .root__prdHeader)
I have a question regarding BEM. Is it ok to have a .block__element on its own with having a block as a parent? I'm building a site with WordPress where there are a lot of other classes from the theme, page builder and plugins, so the need to have parent blocks sometimes makes it all a bit messy. So is this then ok, to have a block__element on its own and then style it via SCSS, or should I add a block to the footer to do this properly?
HTML
<footer id="footer">
<div class="theme-class page-builder-class">
<div class="footer-block__text">Some footer element text</div>
</div>
</footer>
CSS
#footer .footer-block__text {
color: #ffffff;
}
My opinion would be no, for two reasons:
BEM is designed to enforce module separation, so that they are easier to reason about, and to minimize the risk of styles leaking from one module or block to another. If you're mixing BEM blocks with non-BEM code, you're not really doing BEM.
Blocks are designed carefully and assume inheritance from block to block__element. Without seeing any code I of course can't say for sure, but it's possible that the styling of block__element depends on inheriting some rules from block. If the library designer can't assume that all block__elements have a block ancestor, then there's no benefit in structuring the library this way. For instance, if block defines display:flex, and block__element has flex-grow:1, the latter will have no effect without a block parent. If it's getting display:flex from some other ancestor, again you're not really doing BEM.
I think you can mix BEM classes with others in a lot of cases. BEM could be mixed with other methodologies, with some old code, or even with medium specific classes.
For example, I used to mix methodologies:
You have specific changes to make to a block that are not based on logic. In this case, I would prefer use a utility class (ex: .u-uppercase) that will be shorter to write and available for every blocks, than to write an non-logical BEM modifier (ex: .title--uppercase)
You have a layout class (that distribute the screen space) that your repeat in multiple blocks. In this case, I would prefer use an OOCSS object class (ex: .o-container) that will reduce BEM complexity, than to write the same BEM element everywhere (ex: .header__container).
You could find a great presentation about extending BEM here: Modular CSS at Rangle.
From my experience, I tried to mix OOCSS (with l- prefix) and BEM classes (with p- prefix) when building this website https://www.netalis.fr. It was strange at first, but finally very useful and stable.
An example from netalis website:
<!-- HEADER BLOCK -->
<div class="p-header p-header--hero">
<!-- NESTED BLOCK -->
<div class="p-menu"></div>
<!-- OBJECT CLASS -->
<div class="l-container">
<!-- HEADER ELEMENT -->
<div class="p-header__content"></div>
</div>
</div>
It works because theses external classes are:
Isolated from BEM classes, for example no selector that mix both (.p-header > .l-container)
Immutable, the utilities/object classes should not change over time.
So my question is: Does your page-builder-class isolated and immutable?
In all of the material I've read online, it appears that CSS custom properties and CSS variables are the same thing. However, at the end of an example in the Inheritance of CSS Variables section of the Mozilla Developer Network documentation, there is this confusing statement:
Keep in mind that these are custom properties, not actual CSS
variables. The value is computed where it is needed, not stored for
use in other rules. For instance, you cannot set a property for an
element and expect to retrieve it in a sibling's descendant's rule.
The property is only set for the matching selector and its
descendants, like any normal CSS.
Which gives me the impression that these two concepts are not synonymous.
What is the difference between custom properties and variables?
A CSS Custom Property is the same thing as a CSS Variable. But that seems to come of some clumsy naming.
They weren't wrong to title the page: Using CSS custom properties (variables)
However a CSS Variable is not a variable in the traditional sense, as there is no way to define it so that it is globally scoped like in a programming language, or CSS Preprocessor (LESS/Sass).
Even a root scoped custom property/variable is not global. Changing the value of a property in a child will not change the value above or for siblings of that scope. If someone is expecting to be global, it may cause confusion and I suspect that's what Mozilla's writers are trying to point out.
if you look at
w3.org's CSS Custom Properties for Cascading Variables
This module introduces a family of custom author-defined properties known collectively as custom properties
Custom properties are definitions that can be referenced using var(--my-custom-prop). Like a variable!
quote continued...
as one only has to change the value once, in the custom property, and the change will propagate to all uses of that variable automatically.
Awkward... The above statement is not true exactly. It seems Mozilla Developer Network documentation is trying clarify that idea so that it's less confusing. Repeating the original quote:
Keep in mind that these are custom properties, not actual CSS variables. The value is computed where it is needed, not stored for use in other rules. For instance, you cannot set a property for an element and expect to retrieve it in a sibling's descendant's rule. The property is only set for the matching selector and its descendants, like any normal CSS.
They're pointing out it's not a variable in the traditional sense of a programming language. But that it is computed just like styles, adhering to the general cascade/scoping rules of CSS.
Thus var(--my-custom-prop) could resolve to very different things based on where it is declared, and that declarations don't propagate out to a higher scope.
Here's a codepen to mess around with if you'd like to try it out.
So think of CSS Custom Property the same as CSS Variable but be sure to remember that values cascade, and there's no global scope.
To be clear, the specification is called Custom Properties for Cascading Variables. The key is in the word "Cascading"; custom properties cascade, much like any other property with a few key differences.
In everyday usage, there is no difference between a "custom property" and a "CSS variable"; as far as authors are concerned, they're the same thing, just as "property" and "attribute" refer to the same thing in everyday usage even though the correct terms are "custom property" and "property" respectively (CSS doesn't have attributes; any reference to an attribute such as in attribute selectors and attr() refers to attributes in host languages like HTML).
The name "CSS Variables", the spec's URL slug css-variables, and the var() notation, are all just there to placate authors' clamors over the years for variable support in CSS. The spec never actually canonizes the term "CSS variable", even though it uses the word "variable" a couple dozen times throughout its prose to make itself easier for authors to understand (which is strange because CSS specs aren't intended to be read by authors).
As MDN explains, custom properties aren't true variables like that of programming languages or even CSS preprocessors, even though they have a lot in common. As mentioned above, cascading is what sets custom properties apart. Those traits that they have in common are what authors really are looking for in "variable" support in CSS, and they're good enough for most authors' needs.
That's why everyone just calls them "CSS variables", even though in reality it's a bit of a misnomer.
I have looked at the page you have linked; they are trying to explain the "cascading" of css. They are saying that the style depends on a selector's parents, as opposed to being a set value as you would get in a variable.
The explanation attempts to clarify the difference between a css property and a vairable in programming languages. If you already understand css, you don't need to worry about this explanation.
If we look at the example they provide:
<div class="one">
<div class="two">
<div class="three"></div>
<div class="four"></div>
</div>
</div>
If you give properties to class="two", they will be applied to class="three" and class="four".
If you re-use class="three" and class="four" within another class, like this:
<div class="five">
<div class="three"></div>
<div class="four"></div>
</div>
then they will inherit whatever properties you applied to class="five" with nothing to do with class="two".
This all assumes that class="three" and class="four" do not have their own properties. Let's say you assign the color red to class="three", then it will be red in both cases plus the properties inherited from its parent classes.
I believe that it simply means that if you have the following rules:
#foo{
--my-prop: 10px;
}
.bar{
height: var(--my-prop);
}
with the following HTML:
<div id="foo">
<div class="bar"></div>
</div>
<div id="sibling">
<div class="bar"></div>
</div>
then the height of the .bar div in the #sibling div is going to be 0, because the value of --my-prop is only inherited by descendants of #foo.
The language is confusing. I think the author is probably trying to draw a distinction between variables in procedural languages (like JS) versus Custom CSS Properties. You cannot set a property and use it anywhere, like you might with a variable in another language.
I try to code CSS in "Help Class Style" today and many developers on Twitter said it was a bad practice.
Here is an example:
<span class="et-margin-top-30 et-width-400 et-display-inline">
<p class="et-common-frame-shadow et-inner-img-shadow">
<img class="et-common-frame-img" src="img3.jpg"/>
</p>
<h3 class="et-margin-top-10 et-fontsize-26 et-fontweight-bold">foo</h3>
<p class="et-margin-top-10">bar</p>
</span>
Why is it a bad practice? When should we use a helper class such as .clear?
The idea of styling via CSS is separation between content and styling. Your content is in HTML and CSS provides the information on how that should be visually displayed. If you want to change one, you can do so without changing the other.
By naming your classes et-margin-top-30, you're putting the styling information back into your HTML. You may as well write style="margin-top: 30px". Because if you decide that that element should have a 50 pixel margin after all, you need to change both the CSS and the HTML. That's why it's bad style.
You should rather name your HTML elements by their function (e.g. class="headline", or class="call-to-action"), then describe in your CSS how that headline or that call-to-action should be styled. If you want to change that later, you can do so by simply editing your CSS, the HTML doesn't need to change.
Not to mention that if you're using Javascript to manipulate elements, using document.getElementsByClassName('et-margin-top-30') a) makes it very hard to understand the meaning of your scripts and HTML structure and b) requires that you modify your HTML, CSS and Javascript every time you want to tweak the visual appearance of an element. Using descriptive class names becomes doubly important then.
What you are trying to do there looks horrible. It looks like you have a class for all different styling attributes. Not only will it make your HTML unreadable, but it will also enlarge the file size.
What if an element has 15 styles "attached" to it. Will it have 15 classes?
I also think this will only make this slower to render (this is just something I just made up and for which I have no proof), because it has to look up all those classes.
I don't see any difference in doing <p style="color: red;"></p>.
This question is about an approach to css structuring, and so is more discussion oriented.
I'm working with some outsourced css where the body tags have multiple classes assigned, up to half a dozen. (To make things a little worse, none of the css selectors include an html tag which is making it confusing to analyze the css.) These body classes are then used to modify classed or id'd widgets within.
It seems like this approach is like adding an additional dimension to the css, perhaps in some attempt to create a structured css approach. Documentation might have helped, had we been provided any.
This differs from my approach where widgets are styled primarily via id'd divs, perhaps extracting the more generic elements into a class, i.e. div#MyWidget.widgets.
Any ideas on whether such an approach is maintainable, especially considering I am dealing with websites with thousands of pages including tons of legacy stuff, all done by different people with different skill levels? Thanks...
I find nothing particularly wrong with this approach, provided you are conceptually using the body tags to apply very general style rules. The higher up the class is in the DOM, the more generic it should be.
It's hard to answer specifically without examples. One I frequently use is to turn the URL segments into classes for body tag in my pages, for relatively small sites:
// mysite.com/users/show/
<body class="users show">
<div id="Content">
...
</div>
</body>
I use this almost exclusively for overriding default styles on very specific pages:
#Content {
width:500px;
}
.users.show #Content {
width:600px;
}