Tue Jul 01 2025

v5 Announcement

migrationnativewindv5upgrade

A comprehensive guide to upgrading from Nativewind v4 to v5, including breaking changes, new features, and migration steps.

Note: Nativewind v5 is currently available in preview. You can install it with nativewind@preview.

Welcome to the official upgrade guide for Nativewind v5. This release introduces several foundational changes that align Nativewind with the future of React Native while maintaining backward compatibility with the core API.

Note: Nativewind v5 includes breaking changes in its underlying dependencies and internal architecture. Please review all sections carefully before upgrading.

Quick Migration Steps

The simplest way to migrate from Nativewind v4 to v5 is to follow these steps:

Step 1: Update Dependencies

Install the new versions of required packages:

# Using Expo CLI (recommended)
npx expo install nativewind@preview react-native-css react-native-reanimated react-native-safe-area-context
 
# Install Tailwind CSS v4 and PostCSS as dev dependencies
npx expo install --dev tailwindcss @tailwindcss/postcss postcss

Step 2: Update CSS File

Replace your old CSS directives with the new Tailwind v4 imports in your global.css (or equivalent):

/* OLD - Remove these */
@tailwind base;
@tailwind components;
@tailwind utilities;
 
/* NEW - Add these */
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css";
 
@import "nativewind/theme";

Step 3: Update Babel Config

Remove Nativewind from your babel.config.js:

module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
-      ["babel-preset-expo", { jsxImportSource: "nativewind" }],
-      "nativewind/babel",
+      "babel-preset-expo",
    ],
  };
};

Step 4: Create PostCSS Config

Create a postcss.config.mjs file in the root of your project:

// postcss.config.mjs
export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

Step 5: Update Metro Config

Update the withNativewind function call (no longer requires a second argument):

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

Step 6: Clear Cache and Restart

npx expo start --clear

Troubleshooting Common Issues

If you encounter issues, here are some common problems and solutions:

JSX Transform Errors: Ensure you removed nativewind from your babel config and cleared the Metro cache with npx expo start --clear.

Incorrect CSS atRules: Verify you updated to the new atRules in your CSS file (see Step 2 above).

Metro Config Issues: The withNativewind function no longer requires a second argument. Ensure your config matches Step 5.

Missing PostCSS Config: Ensure the postcss.config.mjs file was created with the correct content.

Breaking Changes & Prerequisites

Before upgrading to Nativewind v5, your project must meet the following version requirements:

Tailwind CSS v4.1+

Nativewind v5 is built on top of Tailwind CSS v4.1+. You must upgrade your Tailwind configuration and tooling accordingly.

Migration Tip: Refer to the Tailwind CSS v4 Upgrade Guide for detailed steps.

React Native 0.81+

React Native 0.81 introduces architectural changes that Nativewind v5 relies on, including improvements to the StyleSheet and layout engines.

Use react-native upgrade or migrate your setup manually to update.

Earlier versions of React Native may work with limited functionality. However, Nativewind only provides support for React Native 0.81+.

React Native New Architecture

A number of styles require the new architecture.

The old architecture may work with limited functionality. However, Nativewind only provides support for the new React Native architecture.

React Native Reanimated v4+

Nativewind v5 uses internal features that depend on Reanimated v4+. Ensure your project uses this version to avoid runtime crashes or build issues.

Note: Reanimated v4 introduces its own breaking changes — consult the Reanimated v4 changelog when upgrading.

React Native CSS

Nativewind previously used a transient dependency on a library called react-native-css-interop. This library has been renamed to react-native-css and moved to a peerDependency and will require installation.

Nativewind will no longer be tied to a specific version of react-native-css and the two libraries can be updated individually.

No Runtime Breaking Changes — But Some Deprecations

Nativewind v5 preserves its existing API. Your usage of:

  • className
  • styled

...will continue to work without modification.

However, several features are being deprecated and will emit runtime warnings during development. These features will be removed in a future major release.

Warning: Deprecated features will continue to function in v5 but should be migrated away from as soon as possible.

However, there will be a number of breaking changes to how Nativewind functions and its configuration file that may affect you.

Breaking Changes

Tailwind CSS Changes

Please ensure you are familiar with the Tailwind CSS upgrade guide. It has a number of breaking changes, renamed styles and deprecations.

