Communitygithub.com

Geruyang/agent-skills-library

Richte Tailwind CSS v4 in Expo mit react-native-css und NativeWind v5 für universelles Styling ein

Was ist agent-skills-library?

Diese Skill-Anleitung beschreibt die vollständige Einrichtung von Tailwind CSS v4 in einer Expo-Umgebung unter Verwendung von react-native-css und NativeWind v5. Sie ermöglicht einheitliches Styling für iOS-, Android- und Web-Plattformen durch eine moderne, CSS-zentrierte Konfiguration. Die Anleitung deckt die Installation aller erforderlichen Abhängigkeiten, die Einrichtung von Metro-, PostCSS- und globalen CSS-Dateien sowie die Erstellung von wiederverwendbaren CSS-Komponenten-Wrappern (View, Text, ScrollView, Pressable, Image) ab. Ein besonderer Fokus liegt auf der Vermeidung der veralteten Babel-Konfiguration, der Nutzung von Plattform-spezifischen Medienabfragen und der Integration von Apple-Systemfarben über CSS-Variablen. Diese Skill ist ideal für Entwickler, die mit Expo, React Native und Tailwind CSS arbeiten und eine konsistente, moderne Styling-Lösung für ihre Projekte suchen.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Geruyang/agent-skills-library/tree/HEAD/original-skills/x-openai-expo-tailwind-setup-db649d8

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Tailwind CSS Setup für Expo mit react-native-css

Diese Anleitung beschreibt die Einrichtung von Tailwind CSS v4 in Expo unter Verwendung von react-native-css und NativeWind v5 für universelles Styling auf iOS, Android und Web.

Übersicht

Dieses Setup verwendet:

  • Tailwind CSS v4 – Moderne CSS-zentrierte Konfiguration
  • react-native-css – CSS-Laufzeit für React Native
  • NativeWind v5 – Metro-Transformer für Tailwind in React Native
  • @tailwindcss/postcss – PostCSS-Plugin für Tailwind v4

Installation

# Abhängigkeiten installieren
npx expo install tailwindcss@^4 [email protected] [email protected] @tailwindcss/postcss tailwind-merge clsx

Füge Resolutions für lightningcss-Kompatibilität hinzu:

// package.json
{
  "resolutions": {
    "lightningcss": "1.30.1"
  }
}
  • autoprefixer wird in Expo aufgrund von lightningcss nicht benötigt
  • postcss ist standardmäßig in Expo enthalten

Konfigurationsdateien

Metro-Konfiguration

Erstelle oder aktualisiere metro.config.js:

// 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-Variablen brechen PlatformColor in CSS-Variablen
  inlineVariables: false,
  // Wir fügen className-Unterstützung manuell hinzu
  globalClassNamePolyfill: false,
});

PostCSS-Konfiguration

Erstelle postcss.config.mjs:

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

Globales CSS

Erstelle src/global.css:

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

/* Plattform-spezifische Schriftfamilien */
@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;
  }
}

WICHTIG: Keine Babel-Konfiguration erforderlich

Mit Tailwind v4 und NativeWind v5 benötigst du KEINE babel.config.js für Tailwind. Entferne vorhandene NativeWind-Babel-Presets:

// babel.config.js LÖSCHEN, falls sie nur NativeWind-Konfiguration enthält
// Das Folgende wird NICHT MEHR BENÖTIGT:
// module.exports = function (api) {
//   api.cache(true);
//   return {
//     presets: [
//       ["babel-preset-expo", { jsxImportSource: "nativewind" }],
//       "nativewind/babel",
//     ],
//   };
// };

CSS-Komponenten-Wrapper

Da react-native-css explizites CSS-Element-Wrapping erfordert, erstelle wiederverwendbare Komponenten:

Hauptkomponenten (src/tw/index.tsx)

import {
  useCssElement,
  useNativeVariable as useFunctionalVariable,
} from "react-native-css";

import { Link as RouterLink } from "expo-router";
import Animated from "react-native-reanimated";
import React from "react";
import {
  View as RNView,
  Text as RNText,
  Pressable as RNPressable,
  ScrollView as RNScrollView,
  TouchableHighlight as RNTouchableHighlight,
  TextInput as RNTextInput,
  StyleSheet,
} from "react-native";

