Monday, December 23

BEM For Beginners: Why You Need BEM

BEM For Beginners: Why You Need BEM

BEM For Beginners: Why You Need BEM

Inna Belaya

2018-06-18T14:00:51+02:00
2018-06-18T15:50:05+00:00

BEM makes your code scalable and reusable, thus increasing productivity and facilitating teamwork. Even if you are the only member of the team, BEM can be useful for you. Nevertheless, many developers believe that such a system approach like BEM puts additional boundaries on their project and makes your project overloaded, cumbersome, and slow.

We’ll be collecting all of the main aspects of BEM in a condensed form. This article helps you understand the basic ideas of BEM in just 20 minutes, and to reject prejudices that the system approach is detrimental to your project.

The Big BEM consists of Methodology, Technologies, Libraries, and Tools. In this article, we’ll talk more about the methodology itself because it is the concentrated experience of a huge number of developers and it brings a systematic approach to any project.

In order to show you some practical cases of BEM, we’ll touch on the BEM technologies and completely skip the libraries and tools.

From theory to practice:

So, is BEM a hero or a villain? It’s up to you! But first, read the article.


BEM as a Batman logo
BEMBatman

The Main Reasons Why We Do Not Use Any Selectors Except Classes

One of the basic rules of the BEM methodology is to use only class selectors. In this section, we’ll explain why.

  • Why don’t we use IDs?
  • Why don’t we use tag selectors?
  • Why don’t we use a universal selector?
  • Why don’t we use CSS reset?
  • Why don’t we use nested selectors?
  • Why don’t we combine a tag and a class in a selector?
  • Why don’t we use combined selectors-
  • Why don’t we use attribute selectors?

We Don’t Use IDs (ID Selectors)

The ID provides a unique name for an HTML element. If the name is unique, you can’t reuse it in the interface. This prevents you from reusing the code.

Common Misconceptions
  1. IDs are required for using JavaScript.
    Modern browsers can work with either IDs or classes. Any type of selector is processed at the same rate in the browser.
  2. IDs are used with the <label> tag.
    If you place <label> inside a control, it doesn’t need an ID. Instead of <input id="ID"><label for="ID">Text</label>, simply use <label><input type="...">Text</label>.

We Don’t Use Tag Selectors

HTML page markup is unstable: A new design can change the nesting of the sections, heading levels (for example, from <h1> to <h3>) or turn the <p> paragraph into the <div> tag. Any of these changes will break styles that are written for tags. Even if the design doesn’t change, the set of tags is limited. To use an existing layout in another project, you have to solve conflicts between styles written for the same tags.

An extended set of semantic tags can’t meet all layout needs, either.

An example is when the page header contains a logo. A click on the logo opens the main page of the site (index). You can mark it up with tags by using the <img> tag for the image and the <a> tag for the link.

<header>
  <a href="/">
    <img src="img.logo.png" alt="Logo">
  </a>
</header>

To distinguish between the logo link and an ordinary link in the text, you need extra styles. Now remove underlining and the blue color from the logo link:

header a {
  ...
}

The logo link doesn’t need to be shown on the main page, so change the index page markup:

<header>
  <!-- the <a> tag is replaced with <span> -->
  <span>
    <img src="img.logo.png" alt="Logo">
  </span>
</header>

You don’t need to remove the underlining and the blue color for the <span> tag. So let’s make general rules for the logo link from different pages:

header a,
header span
{
  ...
}

At first glance, this code seems all right, but imagine if the designer removes the logo from the layout. The selector names don’t help you understand which styles should be removed from the project with the logo. The “header a” selector doesn’t show the connection between the link and the logo. This selector could belong to the link in the header menu or, for example, to the link to the author’s profile. The “header span” selector could belong to any part of the header.

To avoid confusion, just use the logo class selector to write the logo styles:

.logo {
  ...
}

We Don’t Use CSS Reset

CSS reset is a set of global CSS rules created for the whole page. These styles affect all layout nodes, violate the independence of components, and make it harder to reuse them.

In BEM, “reset” and “normalize” aren’t even used for a single block. Resetting and normalization cancel existing styles and replace them with other styles, which you will have to change and update later in any case. As a result, the developer has to write styles that override the ones that were just reset.

We Don’t Use The Universal Selector (*)

The universal selector indicates that the project features a style that affects all nodes in the layout. This limits reuse of the layout in other projects:

  • You have to additionally transfer the styles with an asterisk to the project. But in this case, the universal selector might affect the styles in the new project.
  • The styles with an asterisk must be added to the layout you are transferring.

