Styling React Native apps used to frustrate me a bit. I came from Tailwind CSS on the web, so I loved working with quick and flexible utility classes. I always wanted something like that on mobile. Then I found NativeWind. Now, my prototyping is faster, my code feels cleaner, and I can finally think in the same expressive way as I do for web apps. If you are interested in learning how to bring NativeWind into your Expo workflow, let me walk you through how I did it. I will share what worked for me and what to watch for.
Transparency notice: This article incorporates AI tools and may reference projects or businesses I'm affiliated with.
Let’s go step by step and I will share details, gotchas, and a few personal tips about using NativeWind for styling in Expo projects.
What is NativeWind and Why Use It?
NativeWind lets you use Tailwind-like classes in React Native. Instead of writing long style objects or getting stuck with basic inline styles, you get to write compact class names. NativeWind takes those classes and turns them into React Native styles for you. For me, the benefits were instantly clear.
- I get to use familiar, short class names so I can iterate on designs much faster.
- My core logic stays separate from all my style tweaks. No more scrolling past endless style objects.
- I can now share design patterns between web and mobile teams, which saves everyone time.
Prerequisites
Let me quickly list out what you need before you start.
- Make sure Node.js and npm or yarn are on your machine.
- Set up Expo CLI so you can use the
npx expocommand. - Pick your favorite code editor. I use VS Code.
Step-by-Step Guide to Setting up NativeWind
This is exactly how I set things up for my own apps. I will include little notes about where I ran into issues or what I found helpful.
1. Create a New Expo Project
I always start fresh to avoid weird issues. In your terminal, run:
npx create-expo-app MyNativeWindApp
cd MyNativeWindApp
Now you have your basic React Native project to work with.
2. Install NativeWind and Dependencies
NativeWind needs a few friends to work well. I install NativeWind along with Tailwind CSS, React Native Reanimated, and React Native Safe Area Context.
npm install nativewind tailwindcss react-native-reanimated react-native-safe-area-context
If you work with iOS in bare workflow, you might need CocoaPods, but in Expo this is not usually something to stress about.
3. Initialize Tailwind CSS
I use the built-in command to set up Tailwind’s base config:
npx tailwindcss init
This creates a new tailwind.config.js file for you to modify.
4. Configure Tailwind for React Native
Next, open tailwind.config.js. You need to help Tailwind find all your component files, so add the right paths to the content array. This is what mine looks like:
module.exports = {
content: [
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}"
],
presets: [require("nativewind/tailwind/native")],
theme: {
// You can extend colors and more here
},
plugins: [],
};
Pro tip: Check where your components really live. Maybe it is src or another folder. Update these paths to match.
5. Add a Global CSS File
Create global.css right in your project’s root or inside app/. Paste in this boilerplate so Tailwind’s base, components, and utilities are included:
@tailwind base;
@tailwind components;
@tailwind utilities;
6. Update Metro and Babel Configurations
This step tripped me up at first, so I want to be clear. React Native needs to know how to handle CSS and class names.
-
Babel: If you do not have
babel.config.jsyet, create one at your project root. Fill it in like this:
module.exports = { presets: ['babel-preset-expo'], plugins: ['nativewind/babel'], } -
Metro: Now create or update
metro.config.jsat the root. Let Metro see your CSS files:
const { getDefaultConfig } = require('expo/metro-config'); module.exports = (() => { const config = getDefaultConfig(__dirname); config.resolver.assetExts.push('css'); return config; })();
Sometimes Expo changes how things work, so if you get lost, I recommend checking out NativeWind docs. They are usually up to date.
7. Import the Global CSS File
To make Tailwind classes available everywhere, import global.css in your main entry file. In my Expo Router projects, I use app/layout.js or app/layout.tsx. In classic apps, just pop this line at the top of App.js or App.tsx:
import './global.css';
8. (Optional) TypeScript Support
If you work with TypeScript as I do sometimes, add a nativewind-env.d.ts file to the root and write:
/// <reference types="nativewind/types" />
This stops TypeScript from complaining when using class names in your components.
9. Update app.json for the Metro Bundler on Web
If you plan to build for web too, jump into your app.json. Inside the web key, make sure it looks like this:
"web": {
"bundler": "metro"
}
This tells Expo to use Metro for web bundling and process your CSS the right way.
10. Restart and Test
You have made a lot of config changes. Fully restart your dev server so changes are picked up. I always use the clear cache option:
npx expo start -c
The -c flag is important. Sometimes old cache gets in the way and you do not notice broken config right away.
Using NativeWind in Your Components
Once everything is wired up, you get the fun part. Now you can use Tailwind classes right inside the className prop on React Native components. For example:
import { View, Text } from 'react-native';
export default function HomeScreen() {
return (
<View className="flex-1 justify-center items-center bg-blue-500">
<Text className="text-2xl font-bold text-white">
Welcome to NativeWind + Expo!
</Text>
</View>
);
}
Here’s what I noticed:
- Always use
className(notstyle) when working with NativeWind components. - You get spacing, fonts, colors, backgrounds, flexbox, and lots more just by adding Tailwind classes.
- The styles feel like web Tailwind, so your UI code stays readable and easy to tweak.
Example: Responsive Layout
Here is a simple responsive layout I used. I found it straightforward to move between web and mobile approaches.
<View className="flex-row h-screen">
<View className="flex-[0.4] bg-red-500 rounded-t-3xl" />
<View className="flex-[0.6] bg-white">
<Image
source={require('./assets/images/burger.png')}
className="w-full h-full resize-contain"
/>
</View>
</View>
At this point, if you are looking for a way to go from early app ideas to real NativeWind-styled React Native code even faster, especially if you collaborate with a team, tools like RapidNative can be a huge help. RapidNative is an AI-powered collaborative app builder that turns plain English prompts, sketches, screenshots, or PRD documents into production-ready React Native apps, complete with clean modular code styled using NativeWind. You can live preview on physical devices, collaborate in real time, and export your codebase without any lock-in. It is especially handy if you want to quickly prototype and iterate on design ideas with teammates before pushing code, letting you focus more on UX and less on repetitive setup.
Troubleshooting Common Issues
I definitely ran into hiccups during setup. Here are the issues I hit and how you can fix them.
Errors about Babel presets?
Make surebabel-preset-expois installed and mentioned inbabel.config.js.Classes not applying?
Double-check thecontentarray in yourtailwind.config.js. Be sure it matches your folder structure.‘Cannot find module' or 'worklets' errors?
Many times it is missing or out-of-datereact-native-reanimated. Run install or update, then restart Expo.Blank output or broken styles?
Check you really importedglobal.cssat your app’s root file. Also, clear your cache and restart.Using className vs style:
Stick toclassNameon supported components. Mixing withstylesometimes gives weird results, so avoid it when you can.
Productivity Tips
Here are things that made my workflow smoother:
- Install the Tailwind CSS IntelliSense extension for VS Code. It helps autocomplete NativeWind classes.
- Organize your
tailwind.config.jsthoughtfully. This will help as your app grows. - Define your own colors and spacing values to match your brand.
- Combine Tailwind classes for responsive, clean layouts just as you would on the web.
Final Thoughts
Getting NativeWind up and running changed my whole approach to styling React Native apps. I can write code that is simple, readable, and easy to update. I noticed my design process became quicker and more fun. NativeWind brings the power of Tailwind to mobile with only a few setup steps. There are a few things you need to watch for, but once past those, the speed and clarity are worth it.
Start small, check your setup as you go, and use NativeWind’s docs whenever you get stuck. Soon you will be styling screens much faster and with much less hassle.
FAQ
How do I know if NativeWind is working correctly in my Expo project?
You will know it is set up right when you see classes work as props. Try changing a background color or text size with a Tailwind class. If you see the result after saving, then NativeWind is running.
Can I use custom colors and themes with NativeWind?
Absolutely! You can add custom colors, type scales, breakpoints, and more by extending the theme section in your tailwind.config.js. This is how I matched my mobile app to a company brand.
What’s the best way to structure the content array in tailwind.config.js?
Include every path where Tailwind classes might show up. I always add "./app/**/*.{js,jsx,ts,tsx}" and "./components/**/*.{js,jsx,ts,tsx}" at the very least. Adjust if your project folders change.
Will using NativeWind affect the performance of my React Native app?
NativeWind is built to be fast. It translates class names to static style objects behind the scenes. I did not notice a performance drop. Any small overhead is usually worth it for the time and code you save.
With NativeWind, I feel ready to build beautiful, flexible React Native apps at top speed. I hope this guide helps you get started and move fast. Happy coding!
Top comments (0)