// CSS-fähiger Link
export const Link = (
  props: React.ComponentProps<typeof RouterLink> & { className?: string }
) => {
  return useCssElement(RouterLink, props, { className: "style" });
};

Link.Trigger = RouterLink.Trigger;
Link.Menu = RouterLink.Menu;
Link.MenuAction = RouterLink.MenuAction;
Link.Preview = RouterLink.Preview;

// CSS-Variable-Hook
export const useCSSVariable =
  process.env.EXPO_OS !== "web"
    ? useFunctionalVariable
    : (variable: string) => `var(${variable})`;

// View
export type ViewProps = React.ComponentProps<typeof RNView> & {
  className?: string;
};

export const View = (props: ViewProps) => {
  return useCssElement(RNView, props, { className: "style" });
};
View.displayName = "CSS(View)";

// Text
export const Text = (
  props: React.ComponentProps<typeof RNText> & { className?: string }
) => {
  return useCssElement(RNText, props, { className: "style" });
};
Text.displayName = "CSS(Text)";

// ScrollView
export const ScrollView = (
  props: React.ComponentProps<typeof RNScrollView> & {
    className?: string;
    contentContainerClassName?: string;
  }
) => {
  return useCssElement(RNScrollView, props, {
    className: "style",
    contentContainerClassName: "contentContainerStyle",
  });
};
ScrollView.displayName = "CSS(ScrollView)";

// Pressable
export const Pressable = (
  props: React.ComponentProps<typeof RNPressable> & { className?: string }
) => {
  return useCssElement(RNPressable, props, { className: "style" });
};
Pressable.displayName = "CSS(Pressable)";

// TextInput
export const TextInput = (
  props: React.ComponentProps<typeof RNTextInput> & { className?: string }
) => {
  return useCssElement(RNTextInput, props, { className: "style" });
};
TextInput.displayName = "CSS(TextInput)";

// AnimatedScrollView
export const AnimatedScrollView = (
  props: React.ComponentProps<typeof Animated.ScrollView> & {
    className?: string;
    contentClassName?: string;
    contentContainerClassName?: string;
  }
) => {
  return useCssElement(Animated.ScrollView, props, {
    className: "style",
    contentClassName: "contentContainerStyle",
    contentContainerClassName: "contentContainerStyle",
  });
};

// TouchableHighlight mit underlayColor-Extraktion
function XXTouchableHighlight(
  props: React.ComponentProps<typeof RNTouchableHighlight>
) {
  const { underlayColor, ...style } = StyleSheet.flatten(props.style) || {};
  return (
    <RNTouchableHighlight
      underlayColor={underlayColor}
      {...props}
      style={style}
    />
  );
}

export const TouchableHighlight = (
  props: React.ComponentProps<typeof RNTouchableHighlight>
) => {
  return useCssElement(XXTouchableHighlight, props, { className: "style" });
};
TouchableHighlight.displayName = "CSS(TouchableHighlight)";

Image-Komponente (src/tw/image.tsx)

import { useCssElement } from "react-native-css";
import React from "react";
import { StyleSheet } from "react-native";
import Animated from "react-native-reanimated";
import { Image as RNImage } from "expo-image";

const AnimatedExpoImage = Animated.createAnimatedComponent(RNImage);

export type ImageProps = React.ComponentProps<typeof Image>;

function CSSImage(props: React.ComponentProps<typeof AnimatedExpoImage>) {
  // @ts-expect-error: Remap objectFit style to contentFit property
  const { objectFit, objectPosition, ...style } =
    StyleSheet.flatten(props.style) || {};

  return (
    <AnimatedExpoImage
      contentFit={objectFit}
      contentPosition={objectPosition}
      {...props}
      source={
        typeof props.source === "string" ? { uri: props.source } : props.source
      }
      // @ts-expect-error: Style is remapped above
      style={style}
    />
  );
}

export const Image = (
  props: React.ComponentProps<typeof CSSImage> & { className?: string }
) => {
  return useCssElement(CSSImage, props, { className: "style" });
};

Image.displayName = "CSS(Image)";

Animierte Komponenten (src/tw/animated.tsx)

import * as TW from "./index";
import RNAnimated from "react-native-reanimated";

export const Animated = {
  ...RNAnimated,
  View: RNAnimated.createAnimatedComponent(TW.View),
};

