Overview
NativeWind uses Tailwind CSS v4’s plugin system to extend functionality. The framework includes a built-in NativeWind plugin that adds React Native-specific features, and you can create your own plugins to add custom utilities, variants, and behaviors.
NativeWind Plugin
The NativeWind plugin is the core of the framework, providing React Native-specific functionality.
Installation
Register the NativeWind plugin in your theme file:
@plugin "nativewind";
@theme {
/* Your theme configuration */
}
For local development or when using a specific path:
@plugin "./node_modules/nativewind/dist/module/plugin.js";
What the Plugin Provides
The NativeWind plugin adds:
@map Variant - Maps CSS properties to React Native component props
Platform Detection - Enables iOS, Android, and native-specific styling
React Native Utilities - Custom utilities for elevation, ripple effects, etc.
The @map Variant
The @map variant is a powerful feature that lets you map CSS values to any React Native component prop.
Basic Usage
Map values to component props:
import { View , Text } from "react-native" ;
// Map color to the 'tint' prop
< View className = "@map/tint:color-blue-500" />
// Map to nested props
< View className = "@map/android_ripple.color:color-red-500" />
Component Usage
Output Props
import { View , Image } from "react-native" ;
function TintedIcon () {
return (
< Image
source = { require ( "./icon.png" ) }
className = "w-6 h-6 @map/tint:color-blue-500"
/>
);
}
Advanced @map Patterns
Mapping to Nested Props
{ /* Map to android_ripple.color */ }
< Pressable className = "@map/android_ripple.color:color-blue-500" >
< Text > Press me </ Text >
</ Pressable >
{ /* Map to style.test.nested */ }
< View className = "@map/&.test.nested:color-black" />
Using @map with Modifiers
{ /* Map fontSize to a custom prop */ }
< Text className = "@map-[customSize]/fontSize:text-base" />
{ /* Map to nested object */ }
< View className = "@map-[config.theme]/fontSize:text-lg" />
Plugin Implementation
Here’s how the @map variant is implemented in the NativeWind plugin (from /home/daytona/workspace/source/src/plugin.tsx:10-51):
import plugin , { type PluginCreator } from "tailwindcss/plugin" ;
function kebabCase ( str : string ) {
return str . replace (
/ [ A-Z ] + (?! [ a-z ] ) | [ A-Z ] / g ,
( $ , ofs ) => ( ofs ? "-" : "" ) + $ . toLowerCase (),
);
}
const nativewind : PluginCreator = plugin . withOptions (
() =>
({ matchVariant }) => {
matchVariant (
"@map" ,
( value = "" , { modifier }) => {
value = kebabCase ( value . replace ( /&/ , " \\ &" ));
if ( modifier ) {
modifier = modifier . replace ( /&/ , " \\ &" );
}
if ( modifier && value ) {
// @map-[value]/<modifier>:text-red-500
return `@nativeMapping { ${ modifier } : ${ value } }; @media all` ;
} else if ( modifier && ! value ) {
// @map/<modifier>:text-red-500
return `@nativeMapping ${ modifier } ; @media all` ;
} else if ( ! modifier && value ) {
return `@nativeMapping ${ value } ; @media all` ;
} else {
return "" ;
}
},
{ values: { DEFAULT: undefined } },
);
},
);
export default nativewind ;
This plugin creates a matchVariant that generates special @nativeMapping CSS at-rules, which the NativeWind runtime uses to map values to component props.
Creating Custom Utilities
Extend NativeWind with custom utility classes using the @utility directive.
React Native-Specific Utilities
Create utilities for React Native props:
/* Tint color utility */
@utility tint-* {
-rn-tint: --value(--color- * );
@prop -rn-tint tint;
}
/* Android ripple utilities */
@utility ripple-* {
-rn-ripple-style: --value("borderless");
-rn-ripple-color: --value(--color- * );
}
@utility ripple-* {
-rn-ripple-radius: --value(integer);
}
@utility ripple-foreground {
-rn-ripple-foreground: "foreground";
}
/* Elevation utility (Android shadows) */
@utility elevation-* {
-rn-elevation: --value(--elevation- * );
}
/* Corner shape utility (iOS) */
@utility corner-* {
corner-shape : --value("rounded", "squircle");
}
Usage:
Tint Color
Ripple Effect
Elevation
import { Image } from "react-native" ;
< Image
source = { require ( "./icon.png" ) }
className = "w-6 h-6 tint-blue-500"
/>
The @prop Directive
The @prop directive maps CSS properties to component props:
@utility tint-* {
-rn-tint: --value(--color- * );
@prop -rn-tint tint; /* Maps -rn-tint to the 'tint' prop */
}
This tells NativeWind to extract the -rn-tint CSS property and apply it to the component’s tint prop.
Custom Variants
Create custom conditional variants using @custom-variant:
/* Platform variants */
@custom-variant ios (@media ios);
@custom-variant android (@media android);
@custom-variant native (@media native);
@custom-variant tv (@media (display-mode: tv));
/* Web variant (uses child combinator support as detection) */
@custom-variant web (@supports selector(div > div));
/* Custom device variants */
@custom-variant tablet (@media (min-width: 768px));
@custom-variant desktop (@media (min-width: 1024px));
Usage:
< View className = "
ios:bg-blue-500
android:bg-green-500
tablet:p-8
desktop:p-12
" >
< Text className = "native:text-lg web:text-xl" >
Platform-specific styling
</ Text >
</ View >
Third-Party Plugins
NativeWind supports Tailwind CSS plugins from the ecosystem.
Safe Area Plugin
Handle device safe areas (notches, home indicators):
@plugin "nativewind";
@import "tailwindcss-safe-area" ;
@theme {
/* Your configuration */
}
Usage:
import { View , Text } from "react-native" ;
export default function App () {
return (
< View className = "flex-1 pt-safe pb-safe" >
< View className = "px-4" >
< Text > Content with safe area padding </ Text >
</ View >
</ View >
);
}
Available utilities:
pt-safe, pr-safe, pb-safe, pl-safe - Padding for safe areas
mt-safe, mr-safe, mb-safe, ml-safe - Margin for safe areas
top-safe, right-safe, bottom-safe, left-safe - Position values
Creating Tailwind CSS v4 Plugins
Create a custom plugin file:
import plugin from 'tailwindcss/plugin' ;
export default plugin ( function ({ matchUtilities , theme }) {
// Add custom utilities
matchUtilities (
{
'text-shadow' : ( value ) => ({
textShadowColor: value ,
textShadowOffset: { width: 0 , height: 1 },
textShadowRadius: 2 ,
}),
},
{ values: theme ( 'colors' ) }
);
} ) ;
Register it:
@plugin "./my-plugin.js";
Not all Tailwind plugins are compatible with React Native. Plugins that rely on web-specific CSS features may not work.
Advanced Plugin Patterns
Combining Multiple Custom Properties
@utility card {
background-color : white;
border-radius : 12px;
padding: 16px;
-rn-elevation: 4;
@prop -rn-elevation elevation;
}
Responsive Custom Utilities
@utility container {
width: 100%;
padding-left : 16px;
padding-right : 16px;
margin-left : auto;
margin-right : auto;
@media ( min-width : 640 px ) {
max-width : 640px;
}
@media ( min-width : 768 px ) {
max-width : 768px;
padding-left : 24px;
padding-right : 24px;
}
@media ( min-width : 1024 px ) {
max-width : 1024px;
}
}
Variant-Aware Utilities
@utility btn {
padding: 12px 24px;
border-radius : 8px;
font-weight : 600;
text-align : center;
& :active {
opacity : 0.8 ;
transform : scale ( 0.98 );
}
}
@utility btn-primary {
background-color : var(--color-primary);
color: white;
}
@utility btn-secondary {
background-color : var(--color-secondary);
color: white;
}
Plugin Best Practices
Use Semantic Names Name utilities based on their purpose, not their appearance (e.g., elevation-card vs elevation-6)
Document Your Utilities Add comments explaining what custom utilities do and when to use them
Test Cross-Platform Always test custom utilities on iOS, Android, and web if you support all platforms
Follow Conventions Match Tailwind’s naming patterns for consistency (e.g., use -* for variants)
Debugging Plugins
Inspect generated CSS to debug plugin output:
npx tailwindcss --output=debug.css --minify=false
Check the generated CSS for your custom utilities and variants.
Complete Plugin Example
Here’s a comprehensive example combining multiple plugin features:
@plugin "nativewind";
@import "tailwindcss-safe-area" ;
@theme {
/* Brand colors */
--color-brand: #3b82f6 ;
--color-accent: #ec4899;
/* Elevation system */
--elevation-card: 4;
--elevation-modal: 8;
--elevation-drawer: 16;
/* Border radius system */
--radius-button: 8px;
--radius-card: 12px;
--radius-modal: 16px;
}
/* Platform-specific fonts */
:root {
@ media ios {
--font-sans : System ;
}
@media android {
--font-sans: SystemAndroid;
}
}
/* Custom utilities */
@utility elevation-* {
-rn-elevation: --value(--elevation- * );
}
@utility tint-* {
-rn-tint: --value(--color- * );
@prop -rn-tint tint;
}
@utility ripple-* {
-rn-ripple-color: --value(--color- * );
}
@utility card {
background-color : white;
border-radius : var(--radius-card);
padding: 16px;
-rn-elevation: var(--elevation-card);
}
/* Custom variants */
@custom-variant ios (@media ios);
@custom-variant android (@media android);
@custom-variant tablet (@media (min-width: 768px));
@custom-variant desktop (@media (min-width: 1024px));
Usage:
import { View , Text , Image , Pressable } from "react-native" ;
export default function App () {
return (
< View className = "flex-1 pt-safe pb-safe bg-gray-50" >
< View className = "card m-4 tablet:m-8" >
< View className = "flex-row items-center mb-4" >
< Image
source = { require ( "./icon.png" ) }
className = "w-8 h-8 tint-brand"
/>
< Text className = "text-xl font-bold ml-2" > Custom Plugin Demo </ Text >
</ View >
< Pressable className = "
bg-brand p-3 rounded-lg ripple-white
ios:elevation-card android:elevation-modal
" >
< Text className = "text-white text-center font-semibold" >
Platform-Aware Button
</ Text >
</ Pressable >
</ View >
</ View >
);
}
Resources
Tailwind Plugin API Official Tailwind CSS plugin documentation
NativeWind Source Explore the NativeWind plugin source code