Back to blog

Setting Up Tailwind CSS with NativeWind in Expo

Setting Up Tailwind CSS with NativeWind in Expo: A Simplified Approach

This has been on my mind lately as I navigate frontend development in React Native using Expo. Whenever I encounter a new library or framework, I always worry about version mismatches and setup issues. After several frustrating hours trying to get NativeWind working with Tailwind CSS in an Expo project, I've simplified it down to a few key steps.

The First Steps

For those still struggling, here’s what we’re going to do:

  1. Install the Necessary Packages
  2. Set Up Tailwind CSS Properly
  3. Configure Babel and Metro
  4. Import Your CSS File Correctly
  5. Tweak app.json for Web Builds (Optional)
  6. TypeScript Setup (Optional)

Install the Necessary Packages

Let's start by installing just what we need, not everything in the world:

npm install nativewind
npm install --dev tailwindcss prettier-plugin-tailwindcss

These are the bare essentials to get Tailwind and NativeWind up and running. No extra dependencies or version conflicts.

Set Up Tailwind CSS Properly

Next, we need to set up Tailwind CSS in a way that works with NativeWind:

  1. Generate the tailwind.config.js file:
npx tailwindcss init -p
  1. Configure your tailwind.config.js file correctly:
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/**/*.{js,jsx,ts,tsx}", "./pages/**/*.{js,jsx,ts,tsx}"],
  presets: [require("nativewind/preset")],
  theme: {
    extend: {},
  },
  plugins: [],
};
  1. Create a global.css file and add the Tailwind directives:
@tailwind base;
@tailwind utilities;
@tailwind themes;

Configure Babel and Metro

Now, we need to make sure our build tools are aware of these changes:

  1. If you don't have a babel.config.js, create one with this content:
module.exports = function (config) {
  config.set(true);
  return {
    presets: [
      ["@babel-preset-expo", { runtime: "automatic" }],
      "@nativewind/babel-preset"
    ]
  };
}
  1. Create a metro.config.js file if you don’t have one, and add this:
const { defaultConfig } = require("expo/metro-config");
const { withTheme } = require("theming/metro");

const expConfig = defaultConfig(__dirname);

module.exports = withTheme(expConfig, { themeFile: "./theme.css" });

Import Your CSS File

Ensure that your global.css file is imported at the root of your app:

import "./styles.css";

export default function MyApplication() {
  /* Your Application Logic Here */
}

Tweak app.json for Web Builds (Optional)

If you’re working on a project with both web and native builds, make sure Metro is used for web builds in app.json:

{
  "react-native": {
    "ios": {
      "packagerConfig": "metro"
    }
  }
}

TypeScript Setup (Optional)

For those using TypeScript, create a nativewind-env.d.ts file at the root of your project and add this:

/// <reference types="nativewind/types" />

Result

That's it. By following these steps, you should be able to set up Tailwind CSS with NativeWind in an Expo project without running into version conflicts or setup issues. The only real difference is that I skipped the extra packages and fixed versions recommended by some official documentation.

Happy styling! 🚀