Verwendung

Importiere CSS-gewrappte Komponenten aus deinem tw-Verzeichnis:

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">Hallo Tailwind!</Text>
        <Image
          className="w-full h-48 rounded-lg object-cover"
          source={{ uri: "https://example.com/image.jpg" }}
        />
      </View>
    </ScrollView>
  );
}

Benutzerdefinierte Theme-Variablen

Füge benutzerdefinierte Theme-Variablen in deinem global.css mit @theme hinzu:

@layer theme {
  @theme {
    /* Benutzerdefinierte Schriften */
    --font-rounded: "SF Pro Rounded", sans-serif;

    /* Benutzerdefinierte Zeilenabstände */
    --text-xs--line-height: calc(1em / 0.75);
    --text-sm--line-height: calc(1.25em / 0.875);
    --text-base--line-height: calc(1.5em / 1);

    /* Benutzerdefinierte Skalierungen */
    --leading-tight: 1.25em;
    --leading-snug: 1.375em;
    --leading-normal: 1.5em;
  }
}

Plattform-spezifische Stile

Verwende Plattform-Medienabfragen für plattformspezifisches Styling:

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

@media android {
  :root {
    --font-sans: normal;
    --font-rounded: normal;
  }
}

Apple-Systemfarben mit CSS-Variablen

Erstelle eine CSS-Datei für Apple-semantische Farben:

/* src/css/sf.css */
@layer base {
  html {
    color-scheme: light;
  }
}

:root {
  /* Akzentfarben mit Hell/Dunkel-Modus */
  --sf-blue: light-dark(rgb(0 122 255), rgb(10 132 255));
  --sf-green: light-dark(rgb(52 199 89), rgb(48 209 89));
  --sf-red: light-dark(rgb(255 59 48), rgb(255 69 58));

  /* Graustufen */
  --sf-gray: light-dark(rgb(142 142 147), rgb(142 142 147));
  --sf-gray-2: light-dark(rgb(174 174 178), rgb(99 99 102));

  /* Textfarben */
  --sf-text: light-dark(rgb(0 0 0), rgb(255 255 255));
  --sf-text-2: light-dark(rgb(60 60 67 / 0.6), rgb(235 235 245 / 0.6));

  /* Hintergrundfarben */
  --sf-bg: light-dark(rgb(255 255 255), rgb(0 0 0));
  --sf-bg-2: light-dark(rgb(242 242 247), rgb(28 28 30));
}

/* iOS native Farben via platformColor */
@media ios {
  :root {
    --sf-blue: platformColor(systemBlue);
    --sf-green: platformColor(systemGreen);
    --sf-red: platformColor(systemRed);
    --sf-gray: platformColor(systemGray);
    --sf-text: platformColor(label);
    --sf-text-2: platformColor(secondaryLabel);
    --sf-bg: platformColor(systemBackground);
    --sf-bg-2: platformColor(secondarySystemBackground);
  }
}

/* Als Tailwind-Theme-Farben registrieren */
@layer theme {
  @theme {
    --color-sf-blue: var(--sf-blue);
    --color-sf-green: var(--sf-green);
    --color-sf-red: var(--sf-red);
    --color-sf-gray: var(--sf-gray);
    --color-sf-text: var(--sf-text);
    --color-sf-text-2: var(--sf-text-2);
    --color-sf-bg: var(--sf-bg);
    --color-sf-bg-2: var(--sf-bg-2);
  }
}

Dann in Komponenten verwenden:

<Text className="text-sf-text">Primärer Text</Text>
<Text className="text-sf-text-2">Sekundärer Text</Text>
<View className="bg-sf-bg">...</View>

CSS-Variablen in JavaScript verwenden

Verwende den useCSSVariable-Hook:

import { useCSSVariable } from "@/tw";

function MyComponent() {
  const blue = useCSSVariable("--sf-blue");

  return <View style={{ borderColor: blue }} />;
}

Hauptunterschiede zu NativeWind v4 / Tailwind v3

  1. Keine babel.config.js – Konfiguration ist jetzt CSS-zentriert
  2. PostCSS-Plugin – Verwendet @tailwindcss/postcss anstelle von tailwindcss
  3. CSS-Importe – Verwende @import "tailwindcss/..." anstelle von @tailwind-Direktiven
  4. Theme-Konfiguration – Verwende @theme in CSS anstelle von tailwind.config.js
  5. Komponenten-Wrapper – Komponenten müssen mit useCssElement für className-Unterstützung gewrappt werden
  6. Metro-Konfiguration – Verwende withNativewind mit anderen Optionen (inlineVariables: false)

