Recommendations for integrating a CSS library?

I’d be curious what the recommendation would be for integrating one of the existing component CSS libraries out there. I’ve read how the webpack config can be modified or extended, but some of these libraries require modifying the Babel loader configuration used for .js files, which I’d be hesitant to do for fear of messing up redwood’s default configuration there. I tried just integrating straight up PostCSS by adding a configuration for processing raw .css files, but ran into issues with that that I was unable to figure out. I just need a decent solution for handling both global and component styling in a redwood app, and am looking for recommendations. Thanks.


Just as a follow-up, I was reading through some other conversations where tailwind.css was mentioned, and I might just roll with that. that looks like it might just give me what I want just loading it from a CDN with no configuration needed, which would be even better.

That being said, I still think there would be value in anyone else replying here with configured solutions for libs like emotion or styled components or whatever.

Hi @ryexley Are you having any luck getting set up?

If you want a Tailwind example, we use it in our Redwood Example Blog. However, it’s a simple implementation that does not use the Tailwind npm package, separate config, etc. But a fully integrated setup like this React App + Tailwind example should be possible right now.

Note: the exception will be adding the package.json build and watch scripts – our CLI command yarn rw dev has it’s own build:watch. You could add the scripts to specifically build the CSS files, but we’d need to discuss what it might look like to integrate a CSS build:watch with our yarn rw dev in order to 1) build/reload when files change and 2) build for deployment :thinking:)

I’ve not used Post CSS, but I looked through this article and didn’t see anything (other than the build:watch scripts) that wouldn’t be possible in Redwood. (And also interesting to see that it’s built-in to Create-React-App…)

Back to your initial question – you’re correct that Redwood doesn’t have a specific recommendation for CSS. Our assumption is that CSS this will be an individual preference. And we’d like to help in any way we can to make sure Redwood works well with existing libraries. So if anyone is attempting to use the examples above or things like Emotion, Styled-Components, provide global style options like Gatsby, etc., let us know how your setup is working and especially how we can help!

I personally like to use styled-components, or chakra-ui (which uses emotion under the hood).

Doesn’t require any tooling setup, works out of the box :slight_smile:


I’ve recently fell in love with, which also doesn’t require any tooling. the sx prop is everything I’ve ever wanted.


Integrating TailwindCSS (via PostCSS with Autoprefixer and PurgeCSS) is pretty straightforward - check out this article:

1 Like

I thought I saw a Theme UI config from jonniebigodes in the GitHub Issues somewhere. Seemed to be working from what I recall but need to check… :thinking:

@mdv_io this is fantastic!! Could you start a new topic here in the “Troubleshooting & How To” category with the title Adding TailwindCSS to RedwoodJS? That way others can more easily find it and try out your article.

Huge thanks in advance :rocket:

You beat me to it! --> How to: Add TailwindCSS to RedwoodJS

I’ve been using utility-based CSS for a few years now (first Tachyons, then Tailwind) and now there’s no going back. I’m building out entire pages without writing a single line of custom CSS, it’s a dream. The Redwood example-blog is styled using Tailwind, although I’m just including the entire stylesheet as a <link> rather than using PostCSS (to keep the additional config in the example to a minimum). You get much more flexibility when including Tailwind the right way.

