Modern Styling Implementation Patterns

1. CSS-in-JS Styled-components Emotion

CSS-in-JS libraries enable writing CSS directly in JavaScript with dynamic styling, scoped styles, and TypeScript support.

Library Features Use Case Bundle Impact
styled-components Tagged templates, theming, SSR, dynamic props, attrs React apps with dynamic theming ~15KB gzipped
Emotion css prop, styled API, composition, framework agnostic Performance-critical apps ~7KB gzipped
Styled JSX Next.js built-in, scoped styles, zero runtime Next.js projects Build-time only
Linaria Zero-runtime, CSS extraction, static styles Performance-first projects 0KB runtime

Example: Styled-components with dynamic theming

// theme.ts
export const theme = {
  colors: {
    primary: '#007acc',
    secondary: '#6c757d',
    danger: '#dc3545'
  },
  spacing: (n: number) => `${n * 8}px`
};

// Button.tsx
import styled from 'styled-components';

const Button = styled.button<{ variant?: 'primary' | 'secondary' }>`
  padding: ${props => props.theme.spacing(2)};
  background: ${props => props.theme.colors[props.variant || 'primary']};
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  
  &:hover {
    opacity: 0.9;
  }
  
  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
`;

// App.tsx
import { ThemeProvider } from 'styled-components';

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Button variant="primary">Submit</Button>
      <Button variant="secondary">Cancel</Button>
    </ThemeProvider>
  );
}

Example: Emotion with css prop (faster than styled-components)

/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

const buttonStyle = css`
  padding: 12px 24px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  transition: transform 0.2s;
  
  &:hover {
    transform: translateY(-2px);
  }
`;

function Button({ children }) {
  return <button css={buttonStyle}>{children}</button>;
}

// Composition
const primaryButton = css`
  ${buttonStyle};
  background: #007acc;
`;

const dangerButton = css`
  ${buttonStyle};
  background: #dc3545;
`;
Note: Styled-components offers better DX with DevTools and component names in DOM. Emotion is 50% smaller and faster but requires css prop setup. Linaria for zero-runtime SSG sites.

2. Tailwind CSS Utility-first Design

Utility-first CSS framework for rapid UI development with consistent design system and minimal custom CSS.

Category Utilities Example Output CSS
Layout flex, grid, container, box-sizing flex items-center justify-between display: flex; align-items: center; justify-content: space-between
Spacing p-*, m-*, space-*, gap-* p-4 m-2 gap-6 padding: 1rem; margin: 0.5rem; gap: 1.5rem
Typography text-*, font-*, leading-*, tracking-* text-xl font-bold text-gray-900 font-size: 1.25rem; font-weight: 700; color: #111827
Colors bg-*, text-*, border-*, from-*, to-* bg-blue-500 text-white background: #3b82f6; color: #ffffff
Responsive sm:*, md:*, lg:*, xl:*, 2xl:* sm:w-full md:w-1/2 lg:w-1/3 Media query breakpoints: 640px, 768px, 1024px, 1280px, 1536px
States hover:*, focus:*, active:*, disabled:* hover:bg-blue-600 focus:ring-2 Pseudo-class variants

Example: Tailwind configuration and custom utilities

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{js,jsx,ts,tsx}'],
  theme: {
    extend: {
      colors: {
        brand: {
          50: '#f0f9ff',
          500: '#0ea5e9',
          900: '#0c4a6e'
        }
      },
      spacing: {
        '18': '4.5rem',
        '88': '22rem'
      },
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif']
      }
    }
  },
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/aspect-ratio')
  ]
};

// Component usage
function Card() {
  return (
    <div className="bg-white rounded-lg shadow-lg p-6 hover:shadow-xl transition-shadow">
      <h2 className="text-2xl font-bold text-gray-900 mb-4">Card Title</h2>
      <p className="text-gray-600 leading-relaxed">Card content</p>
      <button className="mt-4 px-6 py-2 bg-brand-500 text-white rounded-md 
                         hover:bg-brand-600 focus:ring-2 focus:ring-brand-500 
                         focus:ring-offset-2 disabled:opacity-50">
        Action
      </button>
    </div>
  );
}

