Back to catalog

nativewind-styling

NativeWind styling patterns for React Native. Use when styling components with Tailwind-like utilities in RN.

  • Category: discovered
  • Tags: github, community
  • Version: 1.0.0
  • Author: walid
  • Downloads: 0
  • Updated: 2025-11-22

Download the latest version (v1.0.0) from this page.

SKILL.md

---
name: nativewind-styling
description: NativeWind styling patterns for React Native. Use when styling components with Tailwind-like utilities in RN.
---

# NativeWind Styling

This skill covers NativeWind usage for styling React Native components with Tailwind CSS utilities.

## When to Use This Skill

- Styling components with NativeWind utilities
- Understanding RN-specific Tailwind differences
- Combining NativeWind with StyleSheet
- Responsive design for mobile
- Platform-specific styling

## What is NativeWind?

NativeWind brings Tailwind CSS to React Native. It uses the `className` prop to apply utility classes.

```typescript
import { View, Text } from 'react-native'

<View className="flex-1 bg-white p-4">
  <Text className="text-lg font-semibold text-gray-900">
    Hello, NativeWind!
  </Text>
</View>
```

## Core Utilities

### Layout

#### Flexbox (Default in RN)
```typescript
// Vertical layout (default - no need for flex-col)
<View className="flex-1">
  <View>Item 1</View>
  <View>Item 2</View>
</View>

// Horizontal layout
<View className="flex-row">
  <View>Left</View>
  <View>Right</View>
</View>

// Centering
<View className="flex-1 items-center justify-center">
  <Text>Centered</Text>
</View>

// Space between
<View className="flex-row justify-between items-center">
  <Text>Left</Text>
  <Text>Right</Text>
</View>

// Wrapping
<View className="flex-row flex-wrap">
  {/* Items will wrap to next line */}
</View>
```

#### Dimensions
```typescript
// Full width/height
<View className="w-full h-full">

// Specific sizes (4px per unit)
<View className="w-12 h-12"> {/* 48px × 48px */}
<View className="w-11 h-11"> {/* 44px × 44px - iOS minimum touch target */}

// Percentage-based
<View className="w-1/2 h-1/3">

// Screen dimensions
<View className="w-screen h-screen">

// Minimum/Maximum
<View className="min-h-screen max-w-md">
```

### Spacing

#### Padding
```typescript
// All sides
<View className="p-4"> {/* 16px all sides */}

// Specific sides
<View className="pt-4 pb-6 px-4"> {/* top: 16px, bottom: 24px, horizontal: 16px */}

// Individual sides
<View className="pl-2 pr-3 pt-4 pb-5">

// Common values (8pt grid)
className="p-1"  // 4px
className="p-2"  // 8px
className="p-4"  // 16px
className="p-6"  // 24px
className="p-8"  // 32px
```

#### Margin
```typescript
// All sides
<View className="m-4">

// Specific sides
<View className="mt-2 mb-4 mx-4">

// Auto margin (centering)
<View className="mx-auto"> {/* Horizontal center */}

// Negative margin
<View className="-mt-4"> {/* Pull up by 16px */}
```

#### Gap
```typescript
// IMPORTANT: gap only works in newer React Native versions (0.71+)

// Spacing between flex children
<View className="flex-row gap-2"> {/* 8px between items */}
  <View>Item 1</View>
  <View>Item 2</View>
</View>

// If gap doesn't work, use margin instead:
<View className="flex-row">
  <View className="mr-2">Item 1</View>
  <View className="mr-2">Item 2</View>
  <View>Item 3</View>
</View>
```

### Colors

#### Background
```typescript
<View className="bg-white">
<View className="bg-gray-100">
<View className="bg-blue-500">
<View className="bg-red-600">

// Opacity variants
<View className="bg-black/10"> {/* 10% opacity */}
<View className="bg-blue-500/50"> {/* 50% opacity */}

// Custom hex colors
<View className="bg-[#007AFF]"> {/* iOS blue */}
```

#### Text
```typescript
<Text className="text-black">
<Text className="text-gray-900">
<Text className="text-blue-500">
<Text className="text-white">

// Custom colors
<Text className="text-[#007AFF]">
```

#### Border
```typescript
<View className="border border-gray-300">
<View className="border-2 border-blue-500"> {/* 2px thick */}
<View className="border-t border-gray-200"> {/* Top border only */}

// Border colors
<View className="border border-red-500">
```

### Typography

#### Font Size
```typescript
<Text className="text-xs">    {/* 12px */}
<Text className="text-sm">    {/* 14px */}
<Text className="text-base">  {/* 16px */}
<Text className="text-lg">    {/* 18px */}
<Text className="text-xl">    {/* 20px */}
<Text className="text-2xl">   {/* 24px */}
<Text className="text-3xl">   {/* 30px */}

// Custom sizes
<Text className="text-[17px]"> {/* iOS body text */}
```

#### Font Weight
```typescript
<Text className="font-normal">    {/* 400 */}
<Text className="font-medium">    {/* 500 */}
<Text className="font-semibold">  {/* 600 */}
<Text className="font-bold">      {/* 700 */}
```