One drawback to utility-based CSS is that if you decide one day to restyle your entire site you’re in for a rough ride. IN THEORY, with your standard semantic CSS classes, you can restyle your whole site without touching the HTML, just modifying the CSS (like the old In my 20 years of building for the web this has never once happened, so I’m comfortable going the utility-based route.

1 Like

Another good “how-to” article Rob shared with me:

@thedavid forgive me for not replying to this sooner. Yes, I’ve been able to get setup with something that’s working for me. For now, I’ve wired in Material-UI and that seems to be working fine for me for right now. This thread has been fantastic with a lot of great feedback and links, and I’m grateful for that, because I feel confident that it will benefit not just me, but others looking for options along these lines.

The one thing I feel like I should mention that I’ve specifically not seen, which I believe I touched on in my initial question, is advice on how to integrate any CSS-in-JS library that specifically requires any kind of babel plugin for processing files with a .js extension. I ask that because, when extending the webpack configuration, this would require modifying the module handler for .js files, which I’m guessing would likely modify the core of how Redwood’s configuration works, which could have some adverse effects.

It’s not specifically impacting me at the moment, but it is something that I feel like would be something valuable to get feedback on, even if it’s as simple as “don’t worry about it, it won’t impact the RW config at all.”

Roger that and definitely the right kinds of concern. But this is 100% possible. Just guaranteed to be hard, 'cause it’s JS config ¯_(ツ)_/¯

Step 1:
You can extend/modify your App’s babel and webpack config.

Step 2:
How your App settings affect the core settings is hard to determine until you give it a shot. One rule of thumb would be to limit scope (e.g. don’t use babel.config.js unless absolutely necessary) and be very specific with how and where rules are applied. For example, anything that targets all .js files would scare me. But targeting a specific file name or directory gives me a bit more confidence the config will play nice.

When and if you dive in, I suggest you create a new Forum topic and invite the community along for the journey. And then whatever collaborative result you end up with you can share back for others to implement! Worst case scenario we find a limit to RedwoodJS and have a conversation about whether or not this means we need to improve or add things on the backend.

Win. Win.

1 Like

I just integrated Linaria this morning with some trivial changes to Webpack and babel configs, and updated the RW Blog tutorial code to use it.

Would this kind of thing be useful to add to the Cookbook? I’d be happy to add it, if so!

1 Like

Thanks @jmreidy! It could likely live in a couple places, including:

  1. as a stand-along topic here in “How To” and
  2. possibly in a Guide or CSS Cookbook doc that walks through many different setups/sections for CSS (I’ll defer to @rob, but we’re conceiving of “Guides” as short, specific docs and Cookbooks as a lengthier form of Guides that are a bit more instructional but still advanced and specific).

But most of all, of course it would be helpful! Want to get a draft posted for review and discussion about where to post?

@thedavid here’s a draft below! Happy to move it wherever you think best

Redwood is agnostic about how you choose to style your app. Given the opinionated conventions elsewhere in the project, this freedom to bring your own styling approach may be surprising, but given the wide variety of styling choices available, and the tradeoffs amongst those approaches, this flexibility makes more sense. By not prescribing a specific styling approach, Redwood enables better tailoring for specific use cases (whether you’re adopting a component framework like Grommet or Material UI, or optimizing for a traditional external CSS file approach)

Redwood’s scaffolding generator uses Tailwind CSS for styling generated components, but there’s no reason a Redwood user is committed to using Tailwind. In fact, Redwood makes it quite easy to bring your own preferred tool. Let’s examine building the Contact form in the Redwood tutorial with a CSS-in-JS approach.

For this example, we’ll be using Linaria. Linaria differs from other CSS-in-JS approaches with its lack of reliance on a runtime dependency. Instead, Linaria uses the power of CSS variables for enabling dynamic prop based styling in React components, while still generating static CSS files. It also enables co-location of CSS with React components, and creating scoped selectors to keep the styles outside the global scope. For my tastes, it brings the best of both worlds: the full power of CSS, with the logical benefits of co-locating CSS with JS (and enabling dynamic styling). Josh Comeau has a great post exploring the benefits of using CSS variables for CSS-in-JS.

First, we need to add Linaria support to our Redwood project. We’ll be picking up on the redwoodblog tutorial project on the form creation step.

First let’s add our Linaria dependency yarn add linaria. Integrating Linaria with Webpack also introduces dependencies on css-loader and mini-css-extract-plugin, but those are included in Redwood itself.

Now that we have Linaria, the first thing we need to do is get Babel up and running. There’s already a local .babelrc file in your src/web folder which extends the base babel config. The only thing we need to do here is add an additional preset:

module.exports = {
  extends: "../babel.config.js",
  presets: [

Next we need to hook up Webpack. This part is a little less straightforward. First we need to create our own webpack config file extending the Redwood config. You’ll need to add webpack.config.js to web/config - keep in mind the config directory doesn’t exist and you’ll need to add it manually.

Within that new webpack.config.js file, you want to add code to extend the existing webpack config. Specificallyt, we’ll be overwriting the base Redwood module rules, which you can find on Github. JS rules are the third element in rules[0].oneOf array, so we’ll extend the existing rules

module.exports = (config, { env }) => {
  const jsRules = config.module.rules[0].oneOf[2]
  config.module.rules[0].oneOf[2] = {
    use: [
        loader: 'linaria/loader',
        options: {
          sourceMap: env !== 'production',
  return config

Restart your Redwood dev server, and you should be ready to go! Let’s find out.

The redwood blog tutorial asks you to add styling by creating a specific CSS file. But with Linaria, we can drop the files in the same location as our contact form! Within the ContactPage file, add a Linaria import: import { css } from 'linaria'. Next you’ll be dropping in the same style blog as the tutorial:

const stForm = css`
  textarea {
    display: block;
    outline: none;

  label {
    margin-top: 1rem;

  .error {
    color: red;

  textarea.error {
    border: 1px solid red;

Now add your generated scoped class to your form:

    validation={{ mode: 'blur' }}

And that’s it. Linaria does the rest. There’s a lot more exciting ways of using Linaria, which you can find in their docs. But this will get you started!


@jmreidy :man_facepalming:Huge apologies for letting this one drop off the radar. We’ve been focused on docs but still at a foundational level and getting priority docs backfilled.

To ensure this doesn’t get lost any longer, could you create a new topic here in the forum “How To” category? If so, please give it a title heavy on keywords (think SEO) to make it easy for people to find. And we can still use it in the future once we get further along with docs in general. (Oh, you could also add it to the new Awesome Redwood repo as a link to the forum topic… maybe?)

Sorry again. But really appreciate everything you’ve been helping with!

1 Like

New Theme-UI “How To” Article

Walkthrough instructions here --> How to use Theme-UI with RedwoodJS