xstyled Documentation

repository·main·Indexed 25 days ago

https://github.com/styled-components/xstyled

A utility-first CSS-in-JS framework built for React that enables interfaces using shorthand props and responsive design tokens. It provides a utility-first API via the x object, support for styled-components and Emotion, and a comprehensive system for managing theme breakpoints, color modes, and CSS custom properties.

Tokens
93.9K
Snippets
435
Records
646
Agent score
81%

What's inside xstyled

  1. Understand xstyled performance and bundle size

    main

    xstyled is designed to be highly performant and includes a comprehensive set of utilities for building design systems.

    Bundle Size

    The package size is approximately ~15kb gzipped, which includes all utilities and dependencies. This is intended to provide a complete toolkit for a website or design system out of the box.

    • @xstyled/styled-components: ~15.4kb gzipped
    • @xstyled/emotion: ~15.7kb gzipped

    Runtime Performance

    • Computation: Every property computation is cached to minimize overhead.
    • Rendering: xstyled has no measurable impact on the rendering phase compared to standard styled-components.
    • Evaluation: There is a small impact during the evaluation phase because xstyled uses RegExp to detect properties in CSS. However, this impact is considered negligible compared to React's hydration or mounting phases.
  2. Handle prefers-reduced-motion with motionSafe and motionReduce

    main

    You can conditionally apply transitions based on user accessibility preferences using motionSafe and motionReduce states within the transition object.

    For example, you can enable transitions by default but disable them if the user has requested reduced motion via motionReduce: 'none'.

    <x.button
      color={{ hover: 'red' }}
      transition={{ _: true, motionReduce: 'none' }}
    >
      Hover me
    </x.button>
  3. Compare xstyled vs styled-system benchmarks

    main

    Benchmarks comparing @xstyled/system to styled-system show that while styled-system may have a higher operations-per-second count, xstyled provides additional features that account for the difference:

    • Responsive Styles Ordering: xstyled ensures correct ordering for responsive styles.
    • Nested Theme Caching: xstyled supports nested theme caching, which styled-system does not.
    • API Flexibility: xstyled offers a more flexible API, which introduces a slight performance trade-off.
    @xstyled/system x 431,828 ops/sec ±1.06% (86 runs sampled)
    styled-system x 549,224 ops/sec ±0.85% (90 runs sampled)
    Fastest is styled-system
  4. Use object syntax for states in v3

    main

    In v3, states are specified using object syntax, similar to how breakpoints are handled. States can be nested within breakpoints or other states.

    States are configurable in the theme under the states key:

    export const theme = {
      states: {
        hover: '&:hover',
        // ...
      },
    }
    // Basic state usage
    <x.button color={{ _: 'red-500', hover: 'red-300' }} />
    
    // Mixed screens and states
    <x.button color={{ _: 'red-600', md: { _: 'red-500', hover: 'red-300' } }} />
    
    // Nested states
    <x.div bg={{ first: { odd: 'blue' } } } />
  5. How the css prop differs from Emotion when using theme functions

    main

    When using a function in the css prop with @xstyled/emotion, the signature and usage differ from standard Emotion:

    1. The theme is accessed via a destructured object { theme }.
    2. You must wrap your style object in the css function call.

    With xstyled:

    import { jsx } from '@xstyled/emotion'
    
    const Button = ({ children }) => {
      return (
        <button
          css={({ theme }) =>
            css({
              paddingTop: theme.space[1],
            })
          }
        >
          {children}
        </button>
      )
    }
    /** @jsx jsx */
    import { jsx } from '@xstyled/emotion'
    
    const Button = ({ children }) => {
      return (
        <button
          css={({ theme }) =>
            css({
              paddingTop: theme.space[1],
            })
          }
        >
          {children}
        </button>
      )
    }
  6. Apply Scaled Max-Height from theme

    main

    xstyled automatically applies values defined in your theme.sizes section.

    Important Note on Scales: Because values between 0 and 1 are reserved for fluid/percentage calculations, you must append a suffix s to target specific scale values from your theme. For example, a theme value of 0.5 must be referenced as 0.5s and 1 as 1s to avoid being treated as a percentage.

    Example of using theme scales vs raw numbers:

    <x.div maxHeight="1s" /> {/* Targets theme scale value 1 */}
    <x.div maxHeight={8} />   {/* Sets fixed 8px */}
    <x.div
      maxHeight="1s"
      h={32}
    />
  7. Reverse border direction with divideXReverse and divideYReverse

    main

    When your elements are in reverse order (for example, using flexDirection="row-reverse" or flexDirection="column-reverse"), the standard divide utilities might apply borders to the wrong side. Use divideXReverse or divideYReverse to correct the border placement.

    React propCSS Property
    divideXReverse--x-divide-x-reverse: 1;
    divideYReverse--x-divide-y-reverse: 1;
    <x.div
      display="flex"
      flexDirection="column-reverse"
      divideY
      divideYReverse
      divideColor="rose-500"
    >
      <x.div>1</x.div>
      <x.div>2</x.div>
      <x.div>3</x.div>
    </x.div>
    <x.div
      display="flex"
      flexDirection="column-reverse"
      divideY
      divideYReverse
      divideColor="rose-500"
    >
      <x.div
        textAlign="center"
        fontWeight="extrabold"
        fontSize="2xl"
        color="rose-600"
        py={3}
      >
        1
      </x.div>
      <x.div
        textAlign="center"
        fontWeight="extrabold"
        fontSize="2xl"
        color="rose-600"
        py={3}
      >
        2
      </x.div>
      <x.div
        textAlign="center"
        fontWeight="extrabold"
        fontSize="2xl"
        color="rose-600"
        py={3}
      >
        3
      </x.div>
    </x.div>