SuperAPI AI 工具集

expo-tailwind-setup

前端与建站

查看项目

更新于 10-16 02:12

技能介绍

用途

该技能用于在 Expo 项目中搭建 Tailwind CSS v4,配合 react-native-css 和 NativeWind v5,实现跨 iOS、Android 与 Web 的通用样式(universal styling)。当任务明确属于该上游产品或 API 范围时使用。

主要能力

该方案组合以下组件:

  • Tailwind CSS v4:现代 CSS-first 配置方式
  • react-native-css:React Native 的 CSS 运行时
  • NativeWind v5:React Native 中 Tailwind 的 Metro 转换器
  • @tailwindcss/postcss:Tailwind v4 的 PostCSS 插件

使用方式

安装

npx expo install tailwindcss@^4 nativewind@5.0.0-preview.2 react-native-css@0.0.0-nightly.5ce6396 @tailwindcss/postcss tailwind-merge clsx

为 lightningcss 兼容性添加 resolutions:

// package.json
{
  "resolutions": {
    "lightningcss": "1.30.1"
  }
}

Expo 中因使用 lightningcss,不需要 autoprefixer;postcss 已默认包含在 expo 中。

配置文件

Metro 配置(metro.config.js):

const { getDefaultConfig } = require("expo/metro-config");
const { withNativewind } = require("nativewind/metro");

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

module.exports = withNativewind(config, {
  // inline variables break PlatformColor in CSS variables
  inlineVariables: false,
  // We add className support manually
  globalClassNamePolyfill: false,
});

PostCSS 配置(postcss.config.mjs):

export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

全局 CSS(src/global.css):

@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css";

/* Platform-specific font families */
@media android {
  :root {
    --font-mono: monospace;
    --font-rounded: normal;
    --font-serif: serif;
    --font-sans: normal;
  }
}

@media ios {
  :root {
    --font-mono: ui-monospace;
    --font-serif: ui-serif;
    --font-sans: system-ui;
    --font-rounded: ui-rounded;
  }
}

注意:使用 Tailwind v4 和 NativeWind v5 时,Tailwind 不需要 babel.config.js。如果存在仅包含 NativeWind 配置的 babel.config.js,应删除;不再需要 nativewind/babel 预设与 jsxImportSource 配置。

CSS 组件包装器

由于 react-native-css 需要显式包装 CSS 元素,需创建可复用组件。

主组件(src/tw/index.tsx)使用 useCssElement 与 useNativeVariable 包装 Link、View、Text、ScrollView、Pressable、TextInput、AnimatedScrollView、TouchableHighlight 等,并为每个组件设置 displayName。其中 Link 保留 RouterLink 的 Trigger、Menu、MenuAction、Preview 静态属性;useCSSVariable 在非 Web 平台使用 useFunctionalVariable,Web 平台返回 var(${variable}) 字符串。

Image 组件(src/tw/image.tsx)基于 expo-image 的 Image 与 react-native-reanimated 创建动画组件,将 objectFit 映射为 contentFit、objectPosition 映射为 contentPosition,并将字符串 source 转换为 { uri: source }。

动画组件(src/tw/animated.tsx)导出 Animated 对象,包含 reanimated 全部导出以及用 createAnimatedComponent 包装的 TW.View。

使用示例

import { View, Text, ScrollView, Image } from "@/tw";

export default function MyScreen() {
  return (
    <ScrollView className="flex-1 bg-white">
      <View className="p-4 gap-4">
        <Text className="text-xl font-bold text-gray-900">Hello Tailwind!</Text>
        <Image
          className="w-full h-48 rounded-lg object-cover"
          source={{ uri: "https://example.com/image.jpg" }}
        />
      </View>
    </ScrollView>
  );
}

自定义主题变量

在 global.css 中使用 @theme 添加自定义主题变量,例如自定义字体 --font-rounded、自定义行高 --text-xs--line-height 等,以及 --leading-tight、--leading-snug、--leading-normal 等 leading 比例。

平台特定样式

使用平台媒体查询,例如在 @media ios 与 @media android 中分别设置 --font-sans、--font-rounded 等变量。

Apple 系统颜色与 CSS 变量

可创建 src/css/sf.css,在 :root 中用 light-dark() 定义 --sf-blue、--sf-green、--sf-red、--sf-gray、--sf-text、--sf-bg 等语义颜色;在 @media ios 中改用 platformColor() 引用 iOS 原生颜色(如 systemBlue、label、systemBackground 等);再通过 @layer theme 的 @theme 注册为 Tailwind 主题颜色(--color-sf-blue 等),即可在组件中使用 text-sf-text、bg-sf-bg 等类名。

在 JavaScript 中使用 CSS 变量可通过 useCSSVariable 钩子,例如 const blue = useCSSVariable("--sf-blue"),再用于内联样式。

与 NativeWind v4 / Tailwind v3 的关键差异

  • 不再需要 babel.config.js,配置改为 CSS-first
  • 使用 @tailwindcss/postcss 而非 tailwindcss 作为 PostCSS 插件
  • 使用 @import "tailwindcss/..." 而非 @tailwind 指令
  • 使用 CSS 中的 @theme 而非 tailwind.config.js 进行主题配置
  • 组件必须用 useCssElement 包装以支持 className
  • Metro 配置使用 withNativewind 且选项不同(inlineVariables: false)

常见问题排查

  • 样式未生效:确认应用入口已导入 CSS 文件;确认组件已用 useCssElement 包装;确认 Metro 配置已应用 withNativewind。
  • 平台颜色不工作:在 @media ios 块中使用 platformColor();Web/Android 回退到 light-dark()。
  • TypeScript 报错:为组件 props 添加 className,例如 type Props = React.ComponentProps<typeof RNView> & { className?: string }。

适用场景与限制

适用于需要在 Expo 中统一 iOS、Android、Web 样式的项目。使用限制:仅在任务明确匹配其上游产品或 API 范围时使用;在做出更改前,应依据当前官方文档核实命令、API 行为、定价、配额、凭据与部署影响;生成的示例不能替代针对具体环境的测试、安全审查,以及对破坏性或高成本操作的用户批准。