I heard many developers say they hate CSS. Experience tells me that the reason for this is that they don’t take enough time to learn CSS. Yes, we are not talking about the most friendly "language", but it has been successfully used for styling web pages for more than 20 years. This is impressive, and technologies of this level of prevalence have to be considered. However, as the amount of styles used in a certain project grows, one big minus of CSS manifests itself: it is very difficult to maintain. And badly written styles quickly turn into a nightmare.
In this article, we’ll talk about conventions for naming CSS entities. By applying them, you, first, can work more calmly and confidently, and secondly, you will save many hours, which used to be spent on fine-tuning and debugging styles.
You have already been in a similar situation, right?
Use of names consisting of words separated by hyphens
If you write a lot in JavaScript, it means that you are used to the names of variables in the camel style.
')
var redBox = document.getElementById('...')
From the point of view of JS, everything is fine, but the same approach to naming entities is not very well suited for CSS.
For example, you should not do this:
.redBox { border: 1px solid red; }
Instead, it is better to apply this entry:
.red-box { border: 1px solid red; }
A similar approach to names is common in CSS. Perhaps such names are better readable, and, moreover, they are consistent with the names of CSS properties.
// .some-class { font-weight: 10em } // .some-class { fontWeight: 10em }
BEM Naming Convention
Different development teams take different approaches to the formation of CSS selectors. Some use names whose parts are separated by a hyphen, while others prefer the use of a structured naming convention called BEM.
In general, there are three problems that an entity naming convention seeks to solve. Namely, by applying some kind of agreement, the developer can find out the following simply by looking at the CSS selector:
- The role of the selector.
- The scope of use of the selector.
- Relationships between entities.
Have you ever seen class names written like this:
.nav
These are the results of the application of the BEM naming convention.
Basics of BEM on a simple example
▍What is “B”?
At the heart of BEM is the desire to divide the user interface into small components, independent blocks, suitable for reuse.
Take a look at the following image.
This image of the little man won many prestigious awards.
Well, this picture did not win any awards, but it will be very useful to us. So, the little man (stick-man) is a component, that is - a certain block of design.
You can already quite guess that the letter “B” in the abbreviation “BEM” means “block”. In the real world, a “block” can be a navigation bar, a header, or a page footer, in general, any piece of the user interface.
Following the principle voiced above, the
stick-man
can become an ideal class name for such a component.
The component should be styled as follows:
.stick-man { }
So, here used the name, parts of which are separated by a hyphen. This adds order to our code.
Man is .stick-man in CSS
▍What is “E”?
The letter "E" in the abbreviation "BEM" means "element". Design blocks are rarely some kind of "monolithic structures."
So, for example, our little man (
stick-man
) has a head (
head
), two wonderful arms (
arms
) and legs (
feet
).
The parts of man
Entities
head
,
feet
,
arms
are elements that are inside the main component (block). They can be considered as child components, that is, they are descendants of the parent component.
Using the BEM naming convention, the class names of the elements are obtained by adding to the name of the main component two underscores followed by the name of the element. For example:
.stick-man__head { } .stick-man__arms { } .stick-man__feet { }
▍What is “M”?
The letter "M" in the abbreviation "BEM" symbolizes modifiers. What if our little man can be modified, and he can be either blue (
blue
) or red (
red
)?
Blue man and red man
In a web application, this can be something like a red (
red
) or blue (
blue
) button. These are the very modifiers of the components in question.
When using BEM, the modifier class name is obtained by adding two hyphens to the main component name followed by the element name. For example:
.stick-man--blue { } .stick-man--red { }
The last example shows that the entire block is modified, but this is not always the case. What if there are varieties of a little man with a head of a different size?
Variants of a little man with a head of a different size
This time, only the element of the main unit is modified. Remember that an element is a component nested in the main component. The
.stick-man
construct is a block, and
.stick-man__head
is an element.
As you can see from the above example, the hyphen can be used like this:
.stick-man__head--small { } .stick-man__head--big { }
Note the use of two hyphens. This design is used to denote the modifier.
I guess everything should be clear now. These are the basics of BEM.
Personally, I tend to use in simple projects only class names with name delimiters in the form of hyphens, and I use BEM in more complex user interfaces.
Details about BEM can be read
here .
Why use naming conventions?
“There are only two complex tasks in computer science: invalidation of a cache and naming of entities”
Phil carlton
To invent names is a difficult task. Programmers strive to avoid unnecessary complications in order to create code with the support of which there will be no problems in the future. Proper naming of CSS entities makes it easier to read and maintain the code.
If you decide to use the BEM naming convention, this will lead to the fact that, looking at the code, you will immediately see the relationship between the components. This will add you confidence and peace of mind.
CSS names and javascript
Let's talk about using CSS names in javascript. Here we will help novice programmer John. Today is his first working day. He was asked to do the following HTML code:
<div class="siteNavigation"> </div>
John read this article and realized that
siteNavigation
is not a very good name. Therefore, he took up the matter and refactored the code:
<div class="site-navigation"> </div>
Well done, right? But, to the surprise of John, the project, part of which is the code entrusted to him, stopped working normally. What's the matter? The problem is that somewhere in the JavaScript code, the previously used class name
siteNavigation
:
// JavaScript const nav = document.querySelector('.siteNavigation')
As a result, after the class name was changed, the variable
nav
turned out to be
null
. John's first working day was not so good.
In order to prevent such accidents, you can use a variety of approaches. Consider some of them.
▍Application of class names starting with js-
One of the ways to deal with such errors is to use the names of the classes formed according to the
js-*
pattern. Such names indicate that the DOM element in question is accessed from JS. For example:
<div class="site-navigation js-site-navigation"> </div>
As a result, the following code can be used in JavaScript code:
// JavaScript const nav = document.querySelector('.js-site-navigation')
A programmer who was familiar with this naming convention and saw the name of the
js-site-navigation
class would immediately understand that this name is used in the JS code for working with the DOM element and would not change it without extreme need (and without making appropriate corrections into a javascript program).
▍Application of the rel attribute
I do not use this approach, but I have seen those who apply it. Do you know this design?
<link rel="stylesheet" type="text/css" href="main.css">
The
rel
attribute defines the relationship between the referenced resource and the current document. In the previous example with John, supporters of this approach would do this:
<div class="site-navigation" rel="js-site-navigation"> </div>
In JS, you can work with this as follows:
const nav = document.querySelector("[rel='js-site-navigation']")
I have doubts about this approach, but you may well meet it in some project. The purpose of this use of the
rel
attribute is to indicate that the element is used in JavaScript.
▍About data attributes
Some developers use
data
attributes to organize work with DOM elements from JavaScript. However, this is wrong. Such attributes are used to store data. Here is an example of the correct use of
data
attributes from Twitter code.
Proper use of data attributes
Results
Today, we talked about how the correct approach to naming entities helps to facilitate the work with styles of web pages. If you are one of those who do not like CSS, but for obvious reasons can not do without it, we hope this story will help you to take a fresh look at CSS and make friends with this irreplaceable technology, simultaneously increasing the speed and convenience of working with the code of your projects.
Dear readers! What entity naming schemes do you use when working with CSS?
