Skip to content

Want to skip the docs? Check out pandamastery.com - the best way to learn Panda CSS

Migration

Migrating from Styled Components

Migrate your project from Styled Components to Panda.

This guide outlines the steps needed to migrate your project from Styled Components to Panda and highlights key design differences between the two libraries.

💡

Disclaimer: This isn't about comparing which one is best. Panda and Styled Components are two different CSS-in-JS solutions with design decisions.

Here are some similarities between the two libraries.

  • Both libraries give you a styled factory for creating styled components.
  • Both libraries provide a way to define design tokens (variables) and use them in your styles.
  • Both libraries require the use of & for nested selectors.

Below are some differences between the two libraries.

Installation

Initialize a project with the following command.

panda init -p --jsx-framework react

Then you need to add the cascade layers to the global styles of your project.

@layer reset, base, tokens, recipes, utilities;

Styling components

In styled-components, you can style a component with tagged template literals or with an object.

import styled from 'styled-components'
 
const Button = styled.button`
  background-color: #fff;
  border: 1px solid #000;
  color: #000;
  padding: 0.5rem 1rem;
`
 
const OtherButton = styled.button({
  backgroundColor: '#fff',
  border: '1px solid #000',
  color: '#000',
  padding: '0.5rem 1rem'
})

Panda takes style objects only. Import the styled factory from the styled-system directory Panda generates at the root of your project, and put the styles in the base key. The same factory defines variants and compound variants.

import { styled } from '../styled-system/jsx'
 
const Button = styled('button', {
  base: {
    backgroundColor: '#fff',
    border: '1px solid #000',
    color: '#000',
    padding: '0.5rem 1rem'
  }
})

Prop Interpolation

In styled-components, you can interpolate the component's props to conditionally set styles.

const Button = styled.button`
  ${props =>
    props.color === 'violet' &&
    `
    background-color: 'blueviolet'
  `}
 
  ${props =>
    props.color === 'gray' &&
    `
    background-color: 'gainsboro'
  `}
`

In Panda, we model interpolations using the variants API. This allows define style groups or recipes that can be applied to components.

const Button = styled('button', {
  variants: {
    color: {
      violet: { backgroundColor: 'blueviolet' },
      gray: { backgroundColor: 'gainsboro' }
    }
  }
})
 
// Usage
<Button color="violet">Button</Button>

Tokens and Themes

Defining Tokens

In styled-components, you can define tokens in a theme object that is passed to the ThemeProvider. This requires the use of React's context API to access the theme object in your styles

import { ThemeProvider } from 'styled-components'
 
const theme = {
  colors: {
    primary: 'blue',
    secondary: 'red'
  }
}
 
const App = () => (
  <ThemeProvider theme={theme}>
    <Button>Button</Button>
  </ThemeProvider>
)

In Panda, you define tokens in the theme key of the panda.config.ts file. This allows you to access the tokens in your styles without the need for React's context API.

// panda.config.ts
import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  theme: {
    extend: {
      tokens: {
        colors: {
          primary: { value: 'blue' },
          secondary: { value: 'red' }
        }
      }
    }
  }
})

Using Tokens

In styled-components, you can use tokens in your styles using a function approach that provides the theme prop, and requires ambient type declarations to get type safety.

import styled from 'styled-components'
 
// link.tsx
const StyledLink = styled.a(({ theme }) => ({
  color: theme.colors.primary,
  display: 'block',
  textDecoration: 'none'
}))
 
// theme.d.ts
declare module 'styled-components' {
  export interface DefaultTheme {
    colors: {
      primary: string
      secondary: string
    }
  }
}

In Panda, the tokens are automatically available in your styles and connected to each css property, removing the need for an interpolation function.

// panda.config.ts
import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  theme: {
    // extend the base theme
    extend: {
      tokens: {
        // add custom colors
        colors: {
          primary: { value: 'blue' },
          secondary: { value: 'red' }
        }
      }
    }
  }
})
 
