Compiled Documentation

repository·master·Indexed 24 days ago

https://github.com/atlassian-labs/compiled

A high-performance, compile-time CSS-in-JS library for React that extracts styles into atomic CSS at build time. Includes documentation for @compiled/react, @compiled/css, @compiled/eslint-plugin, and @compiled/babel-plugin-strip-runtime, as well as codemods for migrating from styled-components and emotion.

Tokens
51.9K
Snippets
147
Records
263
Agent score
80%

What's inside Compiled

  1. Use Compiled for CSS-in-JS in React

    master

    Compiled is a compile-time CSS-in-JS library for React. It allows you to define styles using a styled API or a css prop, which are then extracted into an atomic stylesheet at build time to ensure high performance.

    import { styled, ClassNames } from '@compiled/react';
    
    // Tie styles to an element using the css prop
    <div css={{ color: 'purple' }} />
    
    // Create a styled component
    const StyledButton = styled.button`
      color: ${(props) => props.color};
    `;
    
    // Use ClassNames for styles not tied to a specific element
    <ClassNames>
      {({ css }) => children({ className: css({ fontSize: 12 }) })}
    </ClassNames>
  2. Trade-offs of using Atomic CSS in Compiled

    master

    While Atomic CSS offers scalability, developers should be aware of two primary trade-offs:

    1. Larger class names (HTML Markup size)

    Every CSS declaration adds a class to the HTML element. This increases the size of your HTML markup. However, because these class names are highly repetitive, compression techniques like gzip are extremely effective at mitigating this impact.

    2. Selector specificity

    All atomic rules share the same specificity. This means precedence is determined by the order in which the classes appear in the stylesheet. While Compiled automatically sorts common pseudo-classes and at-rules (like media queries), the order of classes across different files or packages can sometimes be non-deterministic.

    Recommendation: If you encounter unpredictable behavior due to specificity, try to rewrite your styles so that only a single declaration can take effect at once. Avoid using the nesting selector unless absolutely necessary.

  3. How Server Side Rendering (SSR) works in Compiled

    master

    Compiled provides zero-config SSR support. Instead of requiring manual configuration, Compiled inlines <style> elements directly into the server-rendered HTML markup next to the components that use them.

    Workflow:

    1. Server Render: The server generates HTML containing both the component markup and the corresponding <style> tags.
    2. Browser Hydration: When JavaScript initializes in the browser, these styles are automatically moved to the <head> of the document.
    3. Deduplication: If the same atomic CSS rule is defined multiple times in the markup, only the first instance is rendered, reducing the initial payload size.

    Benefits:

    • Zero Configuration: Consumers of your components do not need to perform any extra setup.
    • Streaming Support: When using the React streaming server API, component styles are streamed alongside the markup, allowing content to reach users faster.

    Note: If you are using CSS extraction, this inlining behavior no longer applies.

    <!-- Example of inlined SSR markup -->
    <style>._k48pni7l{font-weight:600}</style>
    <div class="_k48pni7l">
      <style>._syaz18rw{color:#ff5630}</style>
      <div class="_syaz18rw">hello world</div>
    </div>
  4. Understand the role of `compiled-css.css` in Webpack style extraction

    master

    In the @compiled/webpack-loader/css-loader workflow, compiled-css.css serves as a placeholder CSS file used during the style extraction process. It fulfills two primary technical requirements:

    1. Thread-safe collection of styles: It provides a centralized mechanism to collect styles safely across different threads or processes during the build.
    2. Caching: It enables efficient caching of extracted styles, which results in faster build bundles.

    The implementation details of how this file is utilized can be found in packages/webpack-loader/src/compiled-loader.ts.

  5. Property ordering in style composition

    master

    When using style composition (e.g., applying multiple css or cssMap objects to a component), the property ordering is applied across the entire composition. If a property in a later object in the array should have been overridden by a property in an earlier object based on Compiled's sorting, it will trigger a violation.

    Example of violation in composition:

    import { css, cssMap } from '@compiled/react';
    
    const styles = cssMap({
      root: {
        paddingTop: '5px',
      },
      warning: {
        // ...
      },
    });
    
    const extraPadding = css({
      padding: '5px',
    });
    
    const Component = ({ children }) => {
      // Violation: paddingTop is applied before padding, but Compiled sorts padding to be overridden by paddingTop
      return <div css={[styles.root, extraPadding]}>{children}</div>;
    };
  6. Use collisionResistantHash for migration

    master

    To migrate to a new hashing scheme that prevents class name collisions, set collisionResistantHash: true.

    • Legacy (Default): Uses a base-36 hash (9-character class names: _ + 4-char group + 4-char value).
    • New (Migration): Uses a base-62 encoded, zero-padded hash (11-character class names: _ + 6-char group + 4-char value).

    Important: This option requires @compiled/react@>=1.0.0. The runtime ax() can handle both formats simultaneously, allowing you to mix old and new classes on the same page during a migration (e.g., when consuming CSS from different npm packages).

  7. Using Runtime Styles (Development/Testing)

    master

    With a basic Babel setup and without extraction enabled, Compiled operates in runtime mode. In this mode, styles are injected into the DOM at runtime.

    Warning: Do not use runtime styles in production. Runtime styles are less performant and can lead to visual breaking changes due to atomic specificity conflicts when mixed with extracted styles.

    Runtime Behavior

    • css() calls are replaced with null.
    • Styles are injected using internal runtime functions like ax and CC.
    • The component uses <CC> and <CS> wrappers to manage style injection.
    • The className is generated via the ax() function using the atomic class names.
    import { ax, ix, CC, CS } from '@compiled/react/runtime';
    const _8 = '._syazu67f{color:#fff}';
    const _7 = '._bfhk1d6m{background-color:#333}';
    const _6 = '._bfhkr75e{background-color:#eee}';
    const _5 = '._19bvftgi{padding-left:1pc}';
    const _4 = '._n3tdftgi{padding-bottom:1pc}';
    const _3 = '._u5f3ftgi{padding-right:1pc}';
    const _2 = '._ca0qftgi{padding-top:1pc}';
    const _ = '._1wybckbl{font-size:3pc}';
    const largeTextStyles = null;
    const invertedStyles = null;
    export const LargeText = ({ inverted, children }) => {
      return (
        <CC>
          <CS>{[_, _2, _3, _4, _5, _6, _7, _8]}</CS>
          <span
            className={ax([
              '_1wybckbl _ca0qftgi _u5f3ftgi _n3tdftgi _19bvftgi _bfhkr75e',
              inverted && '_bfhk1d6m _syazu67f',
            ])}>
            {children}
          </span>
        </CC>
      );
    };
  8. Handle dynamic styling and props

    master

    Passing dynamic styling or props directly to Compiled is no longer recommended because it can interfere with the static analysis used by Atlassian tooling.

    To handle dynamic styles, follow these recommendations in order of preference:

    1. Rewrite as conditional rules or cssMap: Determine if the dynamic style can be expressed as a set of static conditional rules or by using cssMap.
    2. Use the style prop: If you absolutely require dynamic styling that cannot be statically determined, pass the styles to the standard HTML style prop instead of the Compiled css prop.

    For more details on the preferred approach, refer to the UI Styling Standard.