Zero-Runtime CSS From JS With Linaria
Introduction to Linaria
The CSS is extracted out to plain old CSS files with the Babel preset, and critical CSS can be determined with the included helpers.
The idea for Linaria came from css-literal-loader and the syntax of styled-components. It also uses the same parser as styled-components. Glam by Sunil Pai has been another great source of inspiration.
The API looks like this:
You write CSS syntax (plus nesting) in a tagged template literal and tag it with the css function from Linaria. It returns a class name for you to use. This gets optimized with the Babel preset which reduces it down to just a class name:
You can also compose multiple styles together with the include helper:
which is equivalent to writing:
- CSS is extracted at build time, no runtime is included
- CSS can be extracted for inlining during SSR
- CSS syntax with Sass like nesting
- Integrates with existing tools like Webpack to provide features such as Hot Reload
Existing CSS in JS libraries are pretty amazing as they provide several benefits over the traditional way of writing CSS, making it much more maintainable. They also come with its costs:
- CSS needs to be parsed, auto-prefixed and applied to the document at runtime
These costs may not be significant for all applications, and most of the time, it outweighs the benefits gained from CSS in JS.
The main goal of Linaria is to provide a similar level of flexibility and maintainability while not having the runtime cost associated with it.
How does it differ from CSS modules?
It’s pretty similar, except a few key differences:
- You can write CSS in the same file as rest of the component, no back n forth between files
- You can make sure that you don’t have any CSS you don’t use with linters like ESLint, and it also works with tools likes Flow or Jest
How does it differ from other CSS in JS libraries?
Despite the similarities, there are many differences between Linaria and the existing CSS in JS libraries:
- It is required that all the CSS can be evaluated at build time, which means it’s currently not possible to use dynamic values like props
- The CSS can be served as a separate file, improving load time by parallelizing the downloads and decreasing parsing time
When it comes to Emotion, there's a separate post on how Linaria differs from Emotion and styled components.
Want to give it a try? Check Linaria on GitHub, and don't forget to star it. We’re still actively working on it, so please report any issues you find. Pull requests are always welcome.