Methods to Organize CSS

Developer Ben Frain once remarked that it's easy to write CSS code, but it is hard to scale and support it. This article describes the set of solutions out there to deal with this problem.

OOCSS

OOCSS stands for object-oriented CSS. This approach has two main ideas:

  • Separation of structure and design
  • Separation of container and content

Using this structure, the developer obtains general classes that can be used in different places.

At this step, there are two pieces of news (as usual, good and bad):

  • Good: reducing the amount of code by reusing it (DRY principle).
  • Bad: complex support. When you change the style of a particular element, you will most likely have to change not only CSS (because most classes are common), but also add classes to the markup.

Also, the OOCSS approach itself does not offer specific rules, but abstract recommendations, so how this method ends up in production varies.

As it happens, the ideas in OOCSS inspired others to create their own, more concrete, ways of code structuring.

SMACSS

SMACSS stands for Scalable and Modular Architecture for CSS. The main goal of the approach is to reduce the amount of code and simplify code support.

Jonathan Snook divides styles into 5 parts:

  1. Base rules. These are styles of the main website elements - body, input, button, ul, ol, etc. In this section, we use mainly HTML tags and attribute selectors, in exceptional cases - classes (for example, if you have JavaScript-style selections);
  2. Layout rules. Here are the styles of global elements, the size of the cap, footer, sidebar, etc. Jonathan suggests using id here in selectors since these elements will not occur more than 1 time on the page. However, the author of the article considers this a bad practice (whenever an id appears in the styles, somewhere in the world the kitten is sad).
  3. Modules rules. Blocks that can be used multiple times on a single page. For module classes, it is not recommended to use id and tag selectors (for reuse and context independence, respectively).
  4. State rules. In this section, the various statuses of the modules and the basis of the site are prescribed. This is the only section in which the use of the keyword "! Important" is acceptable.
  5. Theme rules. Design styles that you might need to replace.

It is also recommended to enter the namespace for classes belonging to a certain group, and also to use a separate namespace for the classes used in JavaScript.

This approach makes it easier to write and maintain code, and has attracted a large number of developers.

Atomic CSS

With Atomic CSS, a separate class is created for each reusable property. For example, margin-top: 1px; assumes creation of a class mt-1 or width: 200px; the class w-200.

This style allows you to minimize the amount of CSS-code by reusing declarations, and it's also relatively easy to enter changes into modules, for example, when changing a technical task.

However, this approach has significant drawbacks:

  • Class names are descriptive property names, not describing the semantic nature of the element, which can sometimes complicate development.
  • Display settings are directly in the HTML.

Because of these shortcomings, the approach has been met with a significant amount of criticism. Nevertheless, the approach can be effective for large projects.

Also, Atomic CSS is used in various frameworks to specify corrective element styles and in some layers of other methodologies.

MCSS

MCSS is Multilayer CSS. This style of code writing suggests splitting styles into several parts, called layers.

  • Zero layer or foundation. The code responsible for resetting browser styles (e.g. reset.css or normalize.css);
  • Base layer includes styles of reusable elements on the site: buttons, input fields for text, hints, etc.
  • Project layer includes separate modules and a "context" - modifications of the elements depending on the client browser, the device on which the site/application is viewed, user roles, and so on.
  • Cosmetic layer is written the OOCSS style, making minor changes in the appearance of elements. It is recommended to leave only styles that affect the appearance and are not capable of breaking the layout of the site (e.g colors and non-critical indents).

The hierarchy of interaction between layers is very important:

  • The base layer defines neutral styles and does not affect other layers.
  • Elements of the base layer can only affect the classes of its layer.
  • Elements of the project layer can affect the base and project layers.
  • The cosmetic layer is designed in the form of descriptive OOCSS-classes ("atomic" classes) and does not affect other CSS-code, being selectively applied in the markup.

AMCSS

AMCSS is "Attribute Modules for CSS".

Let's look at an example:

<div class="button button--large button--blue">Button</div>

Such a chain of classes is not simple, so let's group these values by attributes.

Here's what happens:

<div button="large blue">Button</div>

To avoid names collisions, it's a good idea to add namespaces to the attributes. Then our button code takes the following form:

<div am-button="large blue">Button</div>

If you use the validator to check the code and it doesn't like the am-button attribute, you can prefix data- before the attribute name.

A little-known selector "~ =" (IE7+) is used, which works as a class attribute: it selects elements whose attribute values contain the specified words, separated by spaces. So, the selector of the form [class~="link"][class~="button"] is similar to the selector a.class.button. Even by specificity, since the selector specificities for the class and the attribute are equal to each other!

Accordingly, the CSS code

.button {...}
.button--large {...}
.button--blue {...}

Converts to

[am-button] {...}
[am-button~="large"] {...}
[am-button~="blue"] {...}

If you think this code is too unusual, you can use a less radical AMCSS form:

<div am-button am-button-large am-button-blue></div>

FUN

FUN stands for Flat hierarchy of selectors, Utility styles, Name-spaced components.

There is a certain principle behind each letter of the name:

  • F, flat hierarchy of selectors: it is recommended to use the classes to select items, avoid a cascade without the need, and do not use ids.
  • U, utility styles: it is encouraged to create the service atomic styles for solving typical makeup tasks, for example, w100 for width: 100%; or fr for float: right;
  • N, name-spaced components: Ben recommends to add namespaces for specifying the styles of specific modules elements. This approach will avoid overlapping in class names.

Some developers note that the code written using these principles is quite convenient to write and maintain; in some way, the author took the best from SMACSS and laid out this technique in a simple and concise manner.

This approach imposes quite a few requirements on the project and the code structure, it only establishes the preferred form of recording selectors and the way they are used in the markup. But in small projects, these rules can be quite enough to create high-quality code.

Conclusion

As you can see, there is no ideal one among these approaches. Therefore none of these methods is an absolute rule - you can take an approach from begin to create something of your own, or create a new approach from scratch.