preface

How to write a maintainable CSS library? Let’s talk about CSS design patterns/architectures. Here are three major CSS design ideas and a recent common one: OOCSS, SMACSS, BEMCSS, and METACSS.

OOCSS

OOCSS, which literally stands for object-oriented CSS, is the theory of CSS developed by Nicole Sullivan. Although it is a theory, it is actually more of a specification between programmers:

  • Separate structure and skin reduces dependence on HTML structure
  • Separate container and content increases style reuse

In the OOCSS concept, the reuse of classes is emphasized, and ids should be avoided as CSS selectors. OOCSS pursues the reuse of components, and its class naming is more abstract. It generally does not reflect concrete things, but focuses on the extraction of the presentation layer.

SMACSS

Smacss uses a flexible thought process to check whether your design process and approach fits your architecture

There are three main specifications for the design:

  • Categorizing CSS Rules
  • Naming Rules
  • Minimizing the Depth of Applicability
Categorizing CSS Rules

This is at the heart of SMACSS. According to SMACSS, the CSS has five categories: 1 Base 2 Layout 3 Module 4 State 5 Theme or Skin

Base Rules

The base specification, which describes the default appearance of a page element in any situation. It is defined without class and ID. CSS Reset also falls into this category. Common examples are normalize. CSS and CSS Tools

Layout Rules

Layout specification, elements are divided into levels, Layout Rules belong to the higher level, it can be used as a container for the lower level Module Rules elements. Left and right columns, grid systems, and so on are layout specifications. Layout is the basic of a website, whether it is left or right or center, or even what other layout, to achieve the basic browsing function of the page, the layout is essential. SMACSS also conventions a prefix L -/layout- to identify the class of the layout. Take the most common example.

.layout-header {}
.layout-container {}
.layout-sidebar {}
.layout-content {}
.layout-footer {}
Copy the code
Module Rules

Module specification, module is the most basic idea of SMACSS, but also the basis of most CSS theory, the style modular can achieve the purpose of reuse and maintenance, but SMACSS proposed a more specific modular scheme. Modules in SMACSS have a name of their own. Classes belonging to modules are prefixed by this module. Examples are as follows:

.todolist{}
.todolist-title{}
.todolist-image{}
.todolist-article{}
Copy the code

It can be seen that todolist, as a module, contains title, image, article and other components, as well as modifier classes such as. Todolist – backbackground – Danger, etc. In the module, its name can be used as a prefix to arbitrarily organize the module structure, but the purpose is to make it easier to use. Increasing extensibility and flexibility is self-defeating if you write lots of classes without any reusability just for the sake of embellishment.

State Rules

The state specification, which should be well understood by many front-end developers, describes the appearance of any element in a particular state. For example, a message box might have states such as SUCCESS and Error. Unlike OOCSS, which extracts decorator classes, SMACSS extracts higher-level style classes for greater reuse, such as hiding the way an element is written:

.is-hidden{
    display: none;
}
Copy the code
Theme Rules

Theme specification, which describes the appearance of a page theme, usually referring to colors and background images. Theme Rules can modify the styles of the first four categories, and should be separated from the first four categories (easy toggle, i.e., “skin”). The Theme Rules of SMACSS do not require a separate class name, that is, you can define. Header {} in Module Rules and then use. Header {} in Theme Rules to define the parts that need to be modified.

Naming Rules

Naming conventions

According to the first 5 categories:

Base Rules(Pass)

Layout Rules are prefixed with l- or Layout -, such as. L -header and. L -sidebar.

Module Rules Specifies the name of the Module, such as. Media and. Media-image.

State Rules are prefixed with IS -, for example,. Is -active and. Is -hidden.

Theme Rules If used as a separate class, use the Theme – prefix, such as. Theme -a-background and. Theme -a-shadow.

Minimizing the Depth of Applicability

Minimum depth of fit principle, a simple example:

/* depth 1 */
.sidebar ul h3 { }

/* depth 2 */
.sub-title { }
Copy the code

The difference between the two CSS pieces is the degree of coupling between HTML and CSS (which is similar to OOCSS’s principle of separating container and content). As you can imagine, the style rules above are actually somewhat dependent on the structure of the HTML because they use inheritance selectors. If your HTML is refactored, you may no longer have these styles. Instead, the following style rule has only one selector and is not dependent on a particular HTML structure. You can get the style by adding a class to the element.

Of course, inheritance selectors are useful because they reduce the style conflicts that arise from the same name, which often occur in collaborative development. However, we should not overdo it and use short, unbounded HTML structure selectors as far as possible without causing style conflicts. This is the meaning of minimal depth of fit for SMACSS.