#### Text Alignment
```typescript
<Text className="text-left">
<Text className="text-center">
<Text className="text-right">
```

#### Line Height
```typescript
<Text className="leading-tight">  {/* 1.25 */}
<Text className="leading-normal"> {/* 1.5 */}
<Text className="leading-relaxed">{/* 1.75 */}

// Custom line height
<Text className="leading-[22px]">
```

#### Text Transform
```typescript
<Text className="uppercase">
<Text className="lowercase">
<Text className="capitalize">
```

#### Text Decoration
```typescript
<Text className="underline">
<Text className="line-through">
<Text className="no-underline">
```

### Borders & Shadows

#### Border Radius
```typescript
<View className="rounded">       {/* 4px */}
<View className="rounded-lg">    {/* 8px */}
<View className="rounded-xl">    {/* 12px */}
<View className="rounded-2xl">   {/* 16px */}
<View className="rounded-3xl">   {/* 24px */}
<View className="rounded-full">  {/* Circle/pill */}

// Specific corners
<View className="rounded-t-lg">  {/* Top corners */}
<View className="rounded-b-xl">  {/* Bottom corners */}
<View className="rounded-tl-lg rounded-br-lg"> {/* Individual corners */}
```

#### Shadows
**Important**: NativeWind shadows have limitations. Use StyleSheet for iOS shadows.

```typescript
// NativeWind shadow (basic)
<View className="shadow-md">

// Better: Use StyleSheet for iOS
import { StyleSheet, Platform } from 'react-native'

<View className="bg-white rounded-xl" style={styles.shadow}>

const styles = StyleSheet.create({
  shadow: Platform.select({
    ios: {
      shadowColor: '#000',
      shadowOffset: { width: 0, height: 2 },
      shadowOpacity: 0.1,
      shadowRadius: 8,
    },
    android: {
      elevation: 4,
    },
  }),
})
```

### Positioning

#### Position
```typescript
// Relative (default)
<View className="relative">

// Absolute positioning
<View className="absolute top-0 right-0">
<View className="absolute bottom-0 left-0">
<View className="absolute inset-0"> {/* top:0, right:0, bottom:0, left:0 */}

// Specific positions
<View className="absolute top-2 right-4">
<View className="absolute -top-2"> {/* Negative positioning */}
```

#### Z-Index
```typescript
<View className="z-10">
<View className="z-20">
<View className="z-50">
```

### Opacity
```typescript
<View className="opacity-0">    {/* Invisible */}
<View className="opacity-50">   {/* 50% */}
<View className="opacity-100">  {/* Fully visible */}

// Custom opacity
<View className="opacity-[0.15]">
```

## Responsive Design

### Screen Size Classes
NativeWind supports responsive prefixes, but mobile apps typically don't need them (single device at a time).

```typescript
// Rarely needed in mobile
<View className="sm:p-4 lg:p-8">

// More common: Use dimensions hook
import { useWindowDimensions } from 'react-native'

const Component = () => {
  const { width } = useWindowDimensions()
  const isSmall = width < 375 // iPhone SE

  return (
    <View className={isSmall ? 'p-2' : 'p-4'}>
      {/* Content */}
    </View>
  )
}
```

## Platform-Specific Styling

### Platform Prefixes
```typescript
// iOS-only
<View className="ios:shadow-lg">

// Android-only
<View className="android:elevation-4">

// More common: Use Platform.select() in StyleSheet
import { Platform, StyleSheet } from 'react-native'

<View className="rounded-xl" style={styles.shadow}>

const styles = StyleSheet.create({
  shadow: Platform.select({
    ios: {
      shadowColor: '#000',
      shadowOffset: { width: 0, height: 2 },
      shadowOpacity: 0.1,
      shadowRadius: 8,
    },
    android: {
      elevation: 4,
    },
  }),
})
```

## Conditional Styling

### State-Based Styling
```typescript
// Simple conditional
const [isActive, setIsActive] = useState(false)

<View className={isActive ? 'bg-blue-500' : 'bg-gray-300'}>

// Template literals
<View className={`p-4 rounded-lg ${isActive ? 'bg-blue-500' : 'bg-gray-300'}`}>

// Multiple conditions
<Text
  className={`
    text-base
    ${isError ? 'text-red-600' : 'text-gray-900'}
    ${isBold ? 'font-bold' : 'font-normal'}
  `}
>
```

### Pressable State
```typescript
import { Pressable } from 'react-native'

<Pressable
  className={({ pressed }) =>
    `p-4 rounded-lg ${pressed ? 'bg-blue-600' : 'bg-blue-500'}`
  }
>
  <Text className="text-white">Press me</Text>
</Pressable>
```

## Combining with StyleSheet

For complex styles (shadows, transforms), combine NativeWind with StyleSheet:

```typescript
import { StyleSheet } from 'react-native'

const Card = () => (
  <View
    className="bg-white rounded-xl p-4"
    style={styles.card}
  >
    {/* Content */}
  </View>
)

const styles = StyleSheet.create({
  card: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 8,
    // Transform (not available in NativeWind)
    transform: [{ rotate: '5deg' }],
  },
})
```

