Go Back

Apr 17, 2025

Styling and Theming in Next js

we’ll cover built-in styling methods as well as popular CSS-in-JS and utility-first approaches.

Styling and Theming in Next js

1. CSS Modules

Next.js supports CSS Modules out of the box for component-scoped styles:

  1. Create a .module.css file alongside your component:

    /* styles/Button.module.css */
    .button {
      background-color: #0070f3;
      padding: 0.75rem 1.5rem;
      border-radius: 0.5rem;
      color: white;
      font-weight: bold;
      cursor: pointer;
      transition: background-color 0.2s;
    }
    .button:hover {
      background-color: #0051a3;
    }
  2. Import and apply the module in your React component:

    import styles from '../styles/Button.module.css';
    
    export default function Button({ children, onClick }) {
      return (
        <button className={styles.button} onClick={onClick}>
          {children}
        </button>
      );
    }

Tip: CSS Modules automatically generate unique class names to avoid collisions across components.

2. Global Styles and `_app.js`

For styles that apply across the entire application (fonts, resets, utilities), use global CSS:

  1. Create styles/globals.css:

    /* styles/globals.css */
    html, body {
      padding: 0;
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto;
      background-color: var(--bg);
      color: var(--fg);
    }
    :root {
      --fg: #333;
      --bg: #fff;
      --primary: #0070f3;
    }
  2. Import in pages/_app.js:

    import '../styles/globals.css';
    
    function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />;
    }
    
    export default MyApp;

3. CSS-in-JS with `styled-jsx`

Next.js includes styled-jsx for scoped CSS in JavaScript:

export default function Card({ children }) {
  return (
    <div className="card">
      {children}
      <style jsx>{`
        .card {
          padding: 1.5rem;
          border: 1px solid #eaeaea;
          border-radius: 0.75rem;
          transition: box-shadow 0.2s;
        }
        .card:hover {
          box-shadow: 0 4px 14px rgba(0, 118, 255, 0.2);
        }
      `}</style>
    </div>
  );
}

Note: Styles defined with styled-jsx are local to the component, avoiding global conflicts.

4. Tailwind CSS Integration

Tailwind CSS is a popular utility-first framework that pairs nicely with Next.js:

  1. Install dependencies:

    npm install -D tailwindcss postcss autoprefixer
    npx tailwindcss init -p
  2. Configure tailwind.config.js:

    module.exports = {
      content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
      theme: { extend: {} },
      plugins: [],
    };
  3. Add Tailwind directives to globals.css:

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
  4. Use utility classes in your components:

    export default function Hero() {
      return (
        <section className="bg-primary/10 py-16">
          <h1 className="text-4xl font-extrabold text-center text-primary">
            Welcome to My Next.js Site
          </h1>
        </section>
      );
    }

Tip: Leverage @tailwindcss/forms and other official plugins for rapid form and UI styling.

5. Theming and Dark Mode

Next.js apps can support light/dark themes using CSS variables and a context or library like next-themes:

  1. Install: npm install next-themes

  2. Wrap your app in ThemeProvider:

    // pages/_app.js
    import { ThemeProvider } from 'next-themes';
    import '../styles/globals.css';
    
    function MyApp({ Component, pageProps }) {
      return (
        <ThemeProvider attribute="class">
          <Component {...pageProps} />
        </ThemeProvider>
      );
    }
    
    export default MyApp;
  3. Toggle Themes in a Component:

    import { useTheme } from 'next-themes';
    
    export default function ThemeToggle() {
      const { theme, setTheme } = useTheme();
      return (
        <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
          {theme === 'light' ? '🌙 Dark Mode' : '☀️ Light Mode'}
        </button>
      );
    }
  4. Define classes in CSS for dark mode:

    /* globals.css */
    .light {
      --bg: #ffffff;
      --fg: #000000;
    }
    .dark {
      --bg: #1a202c;
      --fg: #f7fafc;
    }

With these styling and theming techniques, you’ll have full control over your Next.js app’s appearance and can deliver a polished, branded experience. In Next Article, we’ll explore authentication and authorization flows.