BEMCSS

BEM stands for Block, Element, and Modifier. It is a componentized CSS naming method and specification proposed by Yandex in Russia. Its purpose is to divide the user interface into independent blocks, making development easier and faster, and facilitating team development.

The characteristics of

Componentized/modular development ideas. The decoupled writing mode does not cause namespace pollution, such as the potential nesting risk caused by. XXX ul Li writing. Flat naming method to avoid excessive style hierarchy resulting in reduced parsing efficiency, rendering overhead. Component structure independent, reduce style conflicts, can be opened and completed components quickly applied to new projects. It has good maintainability, readability and flexibility. The rules

The naming pattern for BEM varies in the community, and here is the naming rule proposed by the Yandex team (the code in this article uses this rule) :

.[Block Block]__[Element]_[Modifier] Different naming modes, depending on the BEM connection symbol, depending on the individual:

Each specification is a “thought” or “suggestion” that has been properly evaluated, and is based on actual requirements to facilitate team development and maintenance of extensions.

Block (Block)

Is a separate entity, commonly known as a module or component.

Examples: header, menu, and search

The rule block name must clearly express its purpose, function or meaning and be unique. Block names are concatenated with -. Each block name should be preceded by a prefix, which has a namespace in the CSS (for example, m- and u- represent mod modules and UI components respectively). Each block is logically and functionally independent of the other. Because blocks are independent, they can be reused in application development, reducing code duplication and improving development efficiency. Blocks can be placed anywhere on the page or nested with each other. Blocks of the same type may have certain differences in display, so do not define too many appearance display styles, mainly responsible for the presentation of the structure. This ensures that blocks increase extensibility when reused and nested in different places. To sum up, we can finally define BEM rule as:

. [namespace] – [component name/block] __ element name/elements – [modifier] situation need to build a search component.

Write. M-search {} structure

Element

Is a component in a block and corresponds to a child element/child node in the block.

Example: Header title, menu item, list item

The rule element name must simply describe its structure, layout, or meaning and be semantically related to the block. Blocks and elements are joined by __. Cannot be used separately from blocks. The inner elements of a block are considered children of the block. The class name of the element in a block must be prefixed by the name of the parent block and therefore cannot be written as: block__elem1__elem2. The scenario Search component contains input and Button, which are child elements in the list.

M -search__input{}. M -search__button{

<! --> <form class="m-search"> <! <input class="m-search__input"> <! <button class="m-search__button"> search </button> </form>Copy the code

In principle, no more than two levels of nesting can occur when writing, all styles are flat, and nesting only occurs when the.m-block_active state is active.

Modifier

Defines the appearance, state, or type of blocks and elements.

Example: color, disabled, size

A rule modifier must be an intuitive representation of its appearance, state, or behavior. The modifier joins a block to an element with an _. Modifiers cannot be used alone. You can expand it if necessary and write it as: block__elem_modifier_modifier, with the first modifier indicating its namespace. The scenario assumes that the Search component has several appearances, and we choose one of them. And button displays a disabled style when the user has not entered anything.

M -search__input{}. M -search__button{}. M -search__button_disabled{} structure

<! <form class="m-search m-search-form_dark"> <input class="m-search__input"> <! <button class="m-search__button m-search__button_disabled">Search</button> </form>Copy the code
summary

Many people find the writing style of BEM ugly and aesthetic is a matter of “different minds”. It might seem a little strange to just touch, but everything has an adaptation process. If just for the sake of good looks, avoid its advantages, I think the gain is outweighed the loss. I suggest you try writing code using the BEM specification.

BEM naming makes the Class name longer, but after GZIP compression, the size of the file doesn’t really matter.

Just like CSS semantics proposed in the early years, do not remove semantics for the sake of semantics, the role of semantics itself is to help everyone better identify the code, all specifications are based on the development of the project and team collaboration, the team can choose the most appropriate way according to the wishes of members.

METACSS

Some generic methods, written globally, are offshoots of the generic method idea in SMACSS and are generally named after CSS properties, Emmet CSS abbreviations, or functions, usually with a SINGLE CSS property as a unit

2. Representing an attribute:

.df { display: flex; }
Copy the code

2. Denoting function:

.tcut {  
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
  }
Copy the code

Similarly, encapsulate it for global use and quickly add attributes to develop pages.

Personal summary

Smacss covers all the details; Bemcss focuses on the naming and semantics of CSS. Oocss focuses on reuse, treating each DOM node as an object, which is the idea of CSS back to simplicity; Metacss focuses on rapid development, rapid addition of properties, and finer granularity, adding properties by adding class names to HTML code without having to go to the CSS code in the corresponding selector to modify the style.