Concepts
Merging Styles
Panda CSS provides a few ways to efficiently merge styles together without conflicts.
Merging css
objects
You can merge multiple style objects together using the css
function.
import { css } from 'styled-system/css'
const style1 = {
bg: 'red',
color: 'white'
}
const style2 = {
bg: 'blue'
}
const className = css(style1, style2) // => 'bg_blue text_white'
In some cases though, the style object might not be colocated in the same file as the component. In this case, you can use the css.raw
function to preserve the original style object.
All .raw(...)
signatures are identity functions that return the same value as the input, but > serve as a hint to the compiler that the value is a style object.
// style.js
import { css } from 'styled-system/css'
export const style1 = css.raw({
bg: 'red',
color: 'white'
})
// component.js
import { css } from 'styled-system/css'
import { style1 } from './style.js'
const style2 = css.raw({
bg: 'blue'
})
const className = css(style1, style2) // => 'bg_blue text_white'
Merging cva
+ css
styles
The same technique can be used to merge an atomic cva
recipe and a style object.
import { css, cx, cva } from 'styled-system/css'
const overrideStyles = css.raw({
bg: 'red',
color: 'white'
})
const buttonStyles = cva({
base: {
bg: 'blue',
border: '1px solid black'
},
variants: {
size: {
small: { fontSize: '12px' }
}
}
})
const className = css(
// returns the resolved style object
buttonStyles.raw({ size: 'small' }),
// add the override styles
overrideStyles
)
// => 'bg_red border_1px_solid_black color_white font-size_12px'
Merging sva
+ css
styles
The same technique can be used to merge an atomic sva
recipe and a style object.
import { css, sva } from 'styled-system/css'
const overrideStyles = css.raw({
bg: 'red',
color: 'white'
})
const buttonStyles = sva({
slots: ['root']
base: {
root: {
bg: 'blue',
border: '1px solid black'
}
},
variants: {
size: {
root: {
small: { fontSize: '12px' }
}
}
}
})
// returns the resolved style object for all slots
const { root } = buttonStyles.raw({ size: 'small' })
const className = css(
root,
// add the override styles
overrideStyles
)
// => 'bg_red border_1px_solid_black color_white font-size_12px'
Merging config recipe and style object
Due to the fact that the generated styles of a config recipe is saved in the @layer recipe
cascade layer, they can overriden with any atomic styles. Use the cx
function to achieve that.
The utilties
layer has more precedence than the recipe
layer.
import { css, cx } from 'styled-system/css'
import { button } from 'styled-system/recipes'
const className = cx(
// returns the resolved class name: `button button--size-small`
button({ size: 'small' }),
// add the override styles
css({ bg: 'red' }) // => 'bg_red'
)
// => 'button button--size-small bg_red'
Merging within JSX component
Using these techniques, you can apply them to a component to merge styles together.
Tip: Panda extracts the css
prop from the JSX component
const cardStyles = css.raw({
bg: 'red',
color: 'white'
})
function Card({ title, description, css: cssProp }) {
return (
// merge the `cardStyles` with the `cssProp` passed in
<div className={css(cardStyles, cssProp)}>
<h1>{title}</h1>
<p>{description}</p>
</div>
)
}
// usage
function Demo() {
return (
<Card
title="Hello World"
description="This is a card component"
css={{ bg: 'blue' }}
/>
)
}
If you use any other prop name other than css
, then you must use the css.raw(...)
function to ensure Panda extracts the style object.
const cardStyles = css.raw({
bg: 'red',
color: 'white'
})
function Card({ title, description, style }) {
return (
// merge the `cardStyles` with the `style` passed in
<div className={css(cardStyles, style)}>
<h1>{title}</h1>
<p>{description}</p>
</div>
)
}
// usage
function Demo() {
return (
<Card
title="Hello World"
description="This is a card component"
// use `css.raw(...)` to ensure Panda extracts the style object
style={css.raw({ bg: 'blue' })}
/>
)
}