Example: Responsive design with Tailwind

// Mobile-first responsive layout
function ResponsiveGrid() {
  return (
    <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
      <div className="bg-gray-100 p-4 rounded-lg">Item 1</div>
      <div className="bg-gray-100 p-4 rounded-lg">Item 2</div>
      <div className="bg-gray-100 p-4 rounded-lg">Item 3</div>
    </div>
  );
}

// Dark mode support
function DarkModeButton() {
  return (
    <button className="bg-white dark:bg-gray-800 text-gray-900 dark:text-white 
                       border border-gray-300 dark:border-gray-700 px-4 py-2 rounded-md">
      Toggle
    </button>
  );
}
Tailwind Best Practices: Use @apply for repeated patterns, configure PurgeCSS for production builds (~3KB final CSS), use JIT mode for instant compilation, leverage plugins ecosystem.

3. CSS Variables Custom Properties

Native CSS custom properties for dynamic theming, runtime updates, and component-scoped styling without JavaScript overhead.

Feature Syntax Scope Use Case
Definition --variable-name: value; :root, element, inline Define reusable values
Usage var(--variable-name, fallback) Any CSS property Apply variable with fallback
Inheritance Cascades to descendants DOM tree Component theming
JavaScript Access getComputedStyle(), setProperty() Runtime Dynamic theme switching
Media Queries Change values per breakpoint Responsive Adaptive spacing/sizing

Example: Design system with CSS variables

/* styles/variables.css */
:root {
  /* Colors */
  --color-primary: #007acc;
  --color-secondary: #6c757d;
  --color-success: #28a745;
  --color-danger: #dc3545;
  --color-warning: #ffc107;
  
  /* Spacing scale */
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  
  /* Typography */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'Fira Code', monospace;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.25rem;
  
  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
  
  /* Border radius */
  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 1rem;
  
  /* Transitions */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;
}

/* Component styles */
.button {
  padding: var(--space-md) var(--space-lg);
  background: var(--color-primary);
  color: white;
  border: none;
  border-radius: var(--radius-md);
  font-size: var(--font-size-base);
  transition: all var(--transition-base);
  box-shadow: var(--shadow-sm);
}

