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 ACSS syntax to help you generate Atomic rulesets. It only creates a style sheet with declarations that are relevant to your project. These style declarations are generated from ACSS classes found within your project, or from custom values defined in the Atomizer config file.

Adopting a Atomic CSS methodology 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

ACSS can live side-by-side with traditional style sheets. In cases where ACSS 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 ACSS 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 ACSS. ACSS does not provide classes to create columns based on an opinionated construct (float, inline-block, etc.) Instead, ACSS gives you all the tools you need to create any grid you want.

Specificity

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

By nature, ACSS 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 ACSS 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.
ACSS 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 [↩].