Mobile React Native
Nativewind: Speeding up Styling in React Native
How Nativewind can speed up your React Native Development
If you're anything like me, after working on a few web projects with Tailwind, it can feel like a drag to return to stacks that use other styling libraries. Tailwind has become, for myself, and many other developers, a standard styling paradigm. When starting my most recent React Native project, I was relieved to find out that NativeWind exists. NativeWind is exactly what is sounds like: Tailwind Classes in React Native. I can attest to the breeziness of writing an entire native app without a single call to StyleSheet.create.
It's Familiar
Nativewind takes the familiar classes of Tailwind CSS directly to your React Native components. Virtually every* class from Tailwind CSS can be used the exact same way on your mobile app (and the web), and the development results end up being faster iteration, less translating, and components that feel more readable and maintainable.
Let’s look at how to set it up
NativeWind translates Tailwind class names into React Native styles at runtime or compile-time, if you use the Babel plugin. You end up with the the same composable mindset of Tailwind, but the output is just React Native styles.
The setup is simple enough, for my latest project we used expo:
npx expo install nativewind react-native-reanimated@~3.17.4 react-native-safe-area-context@5.4.0
npx expo install --dev tailwindcss@^3.4.17 prettier-plugin-tailwindcss@^0.5.11
Now to generate a tailwind config, run:
npx tailwindcss init
Be sure to include the path to your components in the generated tailwind.config.js file
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./App.tsx", "./components/**/*.{js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},
plugins: [],
}
Next create your global.css file with tailwind's directives
@tailwind base;
@tailwind components;
@tailwind utilities;
Then, enable the Babel plugin in babel.config.js:
module.exports = function (api) {
api.cache(true);
return {
presets: [
["babel-preset-expo", { jsxImportSource: "nativewind" }],
"nativewind/babel",
],
};
};
Now you’re ready to use all the classes Nativewind provides in your components:
import { View, Text, Pressable } from 'react-native'
export default function MyComponent() {
return (
<View className="flex-1 items-center justify-center bg-gray-100">
<Text className="text-2xl font-semibold text-gray-900 mb-4">
Hello world, this component is using NativeWind!
</Text>
<Pressable className="bg-blue-400 px-4 py-2 rounded-lg active:bg-blue-600">
<Text className="text-white font-medium">Press me</Text>
</Pressable>
</View>
)
}
You will probably want to create some custom tailwind colors/classes, which you can include into the existing theme.
//tailwind.config.js
import { colors } from "./theme/colors"
module.exports = {
theme: {
extend: {
colors: colors
},
},
},
}
For more information on installing Nativewind, be sure to check out the documentation
Defining style objects in React Native can spiral, and to be fair, so can inline tailwind classes at times. The separation of style sheets can look neat at first, but over time, it can become another layer to maintain, a long list of key names that rarely get reused across files when not carefully organized.
Let's compare StyleSheets with Nativewind
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f9fafb',
justifyContent: 'center',
alignItems: 'center',
},
})
Now compare that to this:
<View className="flex-1 bg-gray-50 justify-center items-center" />
The result is the same, and I'd argue the tailwind is more readable.
I prefer never having to context switch between the code I'm writing and the styles it uses. Navigating to the bottom of the file just to tweak a component's padding can be tedious.
As a developer that uses Tailwind on the web, Nativewind makes me feel right at home. It also means that If you plan on distributing your native app to the web, it's simple to use Tailwind breakpoints to alter the design of your components for larger screens.
Integration
Nativewind also plays well with other libraries. Since the generated output is just standard React Native styles, you can still use other animation and navigation libraries. Essentially, if it takes a className prop, you can throw Nativewind styles at it.
import { MotiView } from 'moti'
<MotiView
from={{ opacity: 0, translateY: 8 }}
animate={{ opacity: 1, translateY: 0 }}
className="p-4 bg-brand-500 rounded-xl"
/>
Another great feature is that the basic animation classes included with Tailwind work with Nativewind. At the time of writing this the support is considered experimental, however in my experience all of the animate- classes work as expected on IOS and Android.
In Conclusion
The familiar Tailwind class syntax and easily achieved responsiveness make Nativewind an effective library for speeding up react native development.
If you’re tired of jumping back and forth from component renders and StyleSheets, I highly recommend seeing if Nativewind can improve your workflow on your next React Native Project.
Work with us
Need help with your next React Native project? Don't hesitate to reach out with any questions.