In addition, a universal selector can make the project code unpredictable. For example, it can affect the styles of the universal library components.

Common styles don’t save you time. Often developers start by resetting all margins for components (* { margin: 0; padding: 0; }), but then they still set them the same as in the layout (for example, margin: 12px; padding: 30px;).

We Don’t Use Nested Selectors

Nested selectors increase code coupling and make it difficult to reuse the code.

The BEM methodology doesn’t prohibit nested selectors, but it recommends not to use them too much. For example, nesting is appropriate if you need to change styles of the elements depending on the block’s state or its assigned theme.

.button_hovered .button__text
{
  text-decoration: underline;
}
.button_theme_islands .button__text
{
  line-height: 1.5;
}

We Don’t Use Combined Selectors

Combined selectors are more specific than single selectors, which makes it more difficult to redefine blocks.

Consider the following code:

<button class="button button_theme_islands">...</button>

Let’s say you set CSS rules in the .button.button_theme_islands selector to do less writing. Then you add the “active” modifier to the block:

<button class="button button_theme_islands button_active">...</button>

The .button_active selector doesn’t redefine the block properties written as .button.button_theme_islands because .button.button_theme_islands is more specific than .button_active. To redefine it, combine the block modifier selector with the .button selector and declare it below the .button.button_theme_islands because both selectors are equally specific:

.button.button_theme_islands {}
.button.button_active {}

If you use simple class selectors, you won’t have problems redefining the styles:

.button_theme_islands {}
.button_active {}
.button {}

We Don’t Combine A Tag And A Class In A Selector

Combining a tag and a class in the same selector (for example, button.button) makes CSS rules more specific, so it is more difficult to redefine them.

Consider the following code:

<button class="button">...</button>

Let’s say you set CSS rules in the button.button selector.
Then you add the active modifier to the block:

<button class="button button_active">...</button>

The .button_active selector doesn’t redefine the block properties written as button.button because button.button is more specific than .button_active. To make it more specific, you should combine the block modifier selector with the button.button_active tag.

As the project develops, you might end up with blocks with input.button, span.button or a.button selectors. In this case, all modifiers of the button block and all its nested elements will require four different declarations for each instance.

Possible Exceptions

In rare cases, the methodology allows combining tag and class selectors. For example, this can be used for setting the comments style in CMS systems that can’t generate the correct layout.

You can use the comment to write a text, insert images, or add markup. To make them match the site design, the developer can pre-define styles for all tags available to the user and cascade them down to the nested blocks:

<div class="content">
  ... <!-- the user’s text -->
</div>
CSS rules:
.content a {
  ...
}
.content p {
  font-family: Arial, sans-serif;
  text-align: center;
}

We Don’t Use Attribute Selectors

Attribute selectors are less informative than class selectors. As proof, consider an example with a search form in the header:

<header>
  <form action="/">
    <input name="s">
    <input type="submit">
  </form>
</header>

Try using selector attributes to write the form styles:

header input[type=submit],
header input[type=checkbox] {
  width: auto;
  margin-right: 20px;
}
header input[type=checkbox] {
  margin: 0;
}

In this example, you can’t tell for sure from the selector name that the styles belong to the search form. Using classes makes it clearer. Classes don’t have restrictions that prevent you from writing clearly. For example, you can write it like this:

.form .search {
  ...
}

Now the code is less ambiguous, and it’s clear that the styles belong to the search form.

But the nested selectors still make the CSS rules more specific and prevent you from transferring the layout between projects. To get rid of nesting, use BEM principles.

Summary: class is the only selector that allows you to isolate the styles of each component in the project; increase the readability of the code and do not limit the re-use of the layout.

CSS styles isolation is the most frequent start point of the BEM journey. But this is the least that BEM can give you. To understand how isolated independent components are arranged in BEM, you need to learn the basic concepts, i.e. Block, Element, Modifier, and Mix. Let’s do this in the next section.

The Basics Of BEM

Block And Elements

The BEM methodology is a set of universal rules that can be applied regardless of the technologies used, such as CSS, Sass, HTML, JavaScript or React.

BEM helps to solve the following tasks:

  • Reuse the layout;
  • Move layout fragments around within a project safely;
  • Move the finished layout between projects;
  • Create stable, predictable and clear code;
  • Reduce the project debugging time.

In a BEM project, the interface consists of blocks that can include elements. Blocks are independent components of the page. An element can’t exist outside the block, so keep in mind that each element can belong to one block only.


Source: Smashingmagazine.com

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x