.button:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.card {
  padding: var(--space-lg);
  background: white;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

Example: Runtime theme switching with JavaScript

// themes.ts
export const lightTheme = {
  '--color-bg': '#ffffff',
  '--color-text': '#1a1a1a',
  '--color-border': '#e5e5e5'
};

export const darkTheme = {
  '--color-bg': '#1a1a1a',
  '--color-text': '#ffffff',
  '--color-border': '#333333'
};

// ThemeProvider.tsx
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  useEffect(() => {
    const root = document.documentElement;
    const themeVars = theme === 'light' ? lightTheme : darkTheme;
    
    Object.entries(themeVars).forEach(([key, value]) => {
      root.style.setProperty(key, value);
    });
  }, [theme]);
  
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Component usage
function ThemedCard() {
  return (
    <div style={{
      background: 'var(--color-bg)',
      color: 'var(--color-text)',
      border: '1px solid var(--color-border)'
    }}>
      Themed content
    </div>
  );
}
Browser Support: Excellent - All modern browsers support CSS custom properties. Use PostCSS plugins for older browser fallbacks.

4. Design Tokens Figma Integration

Design tokens are platform-agnostic design decisions (colors, spacing, typography) synced between design tools and code.

Tool/Format Purpose Integration Output
Figma Tokens Plugin Extract tokens from Figma designs JSON export, GitHub sync tokens.json with color, spacing, typography
Style Dictionary Transform tokens to platform formats Build system integration CSS, SCSS, JS, iOS, Android
Tokens Studio Manage multi-brand token sets Figma plugin with Git sync Semantic + alias tokens
Theo (Salesforce) Design token transformation CLI, Node API Multiple formats from single source

Example: Design tokens structure (tokens.json)

{
  "color": {
    "brand": {
      "primary": { "value": "#007acc", "type": "color" },
      "secondary": { "value": "#6c757d", "type": "color" }
    },
    "semantic": {
      "success": { "value": "{color.brand.primary}", "type": "color" },
      "danger": { "value": "#dc3545", "type": "color" }
    }
  },
  "spacing": {
    "xs": { "value": "4px", "type": "spacing" },
    "sm": { "value": "8px", "type": "spacing" },
    "md": { "value": "16px", "type": "spacing" },
    "lg": { "value": "24px", "type": "spacing" },
    "xl": { "value": "32px", "type": "spacing" }
  },
  "typography": {
    "fontFamily": {
      "sans": { "value": "Inter, system-ui, sans-serif", "type": "fontFamily" },
      "mono": { "value": "Fira Code, monospace", "type": "fontFamily" }
    },
    "fontSize": {
      "sm": { "value": "14px", "type": "fontSize" },
      "base": { "value": "16px", "type": "fontSize" },
      "lg": { "value": "20px", "type": "fontSize" },
      "xl": { "value": "24px", "type": "fontSize" }
    },
    "fontWeight": {
      "regular": { "value": "400", "type": "fontWeight" },
      "medium": { "value": "500", "type": "fontWeight" },
      "bold": { "value": "700", "type": "fontWeight" }
    }
  },
  "borderRadius": {
    "sm": { "value": "4px", "type": "borderRadius" },
    "md": { "value": "8px", "type": "borderRadius" },
    "lg": { "value": "16px", "type": "borderRadius" },
    "full": { "value": "9999px", "type": "borderRadius" }
  }
}

Example: Style Dictionary configuration and build

// style-dictionary.config.js
module.exports = {
  source: ['tokens/**/*.json'],
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'src/styles/',
      files: [{
        destination: 'variables.css',
        format: 'css/variables'
      }]
    },
    js: {
      transformGroup: 'js',
      buildPath: 'src/tokens/',
      files: [{
        destination: 'tokens.js',
        format: 'javascript/es6'
      }]
    },
    typescript: {
      transformGroup: 'js',
      buildPath: 'src/tokens/',
      files: [{
        destination: 'tokens.ts',
        format: 'typescript/es6-declarations'
      }]
    }
  }
};

// Generated CSS output (variables.css)
:root {
  --color-brand-primary: #007acc;
  --color-brand-secondary: #6c757d;
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --font-family-sans: Inter, system-ui, sans-serif;
  --font-size-base: 16px;
  --font-weight-bold: 700;
  --border-radius-md: 8px;
}

// Generated TypeScript output (tokens.ts)
export const tokens = {
  color: {
    brand: {
      primary: '#007acc',
      secondary: '#6c757d'
    }
  },
  spacing: {
    xs: '4px',
    sm: '8px',
    md: '16px'
  }
};
Workflow: Design in Figma → Export tokens via plugin → Transform with Style Dictionary → Generate CSS/JS/iOS/Android → Import in codebase. Automate with CI/CD for design-dev sync.

5. Dark Mode Light Mode Toggle

Implement theme switching with system preference detection, persistent storage, and smooth transitions.

Approach Implementation Pros Cons
CSS Media Query @media (prefers-color-scheme: dark) Native, automatic, no JS No manual toggle
Data Attribute [data-theme="dark"] on root Easy CSS targeting, semantic Requires JS for toggle
Class Toggle .dark class on root Simple, Tailwind compatible Flash of wrong theme (FOUT)
CSS Variables Change variable values dynamically Smooth transitions, runtime More complex setup

Example: Complete dark mode implementation with persistence

// theme.css
:root {
  --color-bg: #ffffff;
  --color-text: #1a1a1a;
  --color-border: #e5e5e5;
  --color-card-bg: #f8f9fa;
}