Classname Changes

Tailwind v4 changed the standard for its classnames. As such, these Nativewind classes have also been renamed:

  • elevation-sm has been renamed to elevation-xs
  • elevation has been renamed to elevation-sm

Animation Changes

Nativewind has switched from using a custom animation engine to Reanimated CSS animations. You may find there are implementation differences between the two engines.

Line Height

Line height numeric values are parsed as if they had the em unit. Previously they were parsed as a unit-less value. To migrate, simply divide the old value by the font-size.

rem

rem is no longer exported and cannot be changed at runtime. If you require Tailwind CSS to dynamically change values, you should update your theme to use a CSS variable instead of rem.

Dynamic Mapping Modifier

The dynamic mapping modifier has been renamed to @prop:

- {}-[inputColor]:color-black
+ @prop-[inputColor]:color-black

JSX Transform → Replaced by Import Rewrites

Nativewind v5 removes the JSX transform that previously injected Tailwind support into individual JSX elements. This has been replaced by a new import rewrite system.

This does not require any configuration change, but may affect your app if you are performing your own import rewrites. Previously Nativewind would change this code:

import { View, Text } from 'react-native';
 
<View className="bg-red-500 p-4">
  <Text className="text-white">Hello</Text>
</View>

Now the import will be rewritten to import { View, Text } from 'react-native-css/react-native'

The move to import rewrites is driven by a broader shift in the React Native ecosystem of publishing compiled libraries. Nativewind previously took advantage that libraries were always compiled locally which allowed us to override the jsxImportSource. When libraries are compiled externally, their JSX is already transformed. The new shift to import rewrites is similar to how existing libraries such as react-native-web work.

cssInterop / remapProps → Replaced by styled()

The cssInterop and remapProps APIs are deprecated and replaced with a unified styled API. It accepts the same options as cssInterop/remapProps and returns the same component. The remapProps mode is available via a new 3rd parameter:

// Same as cssInterop()
styled(View, { className: 'style'})
 
// Same as remapProps()
styled(View, { className: 'style'}, { passThrough: true })

By default styled() enables the transform globally for that component, but this can be disabled by setting global to false:

const MyComponent = styled(View, { className: 'style'}, { global: false })

shadow-*

The shadow-* classes now use boxShadow style. Previously they used shadowColor, shadowOffset, shadowOpacity and shadowRadius. There may be a visual difference.

Native Functions → CSS Functions

The nativewind/theme export has been removed. You can now access these functions as CSS functions.

If you are using the new Tailwind CSS v4 CSS config file, you are unable to import the nativewind/theme functions. These have been replaced with custom CSS.

platformColor

platformColor() is available as a CSS function:

@theme {
  --color-error: platformColor(systemRed, red)
}

hairlineWidth

hairlineWidth() is available as a CSS function:

@theme {
  --spacing-hairline: hairlineWidth()
}

pixelRatio

pixelRatio() is available as a CSS function:

@theme {
  --spacing-doublePixelRatio: calc(pixelRatio(2) * 2)
}

fontScale

fontScale() is available as a CSS function:

@theme {
  --spacing-doubleFontScale: calc(fontScale(2) * 2)
}

getPixelSizeForLayoutSize

getPixelSizeForLayoutSize() is available as a CSS function:

@theme {
  --spacing-custom: getPixelSizeForLayoutSize(42)
}

roundToNearestPixel

roundToNearestPixel() is available as a CSS function:

@theme {
  --spacing-custom: roundToNearestPixel(calc(10 / 3))
}

platformSelect

Now use a media query that sets the platform as the media type:

@theme {
  --color-error: var(--my-color, green)
}
 
@media ios {
  :root {
    --my-color: red;
  }
}
 
@media android {
  :root {
    --my-color: blue;
  }
}

pixelRatioSelect / fontScaleSelect

Now use a media query:

@theme {
  --spacing-custom-pixel: 11;
  --spacing-custom-font: 11;
}
 
@media (pixelRatio() > 2) {
  :root {
    --spacing-custom-pixel: 3;
  }
}
 
@media (fontScale() > 2) {
  :root {
    --spacing-custom-font: 3;
  }
}

New CSS Features

Nativewind v5 adds support for the new React Native styling features: