取り組みの背景 — NativeWindとは?
Rorkで開発したアプリのUIデザインをもっと手軽にカスタマイズしたい、と感じたことはありませんか?Rorkの生成コードはReact Nativeをベースとしており、スタイリングには通常StyleSheet.createを使います。しかし、ウェブ開発でおなじみのTailwind CSSと同じ感覚でモバイルアプリのスタイリングができるライブラリがNativeWindです。
NativeWindはTailwind CSSのユーティリティクラスをReact Nativeに移植したライブラリです。className="bg-blue-500 p-4 rounded-lg"のように、Tailwindと全く同じ記法でスタイルを適用できます。Rorkが生成するExpoベースのプロジェクトとの相性も良く、導入後は開発速度が大幅に向上します。
ここではRorkプロジェクトへのセットアップから基本的な使い方、ダークモード対応まで、実際のコードを交えながら丁寧に解説します。
NativeWindを導入するメリット
RorkプロジェクトにNativeWindを導入すると、いくつかの大きなメリットがあります。
まず、ウェブ開発者がすぐに使いこなせる点が挙げられます。Tailwind CSSを知っていれば追加の学習コストがほとんどかかりません。Rorkを使うユーザーの多くはウェブ開発の経験があることが多く、親しみやすいクラス名でスタイリングできることは大きな魅力です。
次に、コードがシンプルになる点です。従来のStyleSheet.createを使う場合、スタイルの定義とコンポーネントが分離して可読性が下がることがありますが、NativeWindを使えばインラインで完結できます。
さらに、ダークモードの実装が容易になります。dark:プレフィックスをクラスに追加するだけで、ダークモード対応が実現できます。
セットアップ手順
必要な環境
- Rorkで生成したExpoプロジェクト
- Node.js 18以上
- Expo SDK 50以上
パッケージのインストール
まず、NativeWindとTailwind CSSをインストールします。
# NativeWind v4 と Tailwind CSS をインストール
npx expo install nativewind tailwindcss
# Tailwind の設定ファイルを生成
npx tailwindcss inittailwind.config.js の設定
生成されたtailwind.config.jsを編集して、Rorkプロジェクトのファイルパスを指定します。
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
// NativeWind v4 のプリセットを適用
presets: [require('nativewind/preset')],
content: [
'./app/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
'./src/**/*.{js,jsx,ts,tsx}',
],
theme: {
extend: {
// カスタムカラーを定義(ブランドカラーなど)
colors: {
primary: '#6366f1',
secondary: '#8b5cf6',
},
},
},
plugins: [],
};babel.config.js の設定
NativeWindを有効にするため、Babelの設定を更新します。
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [
['babel-preset-expo', { jsxImportSource: 'nativewind' }],
'nativewind/babel',
],
};
};metro.config.js の設定
Metroバンドラーに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' });global.css の作成
プロジェクトルートにglobal.cssを作成します。
/* global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;App エントリーポイントへの読み込み
app/_layout.tsx(またはプロジェクトのエントリーポイント)でCSSを読み込みます。
// app/_layout.tsx
import '../global.css';
import { Stack } from 'expo-router';
export default function RootLayout() {
return <Stack />;
}基本的な使い方
セットアップが完了したら、実際にNativeWindを使ってみましょう。
テキストとレイアウト
// components/WelcomeCard.tsx
import { View, Text } from 'react-native';
export function WelcomeCard() {
return (
// flex-col で縦並び、p-6 でパディング、bg-white で背景白
<View className="flex-col p-6 bg-white rounded-2xl shadow-md mx-4 my-2">
{/* text-2xl で大きめフォント、font-bold で太字、text-gray-800 で文字色 */}
<Text className="text-2xl font-bold text-gray-800 mb-2">
ようこそ!
</Text>
{/* text-base で標準サイズ、text-gray-500 でグレー、leading-relaxed で行間 */}
<Text className="text-base text-gray-500 leading-relaxed">
NativeWindを使ったスタイリングのサンプルです。
Tailwindと同じクラス名が使えます。
</Text>
</View>
);
}ボタンコンポーネント
// 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 でタップ時に透明度を変える
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レイアウト
NativeWindを使えば、React NativeのFlexboxレイアウトをTailwindのクラス名で直感的に記述できます。
// components/CardGrid.tsx
import { View, Text } from 'react-native';
const items = ['🍎 Apple', '🍊 Orange', '🍋 Lemon', '🍇 Grape'];
export function CardGrid() {
return (
// flex-row flex-wrap で横並びかつ折り返し
<View className="flex-row flex-wrap gap-3 p-4">
{items.map((item) => (
<View
key={item}
// w-[48%] で親幅の48%に設定(2列グリッド)
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>
);
}
// 出力: 2列グリッドのフルーツカード一覧ダークモード対応
NativeWindのダークモードサポートは非常に優れています。dark:プレフィックスを追加するだけで実装できます。
// components/ThemedCard.tsx
import { View, Text, useColorScheme } from 'react-native';
export function ThemedCard() {
const colorScheme = useColorScheme();
return (
// dark: プレフィックスでダークモード時のスタイルを指定
<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
">
テーマ対応カード
</Text>
<Text className="
text-sm leading-relaxed
text-gray-600 dark:text-gray-300
">
ライトモード・ダークモードに自動対応。
現在: {colorScheme === 'dark' ? '🌙 ダーク' : '☀️ ライト'}
</Text>
</View>
);
}レスポンシブデザイン
タブレット向けのレスポンシブ対応もsm:・md:プレフィックスで実現できます。
// components/ResponsiveLayout.tsx
import { View, Text } from 'react-native';
export function ResponsiveLayout() {
return (
// スマートフォンでは1列、タブレット(768px以上)では2列
<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">左パネル</Text>
<Text className="text-sm text-blue-600 mt-2">
スマートフォンでは上に表示されます
</Text>
</View>
<View className="flex-1 bg-green-50 rounded-xl p-6">
<Text className="text-lg font-bold text-green-800">右パネル</Text>
<Text className="text-sm text-green-600 mt-2">
タブレットでは横に並びます
</Text>
</View>
</View>
);
}よく使うクラスのまとめ
NativeWindでよく使うクラスを整理しておきます。
レイアウト系
flex-1: 残りスペースを埋める(flex: 1)flex-row: 横並び(flexDirection: 'row')items-center: 縦方向中央揃えjustify-between: 両端寄せ
スペーシング系
p-4: padding 16pxm-2: margin 8pxgap-3: gap 12px(子要素間の間隔)mb-4: margin-bottom 16px
テキスト系
text-xl: フォントサイズ 20pxfont-bold: 太字text-gray-700: グレーの文字色leading-relaxed: 緩やかな行間
見た目系
bg-white: 背景白rounded-xl: 角丸 12pxshadow-md: 中程度の影border border-gray-200: 薄いグレーの枠線
Rorkコードへの適用方法
Rorkが生成したコードにNativeWindを適用する際は、既存のstyleプロパティをclassNameに置き換えていきます。
// Rork生成コード(変更前)
<View style={{ padding: 16, backgroundColor: '#fff', borderRadius: 12 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', color: '#111' }}>
タイトル
</Text>
</View>
// NativeWind適用後(変更後)
<View className="p-4 bg-white rounded-xl">
<Text className="text-lg font-bold text-gray-900">
タイトル
</Text>
</View>UIの一貫性を保つためにも、コンポーネント設計の基礎を学んでおくと役立ちます。Rork で再利用可能な React Native コンポーネントを設計する方法 では、保守性の高いUI設計パターンを解説しています。
よくあるエラーと対処法
エラー1: className が適用されない
MetroやBabelの設定が正しくない場合があります。metro.config.jsとbabel.config.jsを再確認し、expo start --clearでキャッシュをクリアして再起動してください。
エラー2: TypeScriptの型エラー
nativewind/types/index.d.tsの参照が必要です。tsconfig.jsonに以下を追加してください。
{
"compilerOptions": {
"types": ["nativewind/types"]
}
}エラー3: カスタムクラスが効かない
tailwind.config.jsのcontentパスに、該当ファイルが含まれているか確認してください。パスが間違っていると、Tailwindがクラスを検出できません。
さらに詳しいUIデザインの実践については、Rork アプリの UX デザインパターン完全ガイド も合わせてご覧ください。ユーザー体験を向上させる画面設計のヒントが豊富に掲載されています。
まとめ
NativeWindをRorkプロジェクトに導入することで、Tailwind CSSの直感的なクラス名を使ったスタイリングが可能になります。設定手順は少し複雑に見えますが、一度セットアップしてしまえば開発速度が大幅に向上します。特にウェブ開発に慣れている方には、すぐに使いこなせる強力なツールです。
ダークモード対応やレスポンシブデザインもシンプルな記法で実現できるため、アプリのUI品質を底上げするのに役立ちます。ぜひ既存のRorkプロジェクトに取り入れてみてください。
本記事の内容