Build beautiful, responsive React Native apps with Tailwind CSS β the easy way.
π‘ What is NativeWind?
NativeWind lets you use Tailwind CSS classes directly in React Native components. WriteclassName="flex-1 bg-white"instead of verbose stylesheets. π¨
π Prerequisites
Before we begin, make sure you have:
| Tool | Install Command / Link |
|---|---|
| Node.js (LTS) | nodejs.org |
| npm or yarn | Comes with Node.js |
| Expo CLI | npm install -g expo-cli |
| Xcode (for iOS) | App Store β οΈ macOS only |
| Android Studio (for Android) | developer.android.com |
π iOS Developers: Xcode is ~12GB and required to run the iOS Simulator. Install it early β it takes time!
π€ Android Developers: Enable a virtual device via Android Studio's Device Manager.
π§± Step 1: Create and Initialize Project
npx create-expo-app@latest my-app
cd my-app
β
Test that everything works:
npm run ios
# or
npm run android
| Key | Action |
|---|---|
i |
Open iOS Simulator |
a |
Open Android Emulator |
r |
Reload the app |
d |
Open developer menu |
π Step 2: Reset the Project (Optional Cleanup)
Expo's template includes demo files. Let's start fresh:
npm run reset-project
When prompted:
Do you want to move existing files to /app-example instead of deleting them? (Y/n):
π Press n to delete and get a clean Expo Router structure.
πΏ Step 3: Install NativeWind & Dependencies
π‘ Keep your Metro bundler running in one terminal. Open a new terminal for installations.
npm install nativewind tailwindcss react-native-reanimated react-native-safe-area-context
| Package | Purpose |
|---|---|
nativewind |
Tailwind for React Native |
tailwindcss |
Core Tailwind engine |
react-native-reanimated |
Smooth animations |
react-native-safe-area-context |
Handle notches & status bars |
π Step 4: Initialize Tailwind
npx tailwindcss init
This creates tailwind.config.js at your project root.
βοΈ Step 5: Update tailwind.config.js
Replace the entire file with:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./App.{js,jsx,ts,tsx}",
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
"./screens/**/*.{js,jsx,ts,tsx}",
],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},
plugins: [],
};
π The
contentarray tells Tailwind which files to scan for class names.
π¨ Step 6: Create app/globals.css
Inside your app/ folder, create globals.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
This imports Tailwind's utility classes into your app.
π§ Step 7: Configure Babel β babel.config.js
At your project root, update babel.config.js:
module.exports = function (api) {
api.cache(true);
return {
presets: [
["babel-preset-expo", { jsxImportSource: "nativewind" }],
"nativewind/babel",
],
};
};
β¨ This enables NativeWind's CSS-in-JS transformation at build time.
π§© Step 8: Customize Metro Config
Run the Expo helper:
npx expo customize metro.config.js
Then update metro.config.js:
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require("nativewind/metro");
const config = getDefaultConfig(__dirname);
module.exports = withNativeWind(config, { input: "./app/globals.css" });
π This injects NativeWind's CSS processor into Expo's bundler.
π Step 9: Add TypeScript Support β nativewind-env.d.ts
At your project root, create:
nativewind-env.d.ts
Add this single line:
/// <reference types="nativewind/types" />
β
Now your editor will recognize className props with autocomplete!
π Step 10: Update app/_layout.tsx
Import your global styles:
import { Stack } from "expo-router";
import "./globals.css";
export default function RootLayout() {
return <Stack />;
}
π§
expo-routeruses file-based routing β_layout.tsxwraps all screens.
π§± Step 11: Example Screen β app/index.tsx
Let's test NativeWind with a simple screen:
import { View, Text } from "react-native";
export default function Index() {
return (
<View className="flex-1 items-center justify-center bg-white">
<Text className="text-red-500 text-2xl font-bold">
Hello from NativeWind π
</Text>
</View>
);
}
β If you see red, bold, centered text β it's working!
π Step 12: Restart with Cache Clear
Final step β clear Metro's cache to apply all config changes:
npx expo start -c
When prompted:
? Clear Metro bundler cache? (y/N)
π Press y
π― You're All Set!
β
Expo + Router
β
NativeWind + Tailwind CSS
β
Hot reloading with class names
β
TypeScript support
β
iOS & Android ready
π οΈ Troubleshooting Tips
| Issue | Solution |
|---|---|
β className not working |
Restart with -c, check babel.config.js
|
| β iOS simulator won't launch | Ensure Xcode is installed + command line tools: xcode-select --install
|
| β Styles not updating | Verify globals.css is imported in _layout.tsx
|
β TypeScript errors on className
|
Confirm nativewind-env.d.ts exists at root |
| β Metro bundler stuck | Delete node_modules/.cache and restart |
π‘ Pro Tip: Add this to your
package.jsonfor faster dev:"scripts": { "ios:clean": "npx expo start -c --ios", "android:clean": "npx expo start -c --android" }
π§ͺ Bonus: Quick Test Component
Try this in a new file to see NativeWind in action:
// app/components/TestCard.tsx
import { View, Text } from "react-native";
export default function TestCard() {
return (
<View className="m-4 p-6 bg-blue-100 rounded-2xl shadow-lg">
<Text className="text-blue-800 text-lg font-semibold mb-2">
π NativeWind Works!
</Text>
<Text className="text-gray-600">
Style with Tailwind, no StyleSheet needed.
</Text>
</View>
);
}
Then import it in index.tsx β instant beautiful UI! π¨
π Helpful Resources
π If this guide saved you time, give it a β€οΈ, share it with a fellow dev, or drop a comment with what you're building next!
Tags: #ReactNative #Expo #NativeWind #TailwindCSS #MobileDev #WebDevelopment #Beginners #Tutorial
Top comments (0)