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
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.
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>
)
}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.
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:
:global() to disable generated classnames, which makes the CSS really verbose and hard to read.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.
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_! ๐ ๐
Was looking at the styling tools for Next.js that are App router compatible, and there still isn't an ideal solution for me.. โ CSS modules: no child selectors like it's 2005 - SCSS modules: child selectors work but need wrapping every child class in :global() to disableย Show more