---
order: 0
---

import SectionMessage from '@atlaskit/section-message';
import CssMapExample from '../../examples/constellation/css-map';
import UnboundedExample from '../../examples/constellation/unbounded';

<SectionMessage title="Migration from Emotion to Compiled" appearance="discovery">
	<p>
		The Atlassian Design System is migrating from Emotion to Compiled CSS-in-JS. This transition
		aims to improve performance and align with modern React features.{' '}
		<a href="https://community.developer.atlassian.com/t/rfc-73-migrating-our-components-to-compiled-css-in-js/85953">
			Read our RFC to learn more.
		</a>
	</p>
</SectionMessage>

`@atlaskit/css` is the replacement for `@atlaskit/primitives.xcss`. It serves as a bounded styling
library for use with native HTML elements and the Atlassian Design System, including
[primitive components](/components/primitives/overview).

Built on [Compiled CSS-in-JS](https://compiledcssinjs.com/), it provides a performant, static
styling solution with some syntax changes. Notably, dynamic styles and certain imports/exports may
not work as before.

For configuration details, see our
[Get Started](/get-started/develop#set-up-your-bundling-environment) guide.

## Usage

`@atlaskit/css` closely resembles the behavior of `@compiled/react` and other CSS-in-JS libraries'
`css()` functions. However, we encourage using `cssMap` to create style maps, as the common practice
at Atlassian.

This is a strictly bounded variant designed to align the use of
[Design System tokens](/components/tokens/all-tokens) and properties. You cannot use arbitrary
values, such as `color: 'rgba(123, 45, 67)'` nor `padding: 8`. Typically, only tokenized values are
allowed. Additionally, there are some restrictions, such as `zIndex`, which only supports a limited
set of numeric values.

### cssMap()

We recommend using `cssMap` to create style maps. These maps can be applied and reused on both
native elements and React components using `props.css` and `props.xcss` respectively.

Make sure to define the styles before using them in your components, i.e. at the top of the file.

<Example Component={CssMapExample} packageName="@atlaskit/css" />

### css()

The `css()` function is a lower-level API that creates a single style object. Unlike `cssMap()`,
it's best suited for one-off styles. Use it with elements that accept a `css` prop. While `css()` is
simpler to use, we recommend `cssMap()` for most cases because it provides better reusability and
type safety.

```tsx
const styles = css({
	padding: token('space.100'),
	color: token('color.text'),
});

<div css={styles}>Hello world!</div>;
```

### Primitives

When using `@atlaskit/css`, it's important to note that it's not compatible with the Emotion variant
of Primitives. Instead, use the Compiled variant of Primitives, available at
`@atlaskit/primitives/compiled`. The Compiled variant is a drop-in replacement that provides the
same components and APIs you're familiar with.

### cx

Use the `cx` function when combining styles in an `xcss` prop to maintain correct typing. This is
not required for native elements, but still works with or without.

```tsx
<div css={[styles.root, styles.bordered]} />
<div css={cx(styles.root, styles.bordered)} />
<Box xcss={cx(styles.root, styles.bordered)} />
```

### JSX pragma

You must have a JSX pragma in scope in order to use this, depending on your setup this may be
automatic, require `React` imported, or require `jsx` imported.

```tsx
/**
 * @jsxRuntime classic
 * @jsx jsx
 */
import { cssMap, cx, jsx } from '@atlaskit/css';
import { Box } from '@atlaskit/primitives/compiled';
import { token } from '@atlaskit/tokens';

const styles = cssMap({
	root: {
		padding: token('space.100'),
		color: token('color.text'),
	},
	compact: { padding: token('space.050') },
});

export default ({ spacing = 'default' }: { spacing: 'compact' | 'default' }) => {
	return (
		<Box xcss={cx(styles.root, spacing === 'compact' && styles.compact)}>
			<p css={[styles.compact]}>Hello world!</p>
		</Box>
	);
};
```

## Building reusable components

With the introduction of `@atlaskit/css`, and leveraging the underlying `createStrictAPI` from
Compiled, we've established a strictly bounded API for our components. This approach ensures
consistency and alignment with our Design System, and it might be an API pattern you find beneficial
to adopt in your own projects.

For instance, if you want to create a component that allows you to extend and pass-through styles,
you can do so:

```tsx
/**
 * @jsxRuntime classic
 * @jsx jsx
 */
import { cssMap, jsx, type StrictXCSSProp } from '@atlaskit/css';
import { token } from '@atlaskit/tokens';

const styles = cssMap({
	button: { padding: token('space.100'), borderRadius: token('radius.small') },
	dense: { padding: token('space.050'), borderRadius: token('radius.xsmall') },
});

export function Card({
	children,
	xcss,
	isDense,
}: {
	children: React.ReactNode;
	isDense?: boolean;
	xcss?: StrictXCSSProp<
		'padding' | 'borderRadius' | 'backgroundColor' | 'color',
		'&:hover' | '&:focus'
	>;
}) {
	return (
		<div css={[styles.button, isDense && styles.dense]} className={xcss}>
			{children}
		</div>
	);
}
```

You can then build a component using this Card component and override its properties as needed:

```tsx
/**
 * @jsxRuntime classic
 * @jsx jsx
 */
import { cssMap, cx, jsx, type StrictXCSSProp } from '@atlaskit/css';
import { token } from '@atlaskit/tokens';
import { Card } from './Card';

const styles = cssMap({
	root: { padding: token('space.200'), borderRadius: token('radius.large') },
	inverse: {
		backgroundColor: token('color.background.discovery'),
		color: token('color.text.inverse'),
	},
});

export const LargeCard = ({
	children,
	isInverse,
}: {
	children: React.ReactNode;
	isInverse?: boolean;
}) => {
	return <Card xcss={cx(styles.root, isInverse && styles.inverse)}>{children}</Card>;
};
```

However, if you're extending a component that uses `props.xcss` under the hood, for example a
Primitive, the first `Card` component would look a bit different, brief example:

```tsx
/**
 * @jsxRuntime classic
 * @jsx jsx
 */
import { cssMap, jsx, type StrictXCSSProp } from '@atlaskit/css';
import { token } from '@atlaskit/tokens';

const styles = cssMap({
	button: { padding: token('space.100'), borderRadius: token('radius.small') },
	dense: { padding: token('space.050'), borderRadius: token('radius.xsmall') },
});

export function Card({
	children,
	xcss,
	isDense,
}: {
	children: React.ReactNode;
	isDense?: boolean;
	xcss?: StrictXCSSProp<'padding' | 'borderRadius', never>;
}) {
	return (
		// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- required with `xcss`
		<div css={[styles.button, isDense && styles.dense]} className={xcss}>
			{children}
		</div>
	);
}
```

### Unbounded styles

If you need to apply styles that aren't tokenized, or styles that aren't within the `@atlaskit/css`
API, you can use the `cssMap()` function from `@compiled/react` directly on native HTML elements.
Note that this won't work on primitive components. While it's best to stick to the Design System
guidelines, this option can be useful for handling specific edge cases. Please note this isn't
recommended for general use.

<Example Component={UnboundedExample} packageName="@atlaskit/css" />

## Configuration required

In order to use any Atlassian Design System packages that distribute Compiled CSS-in-JS, you
**must** configure your project, please refer to our
[Get started](/get-started/develop#set-up-your-bundling-environment) guide.
