Linaria

repository·master·Indexed 11 days ago

https://github.com/callstack/linaria

A zero-runtime CSS-in-JS library that extracts CSS into static files during the build process. It supports familiar CSS syntax, dynamic prop-based styles via CSS variables, and provides specialized tools like @linaria/atomic for utility-first CSS, @linaria/server for critical CSS extraction in SSR, and @linaria/babel-plugin-interop for compatibility with styled-components and Emotion.

Tokens
26.1K
Snippets
93
Records
121
Agent score
95%

What's inside Linaria

  1. Overview of Linaria features

    master

    Linaria is a zero-runtime CSS-in-JS library. It allows you to write styles using JavaScript/TypeScript while extracting them into static CSS files during the build process.

    Key capabilities include:

    • Zero Runtime: CSS is extracted to files at build time, avoiding runtime overhead.
    • CSS Syntax: Supports familiar CSS syntax, including Sass-like nesting.
    • Dynamic Styles: Supports dynamic prop-based styles (via React bindings) by using CSS variables under the hood.
    • Logic in JS: Use standard JavaScript for styling logic instead of a separate CSS preprocessor.
    • Tooling Support: Provides CSS sourcemaps for easier debugging and integrates with stylelint for linting CSS within JS files.
    • Preprocessor Support: Optionally compatible with Sass or PostCSS.
  2. Understanding WyW evaluation strategies

    master

    Linaria uses WyW (Evaluate-on-the-fly) strategies to resolve interpolated values. Choosing the right strategy depends on your project's needs for speed vs. accuracy:

    • hybrid (Default): Attempts to resolve values statically first. If a value cannot be proven statically, it falls back to build-time evaluation in a Node.js environment.
    • execute: Uses evaluator-only behavior. This is a compatibility escape hatch for projects that rely on specific build-time side effects or exact import execution order.
    • static: A strict mode that rejects any fallback to evaluator execution. It will fail if values cannot be resolved statically.

    Warning: Because fallback evaluation runs in Node.js, you cannot use browser-specific APIs (like window) or Node native modules (like fs) inside evaluated expressions unless you wrap them in a function to skip evaluation.

  3. Use the `globalCache` feature

    master

    The globalCache feature is enabled by default. It manages the second level of Linaria's caching system, which caches the results of the entire build process.

    • Enabled (Default): Faster build processes.
    • Disabled: Slower build processes, but decreased memory usage.
  4. Interpolate variables and objects

    master

    Linaria allows you to interpolate JavaScript values into your styles:

    1. Basic Interpolations: Use variables or function calls. These are evaluated at build-time.
    2. Object Interpolations: Pass a JavaScript object. Linaria converts it to a CSS string. Numeric values (e.g., minHeight: 360) will automatically have px appended if no unit is provided. Objects can contain nested selectors and media queries.
    // Basic interpolation
    const fontSize = 16;
    const Title = styled.h1`font-size: ${fontSize}px;`;
    
    // Object interpolation
    const cover = {
      position: 'absolute',
      top: 0,
      '@media (min-width: 200px)': {
        minHeight: 480,
      },
    };
    
    const Title = styled.h1`
      font-size: 24px;
      ${cover};
    `;
  5. Important Linaria trade-offs and limitations

    master

    When using Linaria, be aware of the following constraints:

    1. No IE11 support for dynamic styles: Because dynamic styles in styled components rely on CSS custom properties, they will not work in Internet Explorer 11.
    2. Dynamic styles in css tag: The css tag does not support dynamic styles. For dynamic behavior, use the styled helper or alternative approaches.
    3. Side-effect free modules: Any module imported into a CSS rule (e.g., a colors.js file used inside a css tag) must not have side-effects. It is recommended to keep shared configuration and helpers in files that are purely data/logic without side-effects.
  6. Understand property priorities in Atomic CSS

    master

    To solve the 'shorthand-longhand problem' in atomic CSS, Linaria uses property priorities to ensure predictable styling.

    Priority Rules:

    1. Longhand vs Shorthand: Longhand properties (e.g., padding-top) have higher priority than their shorthand equivalents (e.g., padding).
    2. At-rules: Declarations inside @media rules or other @-rules (like @supports) have higher priority than those outside of them.

    Linaria achieves this by increasing the specificity of the rules. You can find the list of supported properties in the @linaria/atomic propertyPriority function.

  7. How dynamic interpolations are handled in styled components

    master

    When using the styled tag, Linaria replaces dynamic interpolations with CSS custom properties.

    • Function interpolations: These receive the component's props as an argument. The return value is used as the value for the CSS custom property.
    • Other expressions: The result is used as-is. If the result is not a string, it is converted to one.
    • Units: If a valid CSS unit (like px) follows an interpolation directly, Linaria handles it so the unit is applied correctly to the custom property value rather than being appended to the var() function (which would be invalid CSS).
    • Implementation: The interpolations are left in the JS file and passed to a helper that applies the values via inline styles on the rendered element.
    // Linaria handles the unit correctly
    const Title = styled.h1`
      font-size: ${large}px;
    `;
    
    // Transpiles to something like:
    // .Title_t1ugh8t9 { font-size: var(--t1ugh8t-0); }
    // And applies the value via inline styles
  8. Nesting, pseudo-elements, and media queries

    master

    Linaria supports Sass-like nesting for selectors, pseudo-elements, and pseudo-selectors using the & character to refer to the current class. It also supports nesting media queries.

    Supported nesting includes:

    • Pseudo-selectors: &:hover, &.className
    • Pseudo-elements: &::after
    • Child selectors: h3, .code
    • Combinators: & + &
    • Parent selectors: .parent &
    • Media queries: @media (...) { ... }
    const Thing = styled.div`
      color: black;
    
      &::after {
        content: '🌟';
      }
    
      h3 {
        color: tomato;
      }
    
      @media (min-width: 200px) {
        color: blue;
      }
    `;
  9. Use the `happyDOM` feature

    master

    The happyDOM feature is enabled by default. It uses happy-dom to emulate a browser environment during the build process.

    This is useful when libraries contain browser-specific code that cannot be statically evaluated by the dangerousCodeRemover. Emulating a browser allows Linaria to evaluate the code without encountering errors caused by missing browser APIs.

  10. Advantages of Linaria over other CSS-in-JS solutions

    master

    Linaria offers several architectural advantages over runtime CSS-in-JS libraries:

    • Zero Runtime & Parallel Loading: Styles are extracted to separate CSS files at build time. This allows the browser to download and parse CSS and JS in parallel, improving load times.
    • No Client-side Parsing: Unlike libraries that include a parser in the JS bundle, Linaria evaluates styles at build time. No extra parsing is required on the client.
    • No Style Duplication in SSR: Linaria produces a single rule set per declaration. Dynamic differences are handled via CSS variables, preventing the style duplication common in SSR when rendering components with varying props.
    • Build-time Error Detection: Invalid interpolations (e.g., NaN) result in build-time errors rather than runtime bugs.
    • No JS Dependency: Because styles are extracted to CSS, the site can be styled even if JavaScript is disabled or if HTML is pre-generated at build time.
    • Familiar Syntax: You can use standard CSS syntax, making it easy to copy-paste styles from DevTools or other sources.
  11. Use the `softErrors` feature

    master
    The softErrors feature is disabled by default. It provides a more lenient evaluation of interpolated styles and values. Enabling this flag prevents the build from failing if certain files cannot be processed by Linaria, making it useful for debugging.
  12. How Linaria handles dynamic styling with React

    master

    When using the styled helper, Linaria enables declarative dynamic styling by generating CSS variables that automatically update when component props change. This avoids the need to manually manage style updates or duplicate CSS rules for different prop values.

    For example, you can define dimensions based on a size prop, and Linaria will handle the underlying CSS variable updates.

    const Box = styled.div`
      background-color: orange;
      height: ${props => props.size}px;
      width: ${props => props.size}px;
    `;
    
    <Box size={48} />