Thinking in Atomic

Edit on Github

"Atomic CSS" is a CSS architecture. It is not opinionated; it simply defines a set of classes representing single-purpose styling units.

Atomizer implements the Atomic syntax to help you generate Atomic CSS. It only creates a style sheet with declarations that are relevant to your project. These style declarations are generated from Atomic classes found within your project, or from custom values defined in the Atomizer config file.

Adopting Atomic CSS addresses common CSS challenges:

Changes are predictable
Because of the single responsibility principle (one class == one style) it is easy to predict what removing or adding a class will do.
Scope is limited
There is no reliance on descendant/contextual selectors — styling is done inside "specificity layers".
CSS is lean
There is very little redundancy and no dead weight (all styles are relevant to the project).
Components are portable
Classes used to style a component are not specific to that component, hence components can live in any other project that uses Atomizer [2].
Beginner-friendly
Writing efficient and correct selectors is often one of the hardest parts of CSS for new developers to master. With Atomic CSS, developers don't create bloat because they don't write the selectors, instead they mostly re-use existing classes. This can greatly simplify the learning curve for inexperienced developers.

Who's Atomic CSS for?

Atomic CSS is for developers who see the benefits of styling "outside of style sheets" — who want to write markup and styles in one place while benefiting from a Atomic architecture. It is a switch of priorities. You don't maintain style sheets but components.

Be pragmatic

Atomic CSS can live side-by-side with traditional style sheets. In cases where Atomic CSS doesn't seem the most pragmatic, you can always supplement with inline styles or external stylesheets. Use the right tool for the job.

Traditional style sheets may be helpful for styles that Atomic cannot create, styles for elements that aren't under your application's control, or repeating elements that are not componentized [1].

Grids

There is no such thing as a "Grid" in Atomic CSS. Atomic CSS does not provide classes to create columns based on an opinionated construct (float, inline-block, etc.) Instead, Atomic CSS gives you all the tools you need to create any grid you want.

Specificity

From 0,0,1,0 to "infinity"

By nature, Atomic classes have very low specificity (0,0,1,0). Atomizer creates a style sheet in which the specificity of every rule can be increased by the use of a namespace. Best practice is to keep specificity as low as possible, but depending on other rules in your project you may want to include a namespace to increase the weight of Atomic classes.

Keep in mind that the weight of rules is not as important as making sure specificity is homogeneous across rules. For example, styles like these:

#namespace .myBox {}           /* 0,1,1,0 */
#namespace .menu_item {}       /* 0,1,1,0 */
#namespace .list_active {}     /* 0,1,1,0 */
#namespace .article_summary {} /* 0,1,1,0 */
#namespace .nav_link {}        /* 0,1,1,0 */

are easier to maintain than styles like these:

.myBox {}                      /* 0,0,1,0 */
.menu .menu_item {}            /* 0,0,2,0 */
ul.list .active {}             /* 0,0,2,1 */
.main .article .summary {}     /* 0,0,3,0 */
.nav .list .item a {}          /* 0,0,3,1 */

Choosing to include a namespace or not, and to use a class or a id for the namespace, depends on the weight of rules in other style sheets. For Atomic classes to be relevant they must have enough weight to overwrite non-Atomic styles. The specificity may be the same as non-Atomic styles as long as the Atomic style sheet is included after other style sheets.

This table suggests the namespace to use depending on the weight of your other rules (Specificity Calculator).

Specificity Namespace
0,0,1,1 No need for a namespace
Less or equal to 0,0,1,1 Use html (type) for namespace
Less or equal to 0,0,2,0 Use a class for namespace
Less or equal to 0,1,1,0 Use a id for namespace
More than 0,1,1,0 Use whatever it takes [4]

You can set up a namespace in grunt-atomizer or via the Atomizer command line.

Style sheets organization

Take advantage of the cascade by creating "specificity layers" [3] and loading files in proper order.

Layer Specificity Style sheets
type selectors 0,0,0,x normalize.css,
base.css,
etc.
single class 0,0,1,0 helpers.css,
utility.css,
etc.
contextual selectors
(any number of classes)
0,0,x,x layout.css,
custom.css,
etc.
Atomic classes 0,1,1,0 atomic.css
@style 1,0,0,0 Inline Styles
!important rule Trumps all the above [5] Can be anywhere
(as an exception)

This web site uses flat selectors (0,0,1,0) which allows us to follow the same logic as above without the need for a namespace.


  1. An example of this could be the markup of a "button" that could appear in many places across a project (versus a unique "component" included in multiple places) [↩].
  2. Unless that component relies on custom values from the config file - in which case, keys from that file would need to be added to the config of the other project [↩].
  3. Specificity is something we want to leverage, not something we want to keep a lid on [↩].
  4. The namespace can be anything, for example: #someId #anotherId .andAclass [↩].
  5. !important is not related to specificity per se [↩].