**When to use StyleSheet**:
- Shadows (iOS)
- Transforms (rotate, skew)
- Complex animations
- Platform-specific styles

**When to use NativeWind**:
- Layout (flex, padding, margin)
- Colors and backgrounds
- Typography
- Border radius
- Simple styling

## Common Patterns

### Card
```typescript
<View className="bg-white rounded-xl p-4 border border-gray-200">
  <Text className="text-lg font-semibold mb-2">Card Title</Text>
  <Text className="text-gray-600">Card content goes here.</Text>
</View>
```

### Button
```typescript
<Pressable
  className={({ pressed }) =>
    `px-6 py-3 rounded-lg ${pressed ? 'bg-blue-600' : 'bg-blue-500'}`
  }
>
  <Text className="text-white font-semibold text-center">
    Press me
  </Text>
</Pressable>
```

### List Item
```typescript
<Pressable className="flex-row items-center p-4 border-b border-gray-200">
  <Image source={...} className="w-12 h-12 rounded-full mr-3" />
  <View className="flex-1">
    <Text className="text-base font-medium">Item Title</Text>
    <Text className="text-sm text-gray-600">Subtitle</Text>
  </View>
  <ChevronRightIcon />
</Pressable>
```

### Input
```typescript
<TextInput
  placeholder="Search"
  className="bg-gray-100 rounded-lg px-4 py-3 text-base"
  placeholderTextColor="#8E8E93"
/>
```

### Badge
```typescript
<View className="bg-red-500 rounded-full px-2 py-1">
  <Text className="text-white text-xs font-semibold">3</Text>
</View>
```

## Important Differences from Web Tailwind

### 1. No `display` Property
```typescript
// ❌ WRONG: No display in RN
<View className="block">
<View className="inline">

// ✅ CORRECT: Use flex (default)
<View className="flex">
<View className="flex-row">
```

### 2. No `gap` in Older RN Versions
```typescript
// ❌ May not work on RN < 0.71
<View className="flex-row gap-4">

// ✅ SAFE: Use margin
<View className="flex-row">
  <View className="mr-4">Item 1</View>
  <View className="mr-4">Item 2</View>
  <View>Item 3</View>
</View>
```

### 3. Limited Shadow Support
```typescript
// ❌ Limited: NativeWind shadows are basic
<View className="shadow-lg">

// ✅ BETTER: Use StyleSheet for iOS shadows
<View style={styles.shadow}>
```

### 4. Text Must Be in `<Text>`
```typescript
// ❌ WRONG: Raw text not allowed
<View>Hello</View>

// ✅ CORRECT: Wrap in Text
<View>
  <Text>Hello</Text>
</View>
```

### 5. No CSS Grid
```typescript
// ❌ WRONG: No grid in RN
<View className="grid grid-cols-3">

// ✅ CORRECT: Use flex
<View className="flex-row flex-wrap">
  <View className="w-1/3">Item 1</View>
  <View className="w-1/3">Item 2</View>
  <View className="w-1/3">Item 3</View>
</View>
```

## Custom Colors

Define custom colors in `tailwind.config.js`:

```javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: '#007AFF',      // iOS blue
        secondary: '#5AC8FA',    // iOS light blue
        success: '#34C759',      // iOS green
        danger: '#FF3B30',       // iOS red
        warning: '#FF9500',      // iOS orange
      },
    },
  },
}
```

Usage:
```typescript
<View className="bg-primary">
<Text className="text-danger">Error message</Text>
```

## Performance Tips

### 1. Avoid Inline Styles When Possible
```typescript
// ❌ SLOWER: Inline className with template literals
{items.map(item => (
  <View key={item.id} className={`p-4 ${item.active ? 'bg-blue-500' : 'bg-gray-300'}`}>
))}

// ✅ FASTER: Pre-compute className
const getItemClass = (active: boolean) =>
  active ? 'p-4 bg-blue-500' : 'p-4 bg-gray-300'

{items.map(item => (
  <View key={item.id} className={getItemClass(item.active)}>
))}
```

### 2. Use StyleSheet for Static Styles
```typescript
// If styles don't change, use StyleSheet
const styles = StyleSheet.create({
  container: {
    padding: 16,
    backgroundColor: '#fff',
  },
})
```

## Quick Reference

| Category | Common Classes |
|----------|----------------|
| Layout | `flex-1`, `flex-row`, `items-center`, `justify-between` |
| Spacing | `p-4`, `m-2`, `px-4`, `py-2`, `gap-3` |
| Sizing | `w-11`, `h-11`, `w-full`, `h-screen` |
| Colors | `bg-white`, `text-gray-900`, `border-gray-200` |
| Typography | `text-base`, `font-semibold`, `text-center` |
| Borders | `rounded-lg`, `rounded-full`, `border` |
| Position | `absolute`, `relative`, `top-0`, `right-0` |

## Related Skills

- @react-native-patterns - Component patterns
- @ios-design-guidelines - iOS design standards

---

NativeWind makes styling React Native components faster and more intuitive. Combine with StyleSheet for complex styles like shadows and transforms.