Setup and context — What Is NativeWind?
If you've ever wished you could style your Rork app's UI with the same ease as web development, NativeWind is the answer. Rork generates React Native code, which typically uses StyleSheet.create for styling — but NativeWind brings the beloved Tailwind CSS utility-first approach directly to React Native.
With NativeWind, you can write className="bg-blue-500 p-4 rounded-lg" on any React Native component, just like you would in a web project. It pairs beautifully with Rork's Expo-based output and can significantly speed up your UI development once configured.
Why Use NativeWind in Your Rork App
There are several compelling reasons to add NativeWind to your Rork project.
Familiar syntax for web developers. If you already know Tailwind CSS, the learning curve is nearly zero. Many Rork users come from a web background, so being able to use the same class names across platforms is a huge productivity win.
Cleaner, more readable code. Traditional StyleSheet.create separates style definitions from component markup, which can hurt readability in larger files. NativeWind keeps styles inline, making components easier to scan and understand at a glance.
Dark mode with minimal effort. Adding the dark: prefix to any class is all it takes to support dark mode — no conditional logic or theme contexts needed.
Setup Instructions
Requirements
- A Rork-generated Expo project
- Node.js 18 or higher
- Expo SDK 50 or higher
Installing Packages
Start by installing NativeWind and Tailwind CSS:
# Install NativeWind v4 and Tailwind CSS
npx expo install nativewind tailwindcss
# Generate the Tailwind config file
npx tailwindcss initConfiguring tailwind.config.js
Edit the generated tailwind.config.js to point to your project's source files:
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
// Apply the NativeWind v4 preset
presets: [require('nativewind/preset')],
content: [
'./app/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
'./src/**/*.{js,jsx,ts,tsx}',
],
theme: {
extend: {
// Define custom brand colors here
colors: {
primary: '#6366f1',
secondary: '#8b5cf6',
},
},
},
plugins: [],
};Updating babel.config.js
Enable NativeWind by updating your Babel configuration:
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [
['babel-preset-expo', { jsxImportSource: 'nativewind' }],
'nativewind/babel',
],
};
};Updating metro.config.js
Configure the Metro bundler to work with NativeWind:
// metro.config.js
const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');
const config = getDefaultConfig(__dirname);
module.exports = withNativeWind(config, { input: './global.css' });Creating global.css
Create a global.css file at the project root:
/* global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;Importing CSS in Your App Entry Point
Import the CSS file in your app's root layout (app/_layout.tsx):
// app/_layout.tsx
import '../global.css';
import { Stack } from 'expo-router';
export default function RootLayout() {
return <Stack />;
}Basic Usage
With the setup complete, let's look at how to use NativeWind in practice.
Text and Layout
// components/WelcomeCard.tsx
import { View, Text } from 'react-native';
export function WelcomeCard() {
return (
// flex-col stacks children vertically, p-6 adds padding, shadow-md gives depth
<View className="flex-col p-6 bg-white rounded-2xl shadow-md mx-4 my-2">
{/* text-2xl sets font size, font-bold makes it heavy, text-gray-800 sets color */}
<Text className="text-2xl font-bold text-gray-800 mb-2">
Welcome!
</Text>
{/* text-base is default size, text-gray-500 is muted, leading-relaxed improves readability */}
<Text className="text-base text-gray-500 leading-relaxed">
This is a sample component styled with NativeWind —
just like Tailwind CSS on the web.
</Text>
</View>
);
}Button Component
// components/PrimaryButton.tsx
import { TouchableOpacity, Text } from 'react-native';
type Props = {
label: string;
onPress: () => void;
variant?: 'primary' | 'secondary';
};
export function PrimaryButton({ label, onPress, variant = 'primary' }: Props) {
return (
<TouchableOpacity
onPress={onPress}
// active:opacity-80 reduces opacity on press for tactile feedback
className={`
py-4 px-8 rounded-full active:opacity-80
${variant === 'primary' ? 'bg-indigo-500' : 'bg-purple-500'}
`}
>
<Text className="text-white font-semibold text-base text-center">
{label}
</Text>
</TouchableOpacity>
);
}Flexbox Grid Layout
NativeWind makes React Native's Flexbox system intuitive with Tailwind's familiar class names:
// components/CardGrid.tsx
import { View, Text } from 'react-native';
const items = ['🍎 Apple', '🍊 Orange', '🍋 Lemon', '🍇 Grape'];
export function CardGrid() {
return (
// flex-row flex-wrap creates a wrapping horizontal layout
<View className="flex-row flex-wrap gap-3 p-4">
{items.map((item) => (
<View
key={item}
// w-[48%] sets each card to 48% width for a 2-column grid
className="w-[48%] bg-yellow-50 border border-yellow-200 rounded-xl p-4 items-center"
>
<Text className="text-3xl mb-1">{item.split(' ')[0]}</Text>
<Text className="text-sm font-medium text-gray-700">
{item.split(' ')[1]}
</Text>
</View>
))}
</View>
);
}
// Output: a 2-column grid of fruit cardsDark Mode Support
NativeWind's dark mode support is one of its most powerful features. Just prefix any class with dark: and you're done:
// components/ThemedCard.tsx
import { View, Text, useColorScheme } from 'react-native';
export function ThemedCard() {
const colorScheme = useColorScheme();
return (
// dark: prefix applies styles only in dark mode
<View className="
p-6 mx-4 my-2 rounded-2xl
bg-white dark:bg-gray-800
border border-gray-100 dark:border-gray-700
">
<Text className="
text-xl font-bold mb-2
text-gray-900 dark:text-white
">
Theme-Aware Card
</Text>
<Text className="
text-sm leading-relaxed
text-gray-600 dark:text-gray-300
">
This card adapts automatically to light or dark mode.
Current theme: {colorScheme === 'dark' ? '🌙 Dark' : '☀️ Light'}
</Text>
</View>
);
}Responsive Design
Tablet-friendly responsive layouts are straightforward with sm: and md: breakpoints:
// components/ResponsiveLayout.tsx
import { View, Text } from 'react-native';
export function ResponsiveLayout() {
return (
// Stacked on phones, side-by-side on tablets (768px+)
<View className="flex-col sm:flex-row p-4 gap-4">
<View className="flex-1 bg-blue-50 rounded-xl p-6">
<Text className="text-lg font-bold text-blue-800">Left Panel</Text>
<Text className="text-sm text-blue-600 mt-2">
Appears on top on mobile devices
</Text>
</View>
<View className="flex-1 bg-green-50 rounded-xl p-6">
<Text className="text-lg font-bold text-green-800">Right Panel</Text>
<Text className="text-sm text-green-600 mt-2">
Sits side by side on tablets
</Text>
</View>
</View>
);
}Handy NativeWind Classes to Know
Here's a quick reference for the most-used NativeWind utilities:
Layout
flex-1— fills available space (flex: 1)flex-row— horizontal layout (flexDirection: 'row')items-center— centers children verticallyjustify-between— space between children
Spacing
p-4— padding 16pxm-2— margin 8pxgap-3— 12px gap between childrenmb-4— margin-bottom 16px
Typography
text-xl— font size 20pxfont-bold— bold weighttext-gray-700— medium gray text colorleading-relaxed— comfortable line height
Visuals
bg-white— white backgroundrounded-xl— 12px border radiusshadow-md— medium drop shadowborder border-gray-200— light gray border
Applying NativeWind to Rork-Generated Code
When working with Rork output, you'll typically replace style props with className:
// Rork-generated code (before)
<View style={{ padding: 16, backgroundColor: '#fff', borderRadius: 12 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', color: '#111' }}>
Title
</Text>
</View>
// After applying NativeWind (after)
<View className="p-4 bg-white rounded-xl">
<Text className="text-lg font-bold text-gray-900">
Title
</Text>
</View>For a deeper dive into structuring reusable components in your Rork project, check out How to Design Reusable React Native Components in Rork. It covers maintainable UI architecture patterns that pair perfectly with NativeWind.
Common Errors and Fixes
Error 1: className has no effect
Double-check your Metro and Babel configs. After making changes, always clear the cache and restart the dev server with expo start --clear.
Error 2: TypeScript type errors on className
Add the NativeWind type reference to your tsconfig.json:
{
"compilerOptions": {
"types": ["nativewind/types"]
}
}Error 3: Custom classes aren't working
Make sure the file paths in tailwind.config.js under content actually cover the files where you're using NativeWind. Misconfigured paths mean Tailwind can't detect the classes and won't generate the corresponding styles.
If you'd like to improve your overall Rork app UX alongside styling, Rork App UX Design Patterns: Complete Guide is a great companion resource covering interaction design, micro-animations, and screen flow best practices.
Summary
Adding NativeWind to your Rork project unlocks the full power of Tailwind CSS in your React Native UI. While the initial setup involves a few configuration files, the payoff is a dramatically faster and more readable styling workflow — especially if you're already comfortable with Tailwind on the web.
Between dark mode support, responsive breakpoints, and a rich utility class library, NativeWind gives you everything you need to build polished, consistent UIs without wrestling with StyleSheet boilerplate. Give it a try in your next Rork project and see how quickly things come together.