• Atomic CSS-in-JS
  • Time: 2020/04/27
  • Author: [Sebastien Lorber

] (sebastienlorber.com/authors/seb…).

  • Translator: ziven27
  • Translation time: 2020/05/10

We have VUE that can compete with REACT. There are things like CSS-in-JS, OOCSS, BEM, Atomic CSS… CSS solutions appear? Why is that?

With recent iterations of Facebook and Twitter’s product technology solutions, we’ve seen a new trend: Atomic CSS-in-JS.

In this article, we’ll look at what Atomic CSS is, how it relates to technical solutions like functional/utility-first CSS like TailwindCSS, and how it is used by some of the big companies based on the react framework.

Since I’m not an expert, don’t expect to delve into its pros and cons. I just hope you’ll be inspired by what you know about it.

Note: Atomic CSS has nothing to do with Atomic Design Design.

Atomic CSS is a Design pattern for CSS code. Atomic Design is a Design concept for the resources and organization of a Design.

What is atomic CSS?

You’ve probably heard of various CSS solutions, such as BEM, OOCSS…

<button class="button button--state-danger">
    Danger button
</button>
Copy the code

There is a growing preference for utility-first concepts like Tailwind CSS. This is close to Functional CSS and Tachyon.

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Button
</button>
Copy the code

We can achieve more with a smaller set of class classes

Atomic CSS can be thought of as the ultimate abstraction of Utility-first CSS: all CSS classes have a single, unique CSS rule. Thierry Koblentz (Yahoo!) In 2013, “Challenging CSS Best Practices” first mentioned CSS.

/* Atomic CSS */
.bw-2x {
  border-width: 2px;
}
.bss {
  border-style: solid;
}
.sans {
  font-style: sans-serif;
}
.p-1x {
  padding: 10px;
}
/* Not atomic, because the class contains 2 rules */
.p-1x-sans {
  padding: 10px;
  font-style: sans-serif;
}
Copy the code

We have to admit that when we use Utility/Atomic CSS, we are coupling the structure layer with the style layer: when we need to change the button color, we are changing the HTML, not the CSS. This tightly coupled approach is also recognized in the modern CSS-in-JS React code base, but the existing “separation of concerns” prevailing wisdom runs counter to it.

Since we use simple class selectors, “separation of concerns” is no longer a big problem.

We now modify the style through the structure, which will have the following characteristics:

  1. As we add new functionality, the stylesheet bloat rate decreases
  2. We can modify our styles as we move the HTML around.
  3. When we remove a component, we can make sure that we remove the style associated with it.

Of course, this increases the size of the HTML. This can be a problem for server-rendered Web applications, but gzip is a good way to compress high redundancy in class names in the same way that you compress repeated CSS styles in CSS files.

You don’t need to use Utility /atomic CSS in every case, it is more suitable for most common style materials.

This is the Design Token, and Atomic CSS works to its fullest advantage by interconnecting with the Design Token

Once utility/atomic CSS is defined, it is very difficult to change or grow. With this feature, we can proactively cache it (for example, add it to vendor.css without redeploying it every time). The port line is also very high, making it easy to use in other applications.

Limitations of Utility/Atomic CSS

Utility/ Atomic CSS is great, but it has a few bugs.

Often we manually create utility/atomic CSS and set the rules early in the project. But it is difficult to ensure its ease of use and control its inflation rate. Can this be consistent with multiple people using it? Is it affected by bus factor?

Bus factor is a broken window effect in code.

Let Tailwind save us

Tailwind’s approach is convenient and solves some of these problems.

It doesn’t really provide a single utility CSS file for all web sites. Instead, it provides only shared scopes and naming conventions. Configuration files allow you to generate your own utility CSS.

Tailwind’s knowledge can be ported to other applications, even if they don’t use exactly the same class name. It reminds me of React’s “Learn once, write everywhere” philosophy.

I’ve seen people mention that Tailwind’s classes cover almost 90% or 95% of their daily styling needs. This coverage is large enough that we generally do not need to use one-time styles.

At this point you might be wondering why Atomic CSS instead of Tailwind?

What do you get by strictly following the logic of Atomic CSS with only one rule per Class? Will you end up with bigger HTML tags, and inconvenient naming conventions? Anyway, Tailwind already has a lot of atomic classes built in.

So should we abandon the idea of Atomic CSS in favor of a simpler looking Tailwind?

Tailwind is a great solution, but there are still some unresolved issues:

  • You need to learn specific naming conventions
  • CSS rule insertion order is still important
  • Can unused rules be easily deleted?
  • What do we do with the rest of the one-time styles?

Writing Atomic CSS styles by hand is not a good solution compared to Tailwind.

Compare that to CSS-in-JS

Css-in-js and Utility /atomic CSS have a lot in common. Both approaches advocate styling from tags, similar to writing inline styles, which gives them many similar properties (for example, the ability to safely move content).

Christopher Chedeau was instrumental in spreading the idea of CSS-in-JS throughout the React ecosystem. In Talks, he explains the problems with CSS:

Utility/ Atomic CSS CSS-in-JS/Atomic CSS solves some of these problems, but obviously not all of them (especially the indeterminacy resolution of styles).

If they have so many similarities, can’t we use them at the same time?

Into the Atomic CSS – in – JS

Atomic CSS-in-JS can be considered “automated Atomic CSS” :

  • You no longer need to create a CSS class name
  • Normal styles are treated the same as disposable styles
  • Ability to extract the key CSS of a page and split the code
  • There is an opportunity to solve problems with the insertion order of CSS rules in JS

I am not aware of the current support for Atomic CSS in all CSS-IN-JS libraries. Supporting it is actually an implementation detail of the CSS-in-JS library. Support may be available, not available, or optional.