[data-theme="dark"] {
  --color-bg: #1a1a1a;
  --color-text: #ffffff;
  --color-border: #333333;
  --color-card-bg: #2d2d2d;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  transition: background-color 0.3s ease, color 0.3s ease;
}

// useTheme.ts hook
import { useEffect, useState } from 'react';

type Theme = 'light' | 'dark' | 'system';

export function useTheme() {
  const [theme, setTheme] = useState<Theme>(() => {
    const stored = localStorage.getItem('theme') as Theme;
    return stored || 'system';
  });

  useEffect(() => {
    const root = document.documentElement;
    const systemPreference = window.matchMedia('(prefers-color-scheme: dark)');
    
    const applyTheme = (newTheme: Theme) => {
      let appliedTheme: 'light' | 'dark';
      
      if (newTheme === 'system') {
        appliedTheme = systemPreference.matches ? 'dark' : 'light';
      } else {
        appliedTheme = newTheme;
      }
      
      root.setAttribute('data-theme', appliedTheme);
      localStorage.setItem('theme', newTheme);
    };
    
    applyTheme(theme);
    
    // Listen for system preference changes
    const handleChange = (e: MediaQueryListEvent) => {
      if (theme === 'system') {
        root.setAttribute('data-theme', e.matches ? 'dark' : 'light');
      }
    };
    
    systemPreference.addEventListener('change', handleChange);
    return () => systemPreference.removeEventListener('change', handleChange);
  }, [theme]);
  
  return { theme, setTheme };
}

// ThemeToggle.tsx component
function ThemeToggle() {
  const { theme, setTheme } = useTheme();
  
  return (
    <div className="theme-toggle">
      <button 
        onClick={() => setTheme('light')}
        aria-pressed={theme === 'light'}
      >
        ☀️ Light
      </button>
      <button 
        onClick={() => setTheme('dark')}
        aria-pressed={theme === 'dark'}
      >
        🌙 Dark
      </button>
      <button 
        onClick={() => setTheme('system')}
        aria-pressed={theme === 'system'}
      >
        💻 System
      </button>
    </div>
  );
}

Example: Prevent flash of wrong theme (critical inline script)

<!-- Place in <head> before any CSS -->
<script>
  (function() {
    const theme = localStorage.getItem('theme') || 'system';
    const systemPreference = window.matchMedia('(prefers-color-scheme: dark)').matches;
    
    let appliedTheme;
    if (theme === 'system') {
      appliedTheme = systemPreference ? 'dark' : 'light';
    } else {
      appliedTheme = theme;
    }
    
    document.documentElement.setAttribute('data-theme', appliedTheme);
  })();
</script>

<!-- Next.js implementation in _document.tsx -->
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <script dangerouslySetInnerHTML={{
          __html: `
            (function() {
              const theme = localStorage.getItem('theme') || 'system';
              const dark = theme === 'dark' || 
                (theme === 'system' && 
                 window.matchMedia('(prefers-color-scheme: dark)').matches);
              document.documentElement.setAttribute('data-theme', dark ? 'dark' : 'light');
            })();
          `
        }} />
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}
Performance: Avoid transition: all on theme toggle (causes layout thrashing). Target specific properties: background-color, color, border-color. Use prefers-reduced-motion for accessibility.

6. Component Library MUI Chakra UI

Production-ready component libraries with theming, accessibility, and extensive component catalogs.

Library Key Features Best For Bundle Size
Material-UI (MUI) Material Design, comprehensive components, theming system Enterprise apps, admin panels ~80KB core + components
Chakra UI Accessible, composable, dark mode, styled-system Modern apps, fast development ~45KB + components
Ant Design Enterprise UI, rich components, internationalization Data-heavy dashboards ~60KB core + components
Mantine Full-featured, hooks library, 120+ components Complete solution, TypeScript ~50KB + components
Radix UI Unstyled, accessible primitives, headless Custom designs, full control Minimal, per-component
shadcn/ui Copy-paste components, Radix + Tailwind Full customization, no dependencies Only what you use

