Compiled Documentation
repository·master·Indexed 24 days ago
https://github.com/atlassian-labs/compiledA 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.
What's inside Compiled
- Compiled is a compile-time CSS-in-JS library for React. It works by parsing styles written in JavaScript, transforming them during the build process, and outputting them as atomic CSS. This approach reduces runtime overhead and minimizes CSS bloat through style re-use.
Use Compiled for CSS-in-JS in React
masterCompiled is a compile-time CSS-in-JS library for React. It allows you to define styles using a
styledAPI or acssprop, 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>Use transient props with the `$` prefix
masterTo prevent a prop from being passed down to the underlying DOM element, prefix the prop name with a$(e.g.,$color). This is useful for styling props that are not valid HTML attributes or that you want to keep internal to the component logic.Trade-offs of using Atomic CSS in Compiled
masterWhile 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
gzipare 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.
How Server Side Rendering (SSR) works in Compiled
masterCompiled 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:
- Server Render: The server generates HTML containing both the component markup and the corresponding
<style>tags. - Browser Hydration: When JavaScript initializes in the browser, these styles are automatically moved to the
<head>of the document. - 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>- Server Render: The server generates HTML containing both the component markup and the corresponding
Understand the role of `compiled-css.css` in Webpack style extraction
masterIn the
@compiled/webpack-loader/css-loaderworkflow,compiled-css.cssserves as a placeholder CSS file used during the style extraction process. It fulfills two primary technical requirements:- Thread-safe collection of styles: It provides a centralized mechanism to collect styles safely across different threads or processes during the build.
- 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.Automatic vendor prefixing in Compiled
masterCompiled automatically handles vendor prefixing for CSS declarations. You can write standard CSS properties in your style objects, and Compiled will convert them to standard CSS and then apply necessary auto-prefixes (e.g.,
-webkit-,-moz-,-ms-) to ensure cross-browser compatibility.const styles = css({ userSelect: 'none', });Property ordering in style composition
masterWhen using style composition (e.g., applying multiple
cssorcssMapobjects 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>; };Use css or cssMap instead of the deprecated ClassNames API
masterUse collisionResistantHash for migration
masterTo 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 runtimeax()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).- Legacy (Default): Uses a base-36 hash (9-character class names:
Using Runtime Styles (Development/Testing)
masterWith 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 withnull.- Styles are injected using internal runtime functions like
axandCC. - The component uses
<CC>and<CS>wrappers to manage style injection. - The
classNameis generated via theax()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> ); };Handle dynamic styling and props
masterPassing 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:
- Rewrite as conditional rules or
cssMap: Determine if the dynamic style can be expressed as a set of static conditional rules or by usingcssMap. - Use the
styleprop: If you absolutely require dynamic styling that cannot be statically determined, pass the styles to the standard HTMLstyleprop instead of the Compiledcssprop.
For more details on the preferred approach, refer to the UI Styling Standard.
- Rewrite as conditional rules or