I will highlight the following two solutions that have led to the recent use of two large-scale atomic CSS-in-JS:

  • React-Native-Web at Twitter (more details in Nicolas Gallagher’s talk)
  • Stylex at Facebook (more details in Frank Yan’s talk)

Also: Styletron, Fela, CXS

React-Native-Web

React-native Web is a very interesting library: it allows you to render React-Native on the Web. We’re not really talking about cross-platform mobile/Web development here (see the forums for more details).

As a Web developer, all you need to know is that React-Native Web is a regular CSS-in-JS library with a small portion of the original React components. Wherever you see a View, you can replace it with a DIV, which is your best bet.

React-native Web was created by Nicolas Gallagher to work on the mobile side of Twitter. They’re gradually deploying it to mobile devices, not sure when exactly, but probably around 2017/2018. Since then it has been sold by other companies (MLS Soccer, Flipkart, Uber, Thames…) Use, but the most important deployment is the new 2019 Twitter desktop application developed by a team led by Paul Armstrong.

Stylex

Stylex is a new CSS-in-JS library developed on Facebook for the 2020 Facebook rewrite (currently in beta). It seems they plan to open source it one day, possibly under a different name.

It’s worth noting that Nicolas Gallagher, author of the React-Native Web, was hired by Facebook two years ago. It’s not surprising to see some of its concepts reused by Facebook.

Unlike the React-Native Web, Stylex doesn’t seem to be focused on cross-platform development.

All the information I received was from the forum 🙂 we will have to wait for more details.

Inflation rate

As Atomic CSS would expect, both The Twitter and Facebook CSS have been drastically reduced, and they both follow the curves in the diagram. Some apps, though, need to be worked on.

The exact numbers Facebook gave:

  • Their old website had 413Kb of CSS just on the landing page
  • Their new site is 74Kb in size, including dark mode

Resources and outputs

The two libraries seem to have a similar and fairly simple API, but it’s hard to tell because we don’t know much about Stylex.

It’s worth emphasizing that the React-native Web handles CSS abbreviations and margin: 0; Syntax like this.

The production environment

Let’s see what HTML looks like on Twitter:

Look at the new Facebook:

Many people may be horrified to see this, but have to admit that it works and can still be used.

Browsing styles in Chrome Inspector can be a little difficult, but DevTools can help:

CSS rules Execution sequence

Unlike handwriting Utility /atomic CSS, JS libraries can make styles independent of the insertion order of CSS rules. As we all know, in the case of a rule conflict, the winner is not the last class in the class attribute, but the last rule inserted in the stylesheet. We can only solve the specificity problem by using simple class-based selectors.

In effect, these libraries avoid outputting classes with conflicting rules on the same element. They ensure that the last style declared in the tag always wins. The “overridden class” is filtered and does not even enter the DOM.

const styles = pseudoLib.create({
  red: {color: "red"},
  blue: {color: "blue"}});// That div only will have a single atomic class (not 2!) , for the blue color
<div style={[styles.red, styles.blue]} >
  Always blue!
</div>
// That div only will have a single atomic class (not 2!) , for the red color
<div style={[styles.blue, styles.red]} >
  Always red!
</div>
Copy the code

If a class has multiple rules and only one of them is overridden, the CSS-IN-JS library will not be able to filter the class without removing the non-overridden rules.

The same problem occurs if a class has a simple abbreviation rule, such as margin: 0, but overrides it with marginTop: 10. If the margin :0 shorthand syntax is extended to four different classes (marginTop:0; marginLeft:0; marginRight:0; MarginBottom :0), these libraries can filter out classes that should not be overwritten in the DOM.

You still like Tailwind?

Once you know all the Tailwind naming conventions, you can write the UI very quickly. It’s hard to go back to the manual style line by line like CSS-in-JS.

There is nothing to stop you from building your own abstractions on top of Atomic CSS-in-JS frameworks. Styled-system enables many CSS-in-JS libraries to support Atomic CSS. If you still prefer Tailwind, you can even rewrite the naming conventions of Tailwind in JS.

This is the traditional way of writing Tailwind:

<div className="absolute inset-0 p-4 bg-blue-500" />
Copy the code

Let’s pick a random solution (React-Native Web-tailwindCSS) that I saw on Google.

import {t} from 'react-native-tailwindcss';
<View style={[t.absolute, t.inset0.t.p4.t.bgBlue500]} / >
Copy the code

In terms of productivity, it’s not that different. And you can get around typing errors with TypeScript.

conclusion

That’s all I want to say about Atomic CSS-in-JS.

I have never used Atoatomic CSS, Atomic CSS-IN-JS or Tailwind in any large production environment project. I may be wrong somewhere, feel free to correct me on Twitter.

I think atomic CSS-in-JS is a trend in the React ecosystem, and I hope you learned something useful from this article.

Since I haven’t found any articles on atomic CSS-in-JS, this article is mainly written for me. I hope to have a resource link when I mention atomic CSS-in-JS in a future blog post (I plan to write more about the React-Native Web and cross-platform, so stay tuned).

Thank you for reading.

The translator’s words

Atomic CSS I don’t know how many times I’ve recommended it, but let’s just say it’s one of the solutions that solves the CSS problem the most in existence. Especially used in react or Vue projects based on componentized thinking.

  1. I say CSS class name can be abbreviated, you don’t hit me!
  2. How to Manage CSS underwear
  3. “CSS thinking” componentization VS atomization

In addition, I recommend an NPM library based on my years of experience with Atomic CSS.

SACSS: Static Atomic CSS

Sacss can be understood as a castrated version of Tailwind. Castration in exchange for access costs and experience. You’ll understand all the logic after five minutes of reading the document.

Personal ability and translation level is limited, there are mistakes welcome correction