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
StyleSheetobjects, 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
jsxImportSourcetransform alongside its Babel integration, makingclassNamecomposable with utilities likeclsxandcn. - 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
classNameprop is preserved on components, not stripped at build time - You can use utilities like
clsxorcndirectly withclassName - 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:
- Install
nativewind,react-native-reanimated,react-native-safe-area-context, andtailwindcss@^3.4as dependencies - Run
npx tailwindcss initand addnativewind/presetto your Tailwind config - Create a
global.csswith the standard Tailwind directives (@tailwind base;,@tailwind components;,@tailwind utilities;) and import it in your app entry point - Configure
babel.config.jswithjsxImportSource: "nativewind"and include the NativeWind Babel plugin - 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.
Discover how at OpenReplay.com.
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’sDimensionsAPI oruseWindowDimensionshook instead. - Some style props require alternative APIs. For example, list-specific styling like
columnWrapperStylemay still be handled outsideclassName, depending on the component. - Shadows behave differently on native. React Native uses platform-specific shadow properties (
shadowColor,shadowOffset,shadowOpacity,shadowRadiuson iOS andelevationon Android), so the result is not equivalent to CSSbox-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.