Styling tools in the age of server components

Jun 7, 2025 Loading...

A while ago I tweeted about styling options that work with server components (SC):

After updating my site, I thought I'd write up some more thoughts here.

TLDR: trying to replace the great DX of EmotionCSS with an RSC friendly alternative is currently not possible

Firstly, TailwindCSS

If you enjoy using TailwindCSS, you're in luck. As it's a compile time tool it works flawlessly with server components.

I enjoy TailwindCSS and use it on all projects, but I also prefer to use a more traditional styling tool for the majority of my components.

What styling tool has the best DX?

For me, it's got to be EmotionCSS 👩‍🎤. Sure CSS-in-JS have inherent performance downsides, but the DX was unbeatable.

Look at this example, it has everything (note in your IDE the css template literal would have syntax highlighting):

// 🔹 resuable composable styles
const reuasableStyle = css`
  font-weight: 600;
`
 
// 🔹 conditional styles based on props and variables
function sectionTitleStyles(props: SectionTitleProps) {
  const localBoolExample = true
  const { large } = props
  return css`
    ${reuasableStyle}
    font-size: ${large ? '18px' : '14px'};
    ${large &&
    css`
      padding: 50px;
      background: papayawhip;
      /* 🔹 nested conditions */
      border: ${localBoolExample ? `2px solid red` : '2px solid orange'};
    `}
    /* 🔹 automatic styling of children  */
    span {
      color: green;
    }
  `
}
 
type SectionTitleProps = {
  large?: boolean
  children: React.ReactNode
  postFix?: string
}
 
// Look at how clean the component is without any conditional increasing its complexity
export const SectionTitle = (props: SectionTitleProps) => {
  const { children, postFix } = props
  return (
    <h3 css={sectionTitleStyles(props)}>
      {children}
      {postFix && <span>{postFix}</span>}
    </h3>
  )
}

My criteria for the ideal styling tool:

  1. CSS syntax (not object styles) - this is a must, I'm not a fan of object styles.
  2. Supports nested styles - SCSS has supported nesting since 2004, this is a non-negotiable (looking at you CSS modules)
  3. Reusuable composable styles - super useful for sharing chunks of styles, keeping everything modular.
  4. Conditional styles based on passed props - passing props into styles directly removes any conditional styling or class toggling from the component itself.
  5. Conditional styles based on variables, nested being a bonus, and full power of JS inside styles
  6. Automatic styling of children with only applying the component styles at the top level. This means not having to assign every style declaration to every element manually like CSS modules. This comes with added risk, but its minimal if you're aware of it and I believe the speed of development benefits outweigh the risk.
  7. Not styled components. Turning a tag into a react component just to add styles is needlessly complex and confuses what are functional react components (with state and props etc) and what are plain tags with styles.

EmotionCSS meets all of these criteria. But its not SC friendly ❌

It's worth noting you won't ever be able to pass dynamic props to styles in any SC friendly styling tool. As it's just not possible to use dynamic values to build time static CSS files. Instead you'll need to use typical style tags, and manually apply the dynamic styles.

So what are the other options

Well there are a lot that are object style based like PandaCSS. But I'm not a fan of object styles.

So what other options are there that allow CSS syntax:

  • SCSS
    • I've used SCSS for years, its epic. Makes me nostalgic for CSS Guidelines. But unfortunately it doesn't automatically style children. You need to manually apply each style to each element. Or child selectors work but need wrapping every child class in :global() to disable generated classnames, which makes the CSS really verbose and hard to read.
  • CSS modules
    • Does not support nested styles
  • EmotionCSS
    • Only works for client components
  • PigmentCSS
    • Almonst perfect (and is powering this site)!
  • Linaria
    • I need to look into this and see if its viable!

PigmentCSS - nearly perfect, but not quite

PigmentCSS is a "zero-runtime CSS-in-JS library that extracts the colocated styles to their own CSS files at build time.". It's actually built on top of EmotionCSS, which is promising as they should echo the DX of EmotionCSS.

Unfortunately whilst it supports CSS Syntax (and that is how I use it for this site), they don't have much documentation for it. Theres even a bug discussing this.

The other major issue is that the CSS Syntax doesn't work in client components. Theres a bug discussing this.

It's also, at time of writing, not been updated since January 2025, so it's not very active.

Linaria - my next attempt

This is a promising tool, been around for a while and recently updated. I need to look into this and see if its viable. I'm hoping it solves my PigmentCSS issues of client components and CSS Syntax.

Josh Comeau is a big fan of it, and it's worked for him in a SC environment, so I'm hopeful.

I'll update this post with my findings over the next month. Watch this space! 😃

If you like React, Next.js or front-end development in general, feel free to follow and say hi on Twitter @_AshConnolly! 👋 🙂