Use TailwindCSS with Remix without an extra build step!

  • By Darius
  • Last update: Dec 13, 2022
  • Comments: 5


Use TailwindCSS with Remix without an extra build step!


# npm
npm install remix-tailwind tailwindcss postcss

# pnpm
pnpm install remix-tailwind tailwindcss postcss

# yarn
yarn add remix-tailwind tailwindcss postcss


  1. Generate a tailwind config:

    npx tailwindcss init
  2. Create a file at app/routes/tailwindcss.tsx or app/routes/tailwindcss.js:

    import type { LoaderFunction } from "remix"
    import { serveTailwindCss } from "remix-tailwind"
    export const loader: LoaderFunction = () => serveTailwindCss()
  3. Add a link to this route in app/root.tsx:

    export const links: LinksFunction = () => {
      return [{ rel: "stylesheet", href: "/tailwindcss" }]

And that's it! Get styling. ๐Ÿ–Œ

Custom CSS file

remix-tailwind uses a default CSS file, but you can provide a path to your own. The path can be absolute, or relative to the current working directory.

// app/routes/tailwindcss.tsx
import type { LoaderFunction } from "remix"
import { serveTailwindCss } from "remix-tailwind"

export const loader: LoaderFunction = () => serveTailwindCss("app/tailwind.css")
/* app/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

body {
  @apply bg-slate-900 text-slate-100;

How it works

  • Reads your CSS and config when requesting the route
  • Processes tailwind CSS via PostCSS and returns it as a response
  • Remix takes that CSS and applies it to the page (via a link tag, that ol' thing)

In production, the CSS is only built once, and cached on every following request. This is probably fine, but you could consider prebuilding the CSS yourself if you like.



  • 1

    Can't make it to work on

    on dev mode in my local env everything working great but when deployed to I get an error that the mime type is text/html and not text/css even if I set the type attribute on the exported link to text/css it doesn't work

    btw I'm using custom CSS file

  • 2

    feat: support postcss config files


    I used an official package called postcss-load-config that looks for PostCSS config files. All previous tests pass. Let me know what you think about the changes.

  • 3

    A way to add PostCSS plugins

    The package worked great until I added the bg-clip-text class. It didn't work on my browser because the -webkit prefix wasn't added. I created a postcss.config.js file and added tailwindcss and autoprefixer to the plugins hoping it would pick up on that but still no luck.

    I think there could be several solutions to this problem:

    1. Maybe a way for user to add PostCSS plugins when calling serveTailwindCss. (e.g. serveTailwindCss('app/tailwind.css', { postCssPlugins: [autoprefixer] }) - I don't really like this one
    2. Look for a postcss.config.js file and default to the current config if didn't find any.
    3. Accept a path to PostCSS config file. (an alternative to the prior solution - e.g. serveTailwindCss('app/tailwind.css', { postCssConfig: 'postcss.config.js' })

    Also, autoprefixer isn't the only use case for this. there are other plugins that could be used with TailwindCSS. (Reference)

    I could submit a PR for this but I wanted to know what you think about it first.

  • 4

    Caching via URL hash

    Someone brought this up a while ago, and I'd like this capability too. At the moment, the way the API works, you can't get a hashed URL based on the CSS content, like you would if you imported the CSS file normally. Wonder if we can keep remix-tailwind's UX while enabling this :thinking:

  • 5

    Fails on MacOS

    CI run for reference:

    PostCSS has a dependency on fsevents, a mac-only native module, and Remix isn't configured to load .node files through esbuild, so we have a mac-only error.