📜 ⬆️ ⬇️

CSS GuideLines, part 3. Naming classes



CSS naming conventions allow you to write strong, clean, and beautiful code. If you follow the naming rules, you will always know:


The naming rules I follow are very simple: I use a hyphen as a separator, and in difficult places I use BEM-like naming.
')
It should be noted that the naming rules themselves will not give much benefit when writing CSS; but they are very useful when viewing the markup.

Hyphen separation


All words in class names must be separated by a hyphen:

.page-head {} .sub-content {} 

CamelCase and underscore are not used for classes, the following example is incorrect:

 .pageHead {} .sub_content {} 


BEM-like naming


For larger interconnected parts of the interface, I use BEM-like class naming.

BEM, that is, Block, Element, Modifier , is a methodology created by Yandex developers. Despite the fact that BEM is a rather large methodology, at the moment we are only interested in its method of naming elements. Moreover, my naming convention is slightly different from the original BEM: the principles are the same, but the syntax is different.

BEM divides the layout components into three groups:

Draw an analogy:

 .person {} .person__head {} .person--tall {} 

At the beginning of the class, the block name is always put, to denote an element, we separate the block name from the element name by two underscores (__), and to denote a modifier we use two hyphens (-).

In the example above, we can see that .person {} is a block; he has no ancestors. .person__head {} is an element, part of a block; finally, .person--tall is a modifier, a kind of .person {} block.

Use blocks

A block must be a logical, independent unit. Continuing our example with the class .person {} : we cannot create the class .room__person , because .room {} is an independent unit. In this case, it is worth separating the blocks:

 .room {} .room__door {} .room--kitchen {} .person {} .person__head {} 

If we need to designate a person inside the room, it would be more appropriate to use such a selector - .room .person , which allows you to .room .person porridge out of a heap of different incomprehensible elements and blocks.

A more realistic example of the correct use of blocks might look like this:

 .page {} .content {} .sub-content {} .footer {} .footer__copyright {} 

Each piece of code represents its own block. Incorrect usage example:

 .page {} .page__content {} .page__sub-content {} .page__footer {} .page__copyright {} 

It is important to be able to distinguish where BEM is worth applying, and where not. As a rule, I use blocks to describe the autonomous parts of the user interface.

Many layers

If we added another element to our .person {} block, say, .person__eye , we would not need to step back when naming an element, adding the names of the previous elements, right down to the root element. That is, it will be correct to write .person__eye , and not .person__head__eye .

Adding element modifications

You may need to add variations of elements, this can be done in several ways, depending on how and why these elements should be changed. Again, if a person has blue eyes, then in CSS this can be described as:

 .person__eye--blue {} 

However, in real projects everything is a bit more complicated. I apologize for such an analogy, but let us imagine a person with a beautiful face. By itself, it is not particularly beautiful, so the best solution would be to add a modifier to the element .person__face {} :

 .person__face--handsome {} 

But what if we want to describe the face of a beautiful person? That is, the person is beautiful in itself, unlike the previous example, and we need to describe his face? This is done as follows:

 .person--handsome .person__face {} 

This is one of the few cases when we can change an element depending on the modification of the block. If you use Sass, you would get this code:

 .person {} .person__face { .person--handsome & {} } .person--handsome {} 

Notice that we are not adding a new .person__face element inside the .person--handsome element .person--handsome ; instead, we use the Sass parent selector inside the existing .person__face selector. This means that all the rules associated with .person__face will be in one place, and we will not have to scatter them all over the file. This is a good practice when working with nested code: keep all the necessary styles inside one context (in our case, inside .person__face ).

Naming in markup


As previously noted, the class naming convention is most useful when working with markup. Take a look at the next piece of markup, not our agreement:

 <div class="box profile pro-user"> <img class="avatar image" /> <p class="bio">...</p> </div> 

How are the .box and .profile classes related to each other? How are the .profile and .avatar related to each other? Are they related at all? Does the .bio class .bio on the .pro-user class? Can I use the .avatar class outside of this markup?

When viewing such markup it is very difficult to answer all these questions. Using a naming convention changes things:

 <div class="box profile profile--is-pro-user"> <img class="avatar profile__image" /> <p class="profile__bio">...</p> </div> 

Now we immediately see which classes are related to each other and how, and which ones are not; we know which classes we cannot use outside of this markup; Finally, we know which classes can be used elsewhere.

Javascript hooks



It is generally unwise to tie JS and CSS code to the same class in the markup, because if you delete or change one class to, for example, change script behavior, you will certainly affect CSS, and vice versa. Much cleaner, more transparent and generally better to tie JS to individual classes.

I came across cases when deleting some classes for the purpose of processing styles, broke all the scripts on the page, and all because the developer did not think and linked the styles with scripts to the same class.

As a rule, developers use a separate class for js, starting with the prefix "js-", for example:

 <input type="submit" class="btn js-btn" value="Follow" /> 

This markup allows you to use .btn styles anywhere else without affecting the behavior of .js-btn .

data- * attributes

Also, quite often developers use data- * attributes as js-hooks, but this is wrong. data- * attributes, according to the specification, are designed to store data that is not available on the page. data- * attributes are created for storing data, not for binding to js.

Continuing the theme ...


As already mentioned, all the rules presented above are very simple. I urge you not to dwell on what you have learned and read other materials on this topic - this will allow you to get more opportunities for naming classes.

Materials for additional study




Previous part: CSS GuideLines, part 2. Commenting code

Source: https://habr.com/ru/post/236047/


All Articles