Locked Video

Please log in or buy the course to watch

Buy Now

Merging Styles

The Challenge with Merging CSS Styles

In CSS, style conflicts can arise based on cascade order. For example:

<div className="bg_blue bg_red" />

It might look like bg_red would override bg_blue since it comes after in the class list. However, the actual result depends on how the CSS is generated:

.bg_red {
  background: red;
}

.bg_blue {
  background: blue;
}

Here, bg_blue wins since its style declaration appears last in the CSS file. Such nuances make CSS merging complex, but Panda CSS offers a structured approach to merge styles without these conflicts.

Merging Styles with Panda CSS

Panda CSS allows us to merge styles without worrying about duplicate classes or conflicts. Here's how to do it right.

Basic Style Merging

Consider these two styles

const style1 = css({
  bg: 'red',
  color: 'white',
})

const style2 = css({
  bg: 'blue',
})

To merge styles in Panda CSS, we need to preserve the underlying style object. The rule of thumb is to use the .raw method to merge styles.

const style1 = css.raw({
  bg: 'red',
  color: 'white',
  fontSize: 'lg',
})

const style2 = css.raw({
  bg: 'blue',
})

const className = css(style1, style2)
// => 'bg_blue text_white'

Merging Recipe Styles with CSS Style

Let's say you have a buttonRecipe and a one-off promoStyles style

const buttonRecipe = cva({
  base: {
    bg: 'blue',
    border: '1px solid black',
  },
  variants: {
    size: {
      small: { fontSize: '12px' },
    },
  },
})

const promoStyles = css.raw({
  bg: 'red',
  color: 'white',
})

When merging these styles, call .raw on the recipe at the point of use

const buttonStyles = buttonRecipe.raw({
  size: 'small',
})

const className = css(buttonStyles, promoStyles)

Merging Two Recipes

If you need to merge two recipes

const linkRecipe = cva({
  base: {
    bg: 'blue',
  },
  variants: {
    size: {
      small: { fontSize: '14px' },
    },
  },
})
const navLinkRecipe = cva({
  base: {
    bg: 'green',
  },
  variants: {
    size: { lg: { fontSize: '16px' } },
  },
})

To merge these styles, call .raw on the recipe at the point of use

const linkStyles = linkRecipe.raw({
  size: 'small',
})
const navLinkStyles = navLinkRecipe.raw({
  size: 'lg',
})

const className = css(linkStyles, navLinkStyles)

This approach ensures style conflicts are handled cleanly without duplicate or unpredictable classes.

Things to note when merging styles

Two main things to keep in mind when merging styles are:

  • Use .raw to get the underlying style object before merging.
  • Pass the raw style objects to css for clean, conflict-free style merging.