Choosing a CSS-in-JS solution for Next.js v14

黃子洋
4 min readJan 20, 2024

Background

Recently, our Frontend team decided to adopt Next.js for a new project. We decided to use AppRouter from Next.js v14 to leverage the power of React Server Component (RSC).

For our styling engine, we originally used styled-components since we love how CSS-in-JS benefits us. However, after some investigation, we decided to abandon styled-components. Below are some key reasons for our decision.

Problems of Runtime CSS-in-JS

Potential Runtime Overhead

CSS-in-JS which requires Javascript Runtime will perform the following tasks at runtime

  • Parsing the CSS in the tagged template using stylis at runtime.
  • Generating classNames.
  • Creating a <style> tag and inserting it into <head>
How CSS-in-JS which requires Javascript runtime works

If we overused it, it might provide some runtime overhead

Also, we need stylis which is a package for parsing the CSS specified in our tagged template at runtime that would increase our bundle size a little bit.

Performance is a key focus of this project. Therefore, it is important for us to minimize runtime tasks and minimize the JavaScript bundle delivered to our frontend.

Incompatibility with React Server Component

This will be the primary reason for our decision to discontinue the use of runtime CSS-in-JS.

According to the documentation of Next.js, CSS-in-JS, which relies on a JavaScript runtime, is currently not supported in React Server Components.

With the introduction of AppRouter in Next.js version 14, the components we create by default are Server Components. If we opt to continue using styled-components as our styling engine, we would have to declare all our components to be Client Component which is not a thing that we want.

Welcome to Zero Runtime CSS-in-JS

We still love CSS-in-JS and want to continue using it. So we found some guys who are called Zero Runtime CSS-in-JS, what is it?

Below is how Zero Runtime CSS-in-JS works

One of the key differences compared to traditional CSS-in-JS is that the styles are generated at build time instead of run time which we do not need additional runtime operations for injecting styles.

Some Zero runtime CSS-in-JS also provides the optimization for generating atomic CSS for the output .css file which creates highly reusable classes. For more information about atomic CSS, you can check here.

Here are a few candidates for Zero runtime CSS-in-JS. Let’s delve into aspects such as their ease of integration with Next.js 14 and other relevant points.

PandaCSS

PandaCSS is created by Chakra-UI, It generates atomic CSS at build time via PostCSS or its own CLI tool

Pros

1.Ease of integration with Next.js 14 App Router

PandaCSS provides an official guide integrating with Next.js v14 which is extremely simple

2. Syntax similarity to styled-components

If you are acquainted with styled-components, transitioning to PandaCSS is straightforward due to its similar syntax. PandaCSS offers two syntax options: object-literal or template-literal. You can customize this in the configuration file; further details can be found here. I personally love object-literal better.

Cons

  1. Limited to dynamic styling

Due to PandaCSS generates CSS statically, itis limited to dynamic styling, we cannot use runtime variables as values. We can still use runtime variables as conditions to decide which style we are going to apply.

StyleX

StyleX is created by Meta, It also generates atomic CSS at build time using Babel.

Pros

  1. Simplicity

StyleX is simple enough, we mainly use two of its core APIs for creating and applying styles

2. Supports dynamic styling

Unlike PandaCSS which only supports conditional styling, StyleX supports using runtime values as CSS property values by setting the value of the CSS variable at runtime.

For more information, you can check here

Cons

  1. Limitation with Next.js v14

Since StyleX needs Babel to generate atomic CSS at build time, this also means we opt out of Next.js’s compiler which is required for some Next.js features like next/font . You might encounter an error when you use both StyleX and next/font

Since there is no solution for now
https://github.com/facebook/stylex/discussions/133#discussioncomment-7837681

2. Limited set of APIs

If you are looking for styled-components like APIs, StyleX might not be a good fit. It does not provide an API to create a component like below.

style.div`
backgroundColor: 'blue';
// ... other CSS properties
`

It might appear contradictory, as simplicity is highlighted as one of the pros; however, it just depends on different individual’s needs.

My Choice

I have chosen PandaCSS as it aligns well with our team’s preferences which are

  • Integrates well with Next.js v14
  • Offers syntax familiarity, given our previous experience with styled-components.

I plan to write a more in-depth article introducing PandaCSS in the future.

Conclusion

Zero runtime CSS-in-JS has grown a lot in the recent years

The choice of a styling engine is subjective and there’s no definitive right or wrong. It hinges on the specific needs of you or your team.

Last but not least, there are other Zero runtime CSS-in-JS libraries, such as Linaria which is also really good for researching it.

Hope this article helps.

--

--