Fehlerbehebung

Stile werden nicht angewendet

  1. Stelle sicher, dass die CSS-Datei im App-Einstiegspunkt importiert ist
  2. Überprüfe, ob Komponenten mit useCssElement gewrappt sind
  3. Verifiziere, dass die Metro-Konfiguration withNativewind enthält

Plattformfarben funktionieren nicht

  1. Verwende platformColor() in @media ios-Blöcken
  2. Fallback auf light-dark() für Web/Android

TypeScript-Fehler

Füge className zu den Komponenten-Props hinzu:

type Props = React.ComponentProps<typeof RNView> & { className?: string };

Individual skills in this repo

This repo contains 12 individual skills — each has its own dedicated page.

Geruyang/agent-skills-library

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

Geruyang/agent-skills-library

Use for new frontend applications, dashboards, games, creative websites, hero sections, and visually driven UI from scratch, or when the user explicitly asks for a redesign/restyle/modernization. Builds from clean, airy, high-taste, readable image-generated concept design with section-specific references, faithful implementation, and browser testing.

Geruyang/agent-skills-library

Use when testing, debugging, or making targeted improvements to rendered frontend apps through the Build Web Apps or web dev plugin: local dev servers, UI regressions, interaction bugs, console errors, responsive layout, and visual QA. Check whether the Browser plugin is available and use it first when it is; otherwise use regular Playwright with the recorded reason.

Geruyang/agent-skills-library

Design UI surfaces for browser games. Use when the user asks for HUDs, menus, overlays, responsive layouts, or visual direction that must protect the playfield.

Geruyang/agent-skills-library

GSAP animation reference for HyperFrames. Covers gsap.to(), from(), fromTo(), easing, stagger, defaults, timelines (gsap.timeline(), position parameter, labels, nesting, playback), and performance (transforms, will-change, quickTo). Use when writing GSAP animations in HyperFrames compositions.

Geruyang/agent-skills-library

Guide for building, configuring, and deploying microfrontends on Vercel. Use this skill when the user mentions microfrontends, multi-zones, splitting an app across teams, independent deployments, cross-app routing, incremental migration, composing multiple frontends under one domain, microfrontends.json, @vercel/microfrontends, the microfrontends local proxy, or path-based routing between Vercel projects. Also use when the user asks about shared layouts across projects, navigation between microfrontends, fallback environments, asset prefixes, or feature flag controlled routing.

Geruyang/agent-skills-library

Next.js App Router expert guidance. Use when building, debugging, or architecting Next.js applications — routing, Server Components, Server Actions, Cache Components, layouts, middleware/proxy, data fetching, rendering strategies, and deployment on Vercel.

Geruyang/agent-skills-library

Use when sizing Public Equity Investing positions, finding equity hedges, or building an integrated position-and-hedge risk plan from a listed-equity thesis. Do not use for thesis construction, standalone event underwriting, trade execution, personal investment advice, or credit-instrument risk.

Geruyang/agent-skills-library

Integrate data visualizations into React and Next.js applications. Use when the user needs chart components, UML-like or architecture diagram components, React integration patterns, Next.js client or server boundaries, hydration-safe rendering, lazy loading, framework-aware performance, scroll-driven visual stories, or export guidance.

Geruyang/agent-skills-library

shadcn/ui expert guidance — CLI, component installation, composition patterns, custom registries, theming, Tailwind CSS integration, and high-quality interface design. Use when initializing shadcn, adding components, composing product UI, building custom registries, configuring themes, or troubleshooting component issues.

Geruyang/agent-skills-library

v0 by Vercel expert guidance. Use when discussing AI code generation, generating UI components from prompts, v0 CLI usage, v0 SDK/API integration, or integrating v0 into development workflows with GitHub and Vercel deployment.

Geruyang/agent-skills-library

Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI. Provides project context, component docs, and usage examples. Applies when working with shadcn/ui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for "shadcn init", "create an app with --preset", or "switch to --preset".

Verwandte Skills