nativewind
NativeWind
Overview
NativeWind 4.x bridges Tailwind CSS 3.x into React Native, enabling className props on View, Text, Pressable, ScrollView, and other RN components. Provides familiar Tailwind utility classes with native rendering.
Install: pnpm add nativewind tailwindcss@3 + babel/metro configuration
Workflows
Initial setup:
- Install:
pnpm add nativewind tailwindcss@3 - Create
tailwind.config.jswith content paths pointing toapp/,components/, etc. - Create
global.csswith@tailwind base; @tailwind components; @tailwind utilities; - Update
babel.config.js: addnativewind/babelpreset - Update
metro.config.js: wrap withwithNativeWind - Create
nativewind-env.d.tswith/// <reference types="nativewind/types" /> - Import
global.cssin root_layout.tsx
Styling a component:
- Import RN component (View, Text, Pressable, etc.)
- Apply
classNameprop with Tailwind utilities - Use
contentContainerClassNamefor ScrollView/FlashList inner styling - Test on device/simulator to verify rendering
Guidance
Configuration Files
Three config files are required:
babel.config.js: Add NativeWind preset
presets: ['babel-preset-expo', 'nativewind/babel']
metro.config.js: Wrap Metro config with NativeWind
withNativeWind(config, { input: './global.css' })
tailwind.config.js: Standard Tailwind 3.x config with RN content paths
content: ['./app/**/*.{ts,tsx}', './components/**/*.{ts,tsx}']
className Prop
NativeWind adds className support to all RN core components:
<View className="flex-1 bg-white p-4"><Text className="text-lg font-bold text-gray-900"><Pressable className="bg-blue-500 rounded-lg p-3"><ScrollView className="flex-1" contentContainerClassName="p-4 gap-3">
Key Differences from Web Tailwind
| Web Tailwind | NativeWind (RN) | Notes |
|---|---|---|
hover:bg-gray-100 |
Not available | No hover on touch devices |
cursor-pointer |
Not applicable | Use Pressable instead |
flex (row default) |
flex (column default) |
RN flexbox defaults to column |
| Bare strings | Must wrap in <Text> |
RN requires Text component |
div |
View |
No HTML elements |
gap-4 |
gap-4 |
Supported in NativeWind 4.x |
grid |
Not available | Use flex layouts |
Conditional Classes
Concatenate class strings conditionally:
className={`px-4 py-2 rounded-lg ${isActive ? 'bg-blue-500' : 'bg-gray-200'}`}
Or use a utility like clsx/cn for cleaner conditionals.
ScrollView Styling
ScrollView has two className targets:
className— outer container stylingcontentContainerClassName— inner content styling (padding, gap, alignment)
Always use contentContainerClassName for padding and spacing of scroll content.
Theme Customization
Extend via tailwind.config.js theme:
theme: {
extend: {
colors: { brand: { 50: '...', 500: '...', 900: '...' } },
fontFamily: { sans: ['Inter'] }
}
}
Best Practices
- Always create
nativewind-env.d.tsfor TypeScriptclassNametype support - Use
contentContainerClassNameon ScrollView, notclassNamefor inner spacing - Remember flex defaults to column in RN — add
flex-rowexplicitly when needed - Import
global.cssat the top of root_layout.tsx - Use Tailwind's spacing scale consistently (avoid mixing with StyleSheet)
- Keep
tailwind.config.jscontent paths accurate to avoid missing styles - Use
gap-*instead of margin between siblings for consistent spacing
Anti-Patterns
- Mixing
StyleSheet.create()withclassNamein the same component (pick one) - Using
hover:orcursor-utilities (not available on mobile) - Forgetting
contentContainerClassNameon ScrollView (padding won't work onclassName) - Using
gridutilities (not supported in RN — use flex layouts) - Placing bare strings without
<Text>wrapper (crashes on RN) - Not including all source directories in
tailwind.config.jscontent array - Using Tailwind CSS 4.x syntax (NativeWind requires Tailwind 3.x)