Next.js with Tailwind CSS — Complete Setup

Sanjeev SharmaSanjeev Sharma
4 min read

Advertisement

Next.js with Tailwind CSS — Complete Setup

Tailwind CSS with Next.js provides a fast, utility-first approach to styling your applications with minimal configuration.

Installation

Create app with Tailwind included:

npx create-next-app@latest my-app --tailwind

Manual Setup

Add Tailwind to existing Next.js app:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Configuration

Configure template paths:

// tailwind.config.js
export default {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      colors: {
        primary: '#3B82F6',
        secondary: '#8B5CF6',
      },
      fontFamily: {
        sans: ['Inter', 'sans-serif'],
      },
    },
  },
  plugins: [],
}

Global Styles

/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  h1 {
    @apply text-3xl font-bold;
  }

  h2 {
    @apply text-2xl font-semibold;
  }
}

@layer components {
  .btn-primary {
    @apply px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700;
  }

  .card {
    @apply bg-white rounded-lg shadow-md p-6;
  }
}

Basic Styling

Use Tailwind utility classes:

// app/page.tsx
export default function Home() {
  return (
    <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
      <header className="bg-white shadow">
        <nav className="max-w-7xl mx-auto px-4 py-6">
          <h1 className="text-2xl font-bold text-gray-900">My App</h1>
        </nav>
      </header>

      <main className="max-w-7xl mx-auto px-4 py-12">
        <h2 className="text-4xl font-bold mb-8">Welcome</h2>
        <p className="text-lg text-gray-600 mb-6">
          Build beautiful UIs with Tailwind CSS
        </p>
      </main>
    </div>
  )
}

Responsive Design

Build responsive layouts:

// app/components/layout.tsx
export function Sidebar() {
  return (
    <div className="grid grid-cols-1 md:grid-cols-4 gap-6">
      <aside className="md:col-span-1">
        <nav className="space-y-2">
          <a href="/" className="block px-4 py-2 hover:bg-gray-100">
            Home
          </a>
          <a href="/about" className="block px-4 py-2 hover:bg-gray-100">
            About
          </a>
        </nav>
      </aside>

      <main className="md:col-span-3">
        <h1 className="text-2xl md:text-4xl font-bold">Content</h1>
        <p className="mt-4 text-gray-600">
          Responsive on mobile, tablet, and desktop
        </p>
      </main>
    </div>
  )
}

Component Classes

Create reusable component styles:

// app/components/button.tsx
interface ButtonProps {
  children: React.ReactNode
  variant?: 'primary' | 'secondary' | 'danger'
  size?: 'sm' | 'md' | 'lg'
  onClick?: () => void
}

export function Button({
  children,
  variant = 'primary',
  size = 'md',
  onClick
}: ButtonProps) {
  const baseStyles = 'font-semibold rounded-lg transition-colors'

  const variantStyles = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
    danger: 'bg-red-600 text-white hover:bg-red-700'
  }

  const sizeStyles = {
    sm: 'px-2 py-1 text-sm',
    md: 'px-4 py-2 text-base',
    lg: 'px-6 py-3 text-lg'
  }

  const className = `${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]}`

  return (
    <button onClick={onClick} className={className}>
      {children}
    </button>
  )
}

Dark Mode

Enable dark mode support:

// tailwind.config.js
export default {
  darkMode: 'class',
  // ... rest of config
}
// app/layout.tsx
'use client'

import { useEffect, useState } from 'react'

export default function RootLayout({ children }) {
  const [isDark, setIsDark] = useState(false)

  useEffect(() => {
    const isDarkMode = localStorage.getItem('darkMode') === 'true'
    setIsDark(isDarkMode)
    if (isDarkMode) {
      document.documentElement.classList.add('dark')
    }
  }, [])

  const toggleDarkMode = () => {
    setIsDark(!isDark)
    localStorage.setItem('darkMode', String(!isDark))
    document.documentElement.classList.toggle('dark')
  }

  return (
    <html className={isDark ? 'dark' : ''}>
      <body className="bg-white dark:bg-gray-900">
        <button onClick={toggleDarkMode}>
          {isDark ? '☀️' : '🌙'}
        </button>
        {children}
      </body>
    </html>
  )
}

Animations

Use Tailwind animations:

export function LoadingSpinner() {
  return (
    <div className="flex justify-center items-center">
      <div className="animate-spin">
        <div className="w-12 h-12 border-4 border-blue-600 border-t-transparent rounded-full"></div>
      </div>
    </div>
  )
}

Custom Configuration

Extend Tailwind:

// tailwind.config.js
export default {
  theme: {
    extend: {
      animation: {
        'fade-in': 'fadeIn 0.5s ease-in',
        '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' },
        },
      },
      spacing: {
        '128': '32rem',
        '144': '36rem',
      },
    },
  },
  plugins: [],
}

Forms with Tailwind

Style forms elegantly:

// app/components/form.tsx
export function LoginForm() {
  return (
    <form className="space-y-4 max-w-md mx-auto">
      <div>
        <label htmlFor="email" className="block text-sm font-medium mb-2">
          Email
        </label>
        <input
          id="email"
          type="email"
          className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
          placeholder="you@example.com"
        />
      </div>

      <div>
        <label htmlFor="password" className="block text-sm font-medium mb-2">
          Password
        </label>
        <input
          id="password"
          type="password"
          className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
        />
      </div>

      <button
        type="submit"
        className="w-full bg-blue-600 text-white py-2 rounded-lg hover:bg-blue-700 transition-colors"
      >
        Sign In
      </button>
    </form>
  )
}

Performance

Tree-shake unused styles:

// Only included classes in content paths are bundled
// Unused classes are automatically removed

FAQ

Q: How do I override Tailwind utility classes? A: Use !important or create custom components with @layer components.

Q: Can I use Tailwind with CSS modules? A: Yes, they work together. Tailwind is processed globally, CSS modules locally.

Q: What about custom fonts with Tailwind? A: Configure in tailwind.config.js under theme.fontFamily or use @font-face in CSS.


Tailwind CSS enables rapid, maintainable UI development with Next.js.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro