Skip to main content

Overview

This guide helps you migrate between different versions of NativeWind. NativeWind has evolved significantly, with major changes between v2, v4, and v5.
NativeWind v5 is currently in preview. For production apps, use NativeWind v4.1, which is stable and fully supported.

Version Overview

v2 (Legacy)

Original version using custom runtime

v4.1 (Stable)

Current stable release with Tailwind CSS v3 support

v5 (Preview)

Preview release with Tailwind CSS v4 support

Quick Start New Projects

For new projects, use the quickstart templates:
npx rn-new@latest --nativewind

Migrating from v2 to v4

NativeWind v4 introduced significant changes to improve performance and compatibility.
1

Update dependencies

Update to the latest v4 release:
npm install nativewind@^4.1.23
npm install --save-dev tailwindcss@^3.4.0
v4 uses Tailwind CSS v3, while v5 uses Tailwind CSS v4
2

Update configuration

The configuration API changed in v4. Update your configs:Before (v2):
tailwind.config.js
module.exports = {
  content: ["./App.{js,jsx,ts,tsx}", "./src/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
}
After (v4):
tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./App.{js,jsx,ts,tsx}", "./src/**/*.{js,jsx,ts,tsx}"],
  presets: [require('nativewind/preset')],
  theme: {
    extend: {},
  },
  plugins: [],
}
3

Update Metro config

v4 requires Metro configuration:
metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, { input: './global.css' });
4

Create CSS entry file

Create global.css:
global.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Import it in your app entry:
App.tsx
import "./global.css";
5

Update hook usage

Some hooks changed in v4:Before (v2):
import { useColorScheme } from 'nativewind';
After (v4):
import { useColorScheme } from 'react-native';
6

Check for breaking changes

Review the v4 changelog for breaking changes affecting your code.

Migrating from v4 to v5 (Preview)

NativeWind v5 adopts Tailwind CSS v4’s new CSS-first configuration system.
v5 is in preview and APIs may change. Only use for experimental projects.
1

Update dependencies

Install v5 preview and Tailwind CSS v4:
npm install nativewind@next
npm install --save-dev tailwindcss@next @tailwindcss/postcss
npm install react-native-css@latest
Check peer dependencies:
package.json
{
  "dependencies": {
    "nativewind": "^5.0.0-preview.2",
    "react-native-css": "^3.0.1"
  },
  "devDependencies": {
    "tailwindcss": "^4.1.12",
    "@tailwindcss/postcss": "^4.1.11"
  }
}
2

Migrate to CSS-based configuration

Remove tailwind.config.js and create global.css:Before (v4 - tailwind.config.js):
module.exports = {
  content: [...],
  theme: {
    extend: {
      colors: {
        primary: '#3b82f6',
      },
    },
  },
}
After (v5 - global.css):
global.css
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css";
@import "nativewind/theme";

@theme {
  --color-primary: #3b82f6;
}
3

Update Metro config

The Metro wrapper API is simpler in v5:Before (v4):
metro.config.js
module.exports = withNativeWind(config, { input: './global.css' });
After (v5):
metro.config.js
module.exports = withNativewind(config);
4

Add PostCSS config

Create postcss.config.mjs:
postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};
5

Update custom utilities

Custom utilities now use CSS @utility directive:Before (v4 - tailwind.config.js):
module.exports = {
  theme: {
    extend: {
      elevation: {
        sm: 3,
        md: 6,
        lg: 8,
      },
    },
  },
}
After (v5 - global.css):
@theme {
  --elevation-sm: 3;
  --elevation-md: 6;
  --elevation-lg: 8;
}

@utility elevation-* {
  -rn-elevation: --value(--elevation-*);
}
6

Update plugin usage

Plugins are now imported in CSS:Before (v4):
tailwind.config.js
plugins: [require('tailwindcss-safe-area')]
After (v5):
global.css
@import "tailwindcss-safe-area";

Breaking Changes by Version

v4.1.23 (Latest Stable)

Patch Changes:
  • Fixed incorrect template string in platformPath
  • Updated dependencies: react-native-css-interop@0.1.22
No breaking changes - safe to upgrade from any v4.1.x version

v4.1.22

Patch Changes:
  • Fixed building apps locally on Windows
  • Fixed crash when react-native-safe-area-context is not installed
  • Changed lightningcss to be a version range
  • Updated dependencies: react-native-css-interop@0.1.21
Migration: If you rely on safe area utilities without having react-native-safe-area-context installed, this version now handles it gracefully.

v4.0.0

Breaking Changes:
  1. Configuration: Requires Metro and Babel setup
  2. Tailwind Config: Must use nativewind preset
  3. CSS Entry: Requires global.css import
  4. Hooks: Some hooks moved to React Native core
  5. Build-time Processing: Styles now compiled at build time
Benefits:
  • Significantly better performance
  • Smaller bundle size
  • Better compatibility with React Native updates
  • Support for all Tailwind features

v2.0.11 and Earlier

v2.0.11:
  • Fixed useInteraction types
  • Added missing flexBasis from flex-1
v2.0.10:
  • Fixed “unable to find styles” console warning
v2.0.9:
  • Fixed compiling styles during mode:transformOnly
v2.0.8:
  • Fixed cache invalidation for tailwind.config.js
v2.0.7:
  • Removed addExternalDependency from babel
v2.0.6:
  • Fixed null values when rendering styled children

Platform-Specific Migration

Expo Projects

1

Update Expo SDK

Ensure you’re on Expo SDK 54+:
npx expo install expo@latest
2

Update app.config.ts

No specific NativeWind configuration needed in app.config.ts, but ensure you have:
app.config.ts
export default ({ config }: ConfigContext): ExpoConfig => {
  return {
    ...config,
    userInterfaceStyle: "automatic", // For dark mode support
  };
};

React Native CLI Projects

1

Update React Native

npx react-native upgrade
2

Update Metro config

metro.config.js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const { withNativewind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);
module.exports = withNativewind(config);

Common Migration Issues

Solution:
  1. Clear Metro cache: npx expo start --clear
  2. Verify global.css is imported in your app entry
  3. Check Metro config includes withNativewind
  4. Ensure all dependencies are correct versions
Solution:
  1. Delete nativewind-env.d.ts
  2. Restart Metro: npx expo start --clear
  3. Restart TypeScript server in your IDE
  4. Verify nativewind-env.d.ts is regenerated and included in tsconfig.json
Solution:
  1. Delete node_modules and lockfile
  2. Run clean install: npm ci or yarn install
  3. Clear all caches: npx expo start --clear
  4. For iOS: cd ios && pod install && cd ..
  5. Rebuild: npx expo run:ios or npx expo run:android
Solution: Migrate theme configuration to CSS:
global.css
@theme {
  /* Your custom theme tokens */
  --color-brand: #3b82f6;
  --spacing-custom: 1.5rem;
}

Testing After Migration

Verify your migration was successful:
1

Visual inspection

  1. Run your app: npm start
  2. Check all screens render correctly
  3. Test dark mode if you use it
  4. Verify custom colors and spacing
2

Test platform-specific styles

<View className="ios:bg-blue-500 android:bg-green-500">
  <Text>Platform test</Text>
</View>
3

Verify TypeScript

  1. Check no type errors in IDE
  2. Run: npx tsc --noEmit
  3. Verify className prop is typed
4

Run existing tests

npm test

Getting Help

If you encounter issues during migration:

Troubleshooting Guide

Common issues and solutions

GitHub Issues

Report bugs or ask questions

Discord Community

Get help from the community

Contributing

Contribute fixes and improvements

Next Steps

Configuration

Fine-tune your setup

TypeScript

Configure TypeScript

Custom Styles

Create custom utilities