Back

Bringing Tailwind CSS to React Native with NativeWind

Bringing Tailwind CSS to React Native with NativeWind

If you’ve built web apps with Tailwind CSS, switching to React Native’s StyleSheet API feels like a step backward. You lose the utility-first workflow, the familiar class names, and the speed. NativeWind closes that gap by bringing Tailwind-style styling to React Native — without requiring a browser or a CSS engine.

This article explains how NativeWind works, what the current stable version gives you, and where the real boundaries are.

Key Takeaways

  • NativeWind translates Tailwind CSS class names into React Native StyleSheet objects, giving you a utility-first workflow on mobile without a CSS engine.
  • NativeWind v4 is the current production-ready version, targeting Tailwind CSS v3 — not v4. A v5 preview aligned with Tailwind v4 exists but is not yet the default.
  • NativeWind uses a jsxImportSource transform alongside its Babel integration, making className composable with utilities like clsx and cn.
  • NativeWind supports dark mode, group variants, and most common Tailwind utilities, but breakpoints, shadows, and animations behave differently on native platforms.

What NativeWind Actually Does

React Native has no CSS engine. Every style must be a JavaScript object passed to a style prop. NativeWind sits between your code and that requirement: you write className strings using Tailwind syntax, and NativeWind compiles and applies those styles for React Native — combining build-time processing with a lightweight runtime layer for conditional styling.

The result looks like this:

<View className="flex-1 items-center justify-center bg-blue-500">
  <Text className="text-white text-lg font-bold">Hello</Text>
</View>

This is not Tailwind CSS running natively. It’s NativeWind interpreting Tailwind’s class vocabulary and mapping it to styles React Native understands. The distinction matters when you hit the edges.

NativeWind v4: The Stable Production Path

As of early 2026, NativeWind v4 is the production-ready version. It targets Tailwind CSS v3 — not v4. A v5 preview exists that aligns with Tailwind v4, but it is not the default path yet. If you’re starting a new project, use NativeWind v4 with tailwindcss@^3.4.

NativeWind v4 introduced a more predictable architecture built around a jsxImportSource transform while still integrating with Babel. In practice, this means:

  • The className prop is preserved on components, not stripped at build time
  • You can use utilities like clsx or cn directly with className
  • Setup is more consistent across Metro and other tooling

NativeWind v4 also introduced its own StyleSheet import, which extends React Native’s built-in version. It handles merging style and className props cleanly — something the default StyleSheet struggles with for transforms and shadows.

NativeWind Setup with Expo

Expo is the most common environment for NativeWind, and it provides the smoothest setup experience. The high-level steps are:

  1. Install nativewind, react-native-reanimated, react-native-safe-area-context, and tailwindcss@^3.4 as dependencies
  2. Run npx tailwindcss init and add nativewind/preset to your Tailwind config
  3. Create a global.css with the standard Tailwind directives (@tailwind base;, @tailwind components;, @tailwind utilities;) and import it in your app entry point
  4. Configure babel.config.js with jsxImportSource: "nativewind" and include the NativeWind Babel plugin
  5. Wrap your Metro config with withNativeWind

For TypeScript projects, add a nativewind-env.d.ts file with /// <reference types="nativewind/types" /> to get proper className prop support on native components.

If you want to skip configuration entirely, npx rn-new --nativewind scaffolds a minimal Expo project with NativeWind already wired up.

Dark Mode, Variants, and Real Limitations

NativeWind v4 supports the dark: variant through a useColorScheme hook that returns colorScheme, setColorScheme, and toggleColorScheme. You apply dark mode styles exactly as you would on the web:

<Text className="text-gray-900 dark:text-white">Label</Text>

Group variants work too — a Pressable with className="group" can drive child styles via group-active: or group-hover:.

Where it diverges from web Tailwind:

  • Breakpoints don’t map cleanly to mobile screens. Tailwind’s sm:, md:, lg: prefixes are designed for viewport widths, not device form factors. For responsive mobile layouts, you’ll often reach for React Native’s Dimensions API or useWindowDimensions hook instead.
  • Some style props require alternative APIs. For example, list-specific styling like columnWrapperStyle may still be handled outside className, depending on the component.
  • Shadows behave differently on native. React Native uses platform-specific shadow properties (shadowColor, shadowOffset, shadowOpacity, shadowRadius on iOS and elevation on Android), so the result is not equivalent to CSS box-shadow.
  • Animations via utility classes are experimental and inconsistent between iOS and Android. For anything complex, use React Native Reanimated directly.

Conclusion

NativeWind is a translation layer, not a CSS runtime. It gives you Tailwind’s vocabulary and workflow in a React Native context, which is genuinely useful — especially for teams already fluent in Tailwind. But it doesn’t erase the platform boundary. You’ll still write occasional style props, work around native-only constraints, and think in React Native’s layout model.

For most Tailwind-familiar developers, that tradeoff is worth it. The productivity gain from utility-first styling in React Native is real, and NativeWind v4 is stable enough to ship with.

FAQs

Yes, NativeWind works with bare React Native projects. The setup requires manually configuring Metro bundler with the withNativeWind wrapper and ensuring your Babel config includes the jsxImportSource setting. Expo simplifies this process, but it is not a hard requirement. You will need to handle native module linking yourself in a bare project.

NativeWind v4 supports custom themes defined in your tailwind.config.js, including custom colors, spacing, fonts, and breakpoints. Most standard Tailwind plugins that generate utility classes work as expected. However, plugins that rely on browser-specific CSS features like pseudo-elements or CSS Grid may not translate to React Native styles.

NativeWind provides platform variants such as ios: and android: that let you apply styles conditionally based on the running platform. For example, you can write className with ios:shadow-lg android:elevation-4 to target each platform separately. This mirrors how React Native developers typically handle platform differences using the Platform API.

NativeWind uses a mix of build-time compilation and runtime style resolution. While much of the styling is optimized and cached, there is still some runtime overhead for handling conditional and dynamic classes. In most applications, the performance difference is negligible, but it is not purely a zero-cost compile-time transformation. Hot-reload performance during development may be slightly slower due to the additional processing step.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay