Linaria
By Linaria contributors
Linaria is a CSS-in-JS library that lets developers write styles using JavaScript template literals but extracts them into plain CSS files at build time, so no styling logic runs in the browser at runtime. It aims to combine the developer…
Definition
Linaria is a CSS-in-JS library that lets developers write styles using JavaScript template literals but extracts them into plain CSS files at build time, so no styling logic runs in the browser at runtime. It aims to combine the developer ergonomics of CSS-in-JS, such as colocating styles with components and using JavaScript variables, with the performance of static CSS. It targets teams who like CSS-in-JS authoring but want to avoid its runtime performance cost.
Overview
Early CSS-in-JS libraries such as styled-components and Emotion popularized writing component styles as JavaScript template literals colocated with the component itself, but they typically compute and inject those styles into the page at runtime, which adds JavaScript execution cost on every render and can affect metrics like time-to-interactive. Linaria was built specifically to remove that runtime cost: it uses the same familiar tagged-template syntax for writing styles, but a build-time transform extracts all static style logic into ordinary CSS files before the code ever reaches the browser. Mechanically, Linaria's build tooling — implemented as a Babel plugin, webpack loader, or Vite plugin depending on the toolchain — parses the tagged template literals, evaluates any JavaScript expressions that can be resolved at build time, such as referencing a theme constant, and emits standard CSS rules with generated class names, which are then linked back to the component through those class names at runtime. Because the actual styling becomes plain CSS, browsers can parse and apply it exactly as they would a hand-written stylesheet, with no JavaScript-based style computation needed after the build finishes. Linaria sits closest to Stitches in the zero-runtime or near-zero-runtime CSS-in-JS category, both trying to preserve CSS-in-JS's developer experience while minimizing runtime cost, though their build-time mechanics and dynamic-styling capabilities differ. It contrasts with fully runtime libraries like styled-components and Emotion, which offer more flexibility for genuinely dynamic styles computed from arbitrary runtime values, at the cost of shipping a styling engine to the browser. Teams adopt Linaria in performance-sensitive applications where they want the authoring convenience of writing styles alongside components in JavaScript but need production CSS output with no runtime style computation, particularly in server-rendered applications where minimizing JavaScript execution and hydration cost matters most. It fits naturally into build pipelines already using Babel or Vite. The trade-off is that Linaria's zero-runtime model constrains how dynamic a style can be — values only known at actual runtime, such as a value derived from user interaction, require passing them through CSS custom properties rather than arbitrary JavaScript logic evaluated per render, which is a more restrictive model than runtime CSS-in-JS libraries offer. Teams needing highly dynamic, runtime-computed styling may find Linaria's build-time constraints too limiting and prefer Emotion or styled-components instead. Debugging build-time extraction issues can also require more familiarity with the underlying bundler plugin than debugging a purely runtime library does, which adds a modest learning curve for teams new to build-time CSS tooling.
Key Features
- Zero-runtime CSS-in-JS, extracting styles to CSS at build time
- Familiar tagged-template syntax similar to styled-components
- Build-time evaluation of static JavaScript expressions in styles
- Dynamic values handled through CSS custom properties
- Integrates with Babel, webpack, and Vite build pipelines
- No styling engine shipped to the browser at runtime
- Suited to server-rendered apps minimizing JavaScript execution