XCSS

XCSS is a safer, tokens-first approach to CSS-in-JS.

Caution

We are planning on deprecating XCSS. We recommend using @atlaskit/css instead.

XCSS is an Atlassian Design System styling API that natively integrates with Atlassian's design tokens and primitives.

To ensure future compliance with XCSS as it evolves over time, we highly recommend you enable our ESLint plugins and adhere to the UI Styling Standard guidelines by writing local, type-safe, static styles.

The XCSS utility behaves similarly to the css utility in libraries like styled-components, @compiled or @emotion, and is built off of @emotion/react today. If you've used these libraries, XCSS will feel familiar, with a few additional features and constraints.

Familiar features:

  • XCSS is applied as an Emotion className to our primitive components
  • XCSS works with the basic CSS object interface found elsewhere
  • XCSS supports style precedence and conditional styles

Key differences:

  • XCSS has type-safety that ensures token name usage for all CSS properties represented by design tokens
  • XCSS restricts nested selectors completely from usage

Usage

To get started, import the function from @atlaskit/primitives and create a style:

import { xcss } from '@atlaskit/primitives';

// Creates a basic style
const someStyles = xcss({
    display: 'block',
});

Apply this style to a component through the xcss prop:

import { Box, xcss } from '@atlaskit/primitives';

// Creates a basic style
const someStyles = xcss({
    display: 'block',
});

const MyBox = () => {
    return <Box xcss={someStyles} />;
};

The xcss prop and the xcss function are direct complements and are designed to be used together.

It is important to note that styles generated from xcss cannot be applied directly to the className property or css as they are with other CSS-in-JS libraries.

Type safety

XCSS uses strongly-typed values generated from design token definitions, making it simpler to apply the right token to the right CSS property. This is intended to be more ergonomic and intuitive, but also prevent the misapplication of tokens to the wrong properties.

Any valid token name is available to be applied against its matching CSS property. For example, the token name space.200 is a valid value below for padding but will not appear as a color, or a font.

import { xcss } from '@atlaskit/primitives';

const someStyles = xcss({
    padding: 'space.200', // <--- works
    color: 'space.200', // <--- invalid and will error
    borderRadius: 'radius.small', // <--- also valid
});

Restricted nesting

XCSS is flexible enough to implement any design, but it does restrict the application of styles in one key way. Selectors cannot be nested or target elements beyond the element on which styles are applied. This restriction is intended to encourage better component encapsulation, reduce side-effects and make the codebase more resilient to change.

import { xcss } from '@atlaskit/primitives';

const someStyles = xcss({
    ':hover': {
        transform: 'scale(1)', // this is okay
    },
    // This is not okay as this selector affects any nested div in
    // the component tree.
    'div:hover': {
        transform: 'scale(1)',
    },
    // Neither is this
    '> * > div:hover': {
        transform: 'scale(1)',
    },
});

These unsafe selectors will throw a type error if applied. Find richer examples of how to use XCSS in the XCSS examples.

Media Queries

XCSS can create responsive layouts at predefined breakpoints that are consistent with the Atlassian Design System. To enable responsive behavior, XCSS exposes the following pre-defined breakpoints:

MediaBreakpointQueryPixel Value
media.above.xxsxxs@media all0px
media.above.xsxs@media (min-width: 30rem)480px
media.above.smsm@media (min-width: 48rem)768px
media.above.mdmd@media (min-width: 64rem)1024px
media.above.lglg@media (min-width: 90rem)1440px
media.above.xlxl@media (min-width: 110.5rem)1768px
media.only.xxsxxs@media (min-width: 0rem) and (max-width: 29.99rem)0px
media.only.xsxs@media (min-width: 30rem) and (max-width: 47.99rem)480px
media.only.smsm@media (min-width: 48rem) and (max-width: 63.99rem)768px
media.only.mdmd@media (min-width: 64rem) and (max-width: 89.99rem)1024px
media.only.lglg@media (min-width: 90rem) and (max-width: 110.49rem)1440px
media.only.xlxl@media (min-width: 110.5rem)1768px
media.below.xsxs@media not all and (min-width: 30rem)480px
media.below.smsm@media not all and (min-width: 48rem)768px
media.below.mdmd@media not all and (min-width: 64rem)1024px
media.below.lglg@media not all and (min-width: 90rem)1440px
media.below.xlxl@media not all and (min-width: 110.5rem)1768px

Media queries can be applied through keys imported from @atlaskit/primitives/responsive. Find more in depth examples on how to enable responsive behavior in the responsive documentation.

The objects defined at each breakpoint behave in much the same way as a normal XCSS object, and can apply responsiveness to any CSS. The only limitation is that a media query can't contain another media query. This is to prevent arbitrary nesting.

Additionally, pseudo-selectors can't contain media queries. To use media queries and pseudos, the media query must contain the pseudo.

import { xcss } from '@atlaskit/primitives';
import { media } from '@atlaskit/primitives/responsive';

const someStyles = xcss({
    // This is okay, since media queries can contain pseudos
    [media.above.md]: {
        ':hover': {
            backgroundColor: 'color.background.neutral.hovered',
        },
    },

    // This is not okay, we don't allow pseudos to contain media queries
    ':hover': {
        [media.above.md]: {
            backgroundColor: 'color.background.neutral.hovered',
        },
    },

    // This is not okay, since media queries can't contain media queries
    [media.above.md]: {
        [media.above.xs]: {
            backgroundColor: 'color.background.neutral.hovered',
        },
    },
});
Was this page helpful?
We use this feedback to improve our documentation.
© 2026 AtlassianTrademark, (opens new window)Privacy, (opens new window)License