--- name: web-styling description: Styling patterns for React web applications. Use when working with Tailwind CSS, CSS Modules, theming, responsive design, or component styling. --- # Web Styling (React) ## Tailwind CSS ### Basic Usage ```typescript function Button({ variant = 'primary', children }) { const baseClasses = 'px-4 py-2 rounded-lg font-medium transition-colors'; const variants = { primary: 'bg-blue-600 text-white hover:bg-blue-700', secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300', danger: 'bg-red-600 text-white hover:bg-red-700', }; return ( ); } ``` ### Conditional Classes with clsx/cn ```typescript import { clsx } from 'clsx'; // or with tailwind-merge for deduplication import { twMerge } from 'tailwind-merge'; function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } function Card({ isActive, isDisabled, className, children }) { return (
{children}
); } ``` ### Responsive Design ```typescript // Mobile-first breakpoints // sm: 640px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px
{items.map(item => )}
// Responsive text

Title

// Hide/show at breakpoints ``` ### Dark Mode ```typescript // tailwind.config.js module.exports = { darkMode: 'class', // or 'media' for OS preference // ... }; // Component

Title

Description

// Toggle dark mode function ThemeToggle() { const [isDark, setIsDark] = useState(false); useEffect(() => { document.documentElement.classList.toggle('dark', isDark); }, [isDark]); return ( ); } ``` ### Custom Design Tokens ```javascript // tailwind.config.js module.exports = { theme: { extend: { colors: { brand: { 50: '#f0f9ff', 100: '#e0f2fe', 500: '#0ea5e9', 600: '#0284c7', 700: '#0369a1', }, }, fontFamily: { sans: ['Inter', 'system-ui', 'sans-serif'], }, spacing: { '18': '4.5rem', '88': '22rem', }, }, }, }; ``` ```typescript // Usage ``` --- ## CSS Modules ### Basic Usage ```css /* Button.module.css */ .button { padding: 0.5rem 1rem; border-radius: 0.5rem; font-weight: 500; } .primary { background-color: #3b82f6; color: white; } .secondary { background-color: #e5e7eb; color: #1f2937; } ``` ```typescript // Button.tsx import styles from './Button.module.css'; function Button({ variant = 'primary', children }) { return ( ); } ``` ### With clsx ```typescript import styles from './Card.module.css'; import { clsx } from 'clsx'; function Card({ isActive, className, children }) { return (
{children}
); } ``` --- ## CSS-in-JS (styled-components) ```typescript import styled from 'styled-components'; const Button = styled.button<{ variant?: 'primary' | 'secondary' }>` padding: 0.5rem 1rem; border-radius: 0.5rem; font-weight: 500; transition: background-color 0.2s; ${({ variant = 'primary' }) => variant === 'primary' ? ` background-color: #3b82f6; color: white; &:hover { background-color: #2563eb; } ` : ` background-color: #e5e7eb; color: #1f2937; &:hover { background-color: #d1d5db; } `} `; // With theme import { ThemeProvider } from 'styled-components'; const theme = { colors: { primary: '#3b82f6', secondary: '#e5e7eb', }, spacing: { sm: '0.5rem', md: '1rem', }, }; const ThemedButton = styled.button` background-color: ${({ theme }) => theme.colors.primary}; padding: ${({ theme }) => theme.spacing.md}; `; ``` --- ## Component Variants Pattern ```typescript // Using cva (class-variance-authority) with Tailwind import { cva, type VariantProps } from 'class-variance-authority'; const buttonVariants = cva( 'inline-flex items-center justify-center rounded-md font-medium transition-colors', { variants: { variant: { primary: 'bg-blue-600 text-white hover:bg-blue-700', secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200', outline: 'border border-gray-300 hover:bg-gray-50', ghost: 'hover:bg-gray-100', danger: 'bg-red-600 text-white hover:bg-red-700', }, size: { sm: 'h-8 px-3 text-sm', md: 'h-10 px-4', lg: 'h-12 px-6 text-lg', }, }, defaultVariants: { variant: 'primary', size: 'md', }, } ); interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps {} function Button({ variant, size, className, ...props }: ButtonProps) { return ( ``` --- ## Animation Patterns ### Tailwind Animations ```typescript // Built-in animations
Loading...
Loading...
Scroll down
// Transitions // Custom animation in tailwind.config.js module.exports = { theme: { extend: { animation: { 'fade-in': 'fadeIn 0.3s ease-out', 'slide-up': 'slideUp 0.3s ease-out', }, keyframes: { fadeIn: { '0%': { opacity: '0' }, '100%': { opacity: '1' }, }, slideUp: { '0%': { transform: 'translateY(10px)', opacity: '0' }, '100%': { transform: 'translateY(0)', opacity: '1' }, }, }, }, }, }; // Usage
Fading in...
``` ### Framer Motion ```typescript import { motion, AnimatePresence } from 'framer-motion'; function Modal({ isOpen, onClose, children }) { return ( {isOpen && ( <> {children} )} ); } ``` --- ## Layout Patterns ### Flexbox ```typescript // Centering
Centered content
// Space between
// Responsive direction
``` ### Grid ```typescript // Equal columns
{items.map(item => )}
// Complex layout
Main content
// Auto-fit for unknown count
{items.map(item => )}
``` ### Container ```typescript // Centered container with max-width
// Or with custom max-width
``` --- ## Theming System ```typescript // theme.ts export const theme = { colors: { primary: { 50: '#eff6ff', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', }, gray: { 50: '#f9fafb', 100: '#f3f4f6', 900: '#111827', }, }, spacing: { xs: '0.25rem', sm: '0.5rem', md: '1rem', lg: '1.5rem', xl: '2rem', }, } as const; // CSS Variables approach :root { --color-primary: #3b82f6; --color-background: #ffffff; --color-text: #111827; } .dark { --color-primary: #60a5fa; --color-background: #111827; --color-text: #f9fafb; } // Usage with Tailwind
Content
``` --- ## Common Issues | Issue | Solution | |-------|----------| | Styles not applying | Check class specificity, Tailwind purging | | Dark mode flicker | Use CSS variables or SSR-safe approach | | Layout shift | Set explicit dimensions, use skeleton loaders | | Mobile overflow | Add `overflow-x-hidden` to body | | Z-index conflicts | Use consistent z-index scale | --- ## File Structure ``` styles/ globals.css # Global styles, Tailwind imports variables.css # CSS custom properties components/ Button/ Button.tsx Button.module.css # If using CSS Modules index.ts tailwind.config.js # Tailwind configuration ```