// link.tsx
import { styled } from '../styled-system/jsx'
 
const StyledLink = styled('a', {
  base: {
    color: 'primary',
    display: 'block',
    textDecoration: 'none'
  }
})

Responsive Styles

In styled-components, you write the media query manually or use a helper function like styled-media-query.

import styled from 'styled-components'
import media from 'styled-media-query'
 
const Button = styled.button({
  backgroundColor: '#fff',
  border: '1px solid #000',
  color: '#000',
  padding: '0.5rem 1rem',
 
  [media.greaterThan('medium')]: {
    padding: '1rem 2rem'
  }
})

In Panda, you can use the pseudo props API to define responsive styles.

import { styled } from '../styled-system/jsx'
 
const Button = styled('button', {
  base: {
    backgroundColor: '#fff',
    border: '1px solid #000',
    color: '#000',
    padding: { base: '0.5rem 1rem', md: '1rem 2rem' }
  }
})

Global Styles

In styled-components, you can use the createGlobalStyle function to define global styles.

import { createGlobalStyle } from 'styled-components'
 
const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    padding: 0;
  }
`

In Panda, you can use the globalCss key of the panda.config.ts file to define global styles. This will automatically add styles to the project via PostCSS.

// panda.config.ts
import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  globalCss: {
    body: {
      margin: 0,
      padding: 0
    }
  }
})

Targeting Components

In styled-components, you can target existing styled components within the styled function

import styled from 'styled-components'
 
const Link = styled.a`
  background: papayawhip;
  color: #bf4f74;
`
 
const Icon = styled.svg`
  width: 48px;
  height: 48px;
 
  ${Link}:hover & {
    fill: rebeccapurple;
  }
`

In Panda, you need to use the native selector directly. This is largely due to the static nature of Panda

import { styled } from '../styled-system/jsx'
 
const Link = styled('a', {
  base: {
    background: 'papayawhip',
    color: '#bf4f74'
  }
})
 
const Icon = styled('svg', {
  base: {
    width: '48px',
    height: '48px',
    '.Link:hover &': {
      fill: 'rebeccapurple'
    }
  }
})
 
const App = () => (
  <Link className="Link">
    <Icon />
  </Link>
)

Animations

In styled components, you can define keyframes using the keyframes method.

import styled, { keyframes } from 'styled-components'
 
const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }
 
  to {
    transform: rotate(360deg);
  }
`
 
// usage
const Button = styled.button`
  &:hover {
    animation: ${rotate} 200ms;
  }
`

In Panda, you define keyframes in the theme.keyframes key of the panda.config function.

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  theme: {
    extend: {
      keyframes: {
        rotate: {
          from: {
            transform: 'rotate(0deg)'
          },
          to: {
            transform: 'rotate(360deg)'
          }
        }
      }
    }
  }
})
 
// usage
import { styled } from '../styled-system/jsx'
 
const Button = styled('button', {
  base: {
    '&:hover': {
      animation: 'rotate 200ms'
    }
  }
})

Server-Side Rendering

In styled components, you need to configure the server-side rendering for your framework.

import { renderToString } from 'react-dom/server'
import { ServerStyleSheet } from 'styled-components'
 
const sheet = new ServerStyleSheet()
try {
  const html = renderToString(sheet.collectStyles(<YourApp />))
  const styleTags = sheet.getStyleTags() // or sheet.getStyleElement();
} catch (error) {
  // handle error
  console.error(error)
} finally {
  sheet.seal()
}

In Panda, you don't need to configure anything. Panda automatically extracts the styles and injects them at build time using PostCSS.

Conclusion

Before choosing your preferred CSS-in-JS library, be sure to consider your engineering and design goals. Both Styled components and Panda are capable of achieving many of the same styling goals, but they have different approaches.

Edit this page on GitHubView as markdown
Last updated on