Example: Material-UI (MUI) with custom theme

// theme.ts
import { createTheme } from '@mui/material/styles';

export const theme = createTheme({
  palette: {
    primary: {
      main: '#007acc',
      light: '#42a5f5',
      dark: '#005fa3'
    },
    secondary: {
      main: '#6c757d'
    },
    mode: 'light' // or 'dark'
  },
  typography: {
    fontFamily: 'Inter, system-ui, sans-serif',
    h1: {
      fontSize: '2.5rem',
      fontWeight: 700
    }
  },
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          borderRadius: 8,
          textTransform: 'none',
          boxShadow: 'none'
        }
      },
      defaultProps: {
        disableElevation: true
      }
    }
  }
});

// App.tsx
import { ThemeProvider } from '@mui/material/styles';
import { Button, TextField, Card, CardContent } from '@mui/material';

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Card>
        <CardContent>
          <TextField 
            label="Email" 
            variant="outlined" 
            fullWidth 
            margin="normal"
          />
          <Button variant="contained" color="primary">
            Submit
          </Button>
        </CardContent>
      </Card>
    </ThemeProvider>
  );
}

Example: Chakra UI with composition and dark mode

// App.tsx
import { ChakraProvider, extendTheme, Box, Button, Input, Stack } from '@chakra-ui/react';

const theme = extendTheme({
  colors: {
    brand: {
      50: '#e3f2fd',
      500: '#007acc',
      900: '#003d66'
    }
  },
  config: {
    initialColorMode: 'light',
    useSystemColorMode: true
  }
});

function App() {
  return (
    <ChakraProvider theme={theme}>
      <Box p={8} bg="gray.50" minH="100vh">
        <Stack spacing={4} maxW="md">
          <Input placeholder="Email" size="lg" />
          <Button 
            colorScheme="brand" 
            size="lg" 
            _hover={{ transform: 'translateY(-2px)', boxShadow: 'lg' }}
          >
            Submit
          </Button>
        </Stack>
      </Box>
    </ChakraProvider>
  );
}

// ColorModeToggle.tsx
import { useColorMode, IconButton } from '@chakra-ui/react';
import { SunIcon, MoonIcon } from '@chakra-ui/icons';

function ColorModeToggle() {
  const { colorMode, toggleColorMode } = useColorMode();
  return (
    <IconButton
      aria-label="Toggle color mode"
      icon={colorMode === 'light' ? <MoonIcon /> : <SunIcon />}
      onClick={toggleColorMode}
    />
  );
}

Example: shadcn/ui with Radix primitives (copy-paste approach)

// components/ui/button.tsx (copied from shadcn/ui)
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input hover:bg-accent hover:text-accent-foreground",
        ghost: "hover:bg-accent hover:text-accent-foreground"
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button";
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    );
  }
);

// Usage
import { Button } from "@/components/ui/button";

function MyComponent() {
  return (
    <>
      <Button variant="default">Default</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost" size="sm">Small Ghost</Button>
    </>
  );
}
MUI Pros: Material Design consistency, massive component library (100+), strong TypeScript support, excellent documentation, MUI X for advanced components (DataGrid, Date Pickers).
Chakra UI Pros: Excellent DX with style props, built-in dark mode, smaller bundle, composable design, fast setup. Great for startups and modern apps.

Styling Strategy Decision Matrix

Use Case Recommended Approach Rationale
Rapid prototyping Tailwind CSS + shadcn/ui Fast development, no custom CSS, full control
Enterprise dashboard MUI or Ant Design Rich components, data tables, consistency
Design system from scratch Radix UI + CSS Variables + Tokens Full customization, brand consistency
Performance-critical Tailwind CSS + Linaria Zero-runtime CSS, optimal bundle size
Dynamic theming CSS Variables + Chakra UI Runtime theme switching, easy dark mode