1. In this paper,

When writing CSS code, have you ever encountered the problem of not knowing what class name to choose? Changing the style of one component and worrying about affecting other components? How are component styles written reusable? To solve these problems, clever programmers invented the BEM nomenclature.

BEM naming is a standard for CSS naming. It modularizes pages and isolates styles to improve code reuse and reduce maintenance costs. BEM stands for Block, Element, modifier, linked by double underscore __ or double underscore –.

BEM is commonly used in framework development, such as wechat WEUI, Ele. me Element-UI, Uzan Vant, etc. The author is also through reading the source code of these excellent frameworks, to learn this set of CSS naming method, from then on to the peak of life, win baifumei.

2. Why is BEM nomenclature needed

2.1 Style isolation to avoid CSS style contamination

The root cause of CSS style pollution is that CSS has no scope. BEM avoids global CSS style contamination by creating a “scope” for CSS through special naming. For example, to name an input field:

/ / ordinary.base input{} // BEM naming.base-input__inner {}
Copy the code

The normal nomenclature applies to all descendants of class=’base’. Style pollution is when you want to style the current element but accidentally affect other elements.

BEM nomenclature, which only applies to elements of class=’base-input__inner’, achieves style isolation. Does not affect other elements. Some people say that CSS-Module can also achieve CSS “scope”, and the scope is more unique, why I use BEM?

2.2 Code is easier to cover

Suppose you are developing a generic input box component using CSS-Module. When packed, it looks like this:

.base-input-sdFh3sxLwo5uer {}
Copy the code

Another person uses your input box component, but doesn’t think it looks good and wants to change it. It turns out that you can’t use CSS to select your component precisely because the hash value after.base-input is dynamic. So, he beat his chest and vowed never to use your components again.

2.3 Code is easier to read

Base represents the base component, input represents the input box component, and inner is a piece of the component.

3. What is BEM nomenclature

BEM stands for block, Element, or modifier, using different blocks, functions, and styles to name elements. These three parts are concatenated with — using __ (two instead of one to leave a name for the block). The pattern of naming conventions is as follows:

.block{}
.block__element{}
.block--modifier{}
Copy the code
  • blockRepresents a higher level abstraction or component
  • block__elementOn behalf ofblockThe offspring used to form a completeblockAs a whole
  • block--modifierOn behalf ofblockDifferent states or versions of

3.1 Common Specifications

  1. Use a hyphen – link when block, element, modifier contains more than one word, e.g. :

      .el-dropdown-menu
      .el-button
    Copy the code
  2. Block and element are linked by a double underscore __, for example:

    / / form.form__item/ / navigation items.menu__item
    Copy the code
  3. Use a double underline for Element and Modifier — links, such as to indicate different states of a button:

    / / the default.el-button--default/ / success.el-button--success
    Copy the code
  4. When using JS to control styles, the CSS names start with IS -, such as IS-SUCCESS, IS-Failed, and IS-Disabled

3.2 Common element names

  • Form elements: form, form-item, Input, Select, Radio, checkBox, Switch, Rate, datePicker

  • Navigation elements: nav, Subnav, Menu, TAB

  • Prompt: Alert, message, messageBox, notification

  • Data display: Table Process Tree Pagiantion

  • Others: Button, icon

4. How to use BEM nomenclature

4.1 Page Naming

Start with page- to indicate that this is a page, not a component. When naming a page, BEM can be used in conjunction with CSS-Module. It not only ensures the uniqueness of the packed selector, but also makes it easy to debug. For example,

/ / before compilation.page-index {}
.page-zufang{} // After compiling.page-index-70yGFBg1eKjbSIwN {}
.page-zufang-mFTy62A1t83zjDbh {}
Copy the code

With CSS-Module, the packaged CLSS name is a reference that can be changed

# Make packaged files easier to identifytest: /\.css$/,
   use: [
     {
       loader: 'css-loader'.options: {
         modules: true.localIdentName: '[local]--[hash:base64:5]'}}}]Copy the code

The selectors in the page are nested within the page root selector (.page-xxx), ensuring that all styles apply only to the current page. For example,

<! - Page name -home -><div class="page-home">
    <div class="the-form">
      <div class="the-form-item">
        <div class="the-input"></div>
      </div>
    </div>
    <div class="the-table">
      <div class="the-table-content"></div>
    </div>
  </div>
  <style>
    .page-home {
      .the-form {}
      .the-form-item {}
      .the-input {}
      .the-table {}
      .the-table-content {}
    }
  </style>

Copy the code

4.2 Naming Common Components

Start with base-, which denotes a common component:

<div class="base-input">
  <input class="base-input__inner"/>   
</div>Base -input {}. Base -input__inner {}Copy the code

Each class name of a common component with the component’s scope prefix, such as base-input for base-input__inner.

Selectors should not be nested to keep the weight of the selectors as low as possible. Here’s why:

  • base-input__innerIt is already scoped and no longer needs to be nested.
  • Because of the low weight of component selectors, overwriting styles is convenient when modifying component styles outside the component.

4.3 Naming Local Components

Start with the-, where the denotes a particular component.

<div class="the-header">
  <div class="the-header__title" />
  <div class="the-header__desc">
</div>The -header {}. The -header__title {}. The -header__desc {}Copy the code

Each class name of a local component with the component’s scope prefix, such as the-header__title, whose scope prefix is the-header.

Local components should not be nested to reduce selector weights.

Local components can also be used with CSS-Modules, because local components are only used by a few specific pages and can be styled directly within the component itself.

5. Other matters needing attention

5.1 Naming semantics

How do you measure how semantic your naming is? Having someone new, looking at your code, knowing what this class does, without explaining it, is more semantic.

Usually, you can name modules according to their functions, such as page header, navigation bar nav, main, sidebar, footer, etc., so that the whole page looks clearer and easier to maintain.

// bad
.fl{... }.fr{... } // good // float left.is-float-left{... } // Float right.is-float-right{... }Copy the code

The above code, named fl, FR, etc., is not very clear. You have to look at the code to know what it means, but is-float-left is very clear.

5.2 Use class selectors. Avoid id, tag, and pseudo-class selectors

Selectors such as labels and pseudo-classes are too wide to be “scoped” and pollute global styles. For example, in the following code, the.the-header a selector selects all descendants of the-header

<div class="the-header">
  <a></a>
</div>
// bad
.the-header a { ... }
Copy the code

5.3 When overwriting third-party component styles, rename the class name

Changing the style with the original class name may inadvertently affect the style of subsequent components. To eliminate this, you can create a new class name that applies only to the current component. For example, modify the input box component style of Ant-Design

<div className="the-form">
  <Input className="the-input" />
</div>// Bad affects all input fields of the descendant of the form.the-form.ant-input {} // good only applies to input fields of className='the-input'.the-form.the-input {}Copy the code

6. Reference

CSS BEM writing specification

CSS naming convention -BEM

This article was adapted from: BEM nomenclature