Intermediate18 min1 prerequisite

Build responsive layouts and implement dark mode with Tailwind CSS for AI-generated applications.

Responsive Design & Dark Mode

AI-generated applications need to work on all devices and respect user preferences. This lesson covers responsive patterns and dark mode implementation.

Mobile-First Design

The Mobile-First Approach

Start with mobile styles, add breakpoints for larger screens:

Terminal
<div className="
  p-4              // Mobile: 16px padding
  md:p-6           // Medium+: 24px padding
  lg:p-8           // Large+: 32px padding
">

Breakpoint Reference

PrefixMin WidthTarget Devices
(none)0pxMobile phones
sm:640pxLarge phones, small tablets
md:768pxTablets
lg:1024pxLaptops, desktops
xl:1280pxLarge desktops
2xl:1536pxExtra large screens

Responsive Layout Patterns

Stack to Row:

Terminal
<div className="flex flex-col md:flex-row gap-4">
  <div>Left content</div>
  <div>Right content</div>
</div>

Responsive Grid:

Terminal
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
  {items.map(item => (
    <Card key={item.id} {...item} />
  ))}
</div>

Show/Hide Elements:

Terminal
{/* Hidden on mobile, visible on md+ */}
<nav className="hidden md:block">
  Desktop navigation
</nav>

{/* Visible on mobile, hidden on md+ */}
<button className="md:hidden">
  Mobile menu
</button>

Responsive Typography:

Terminal
<h1 className="text-2xl sm:text-3xl md:text-4xl lg:text-5xl font-bold">
  Responsive Heading
</h1>

Responsive Spacing:

Terminal
<section className="py-12 md:py-16 lg:py-24">
  <div className="container px-4 md:px-6 lg:px-8 mx-auto">
    Content
  </div>
</section>

Common Responsive Components

Responsive Navigation

Terminal
export function Navbar() {
  return (
    <nav className="bg-white shadow">
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="flex justify-between h-16">
          {/* Logo */}
          <div className="flex items-center">
            <Logo />
          </div>

          {/* Desktop navigation */}
          <div className="hidden md:flex items-center space-x-8">
            <NavLink href="/features">Features</NavLink>
            <NavLink href="/pricing">Pricing</NavLink>
            <NavLink href="/about">About</NavLink>
            <Button>Get Started</Button>
          </div>

          {/* Mobile menu button */}
          <div className="md:hidden flex items-center">
            <MobileMenuButton />
          </div>
        </div>
      </div>
    </nav>
  )
}

Responsive Card Grid

Terminal
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {products.map(product => (
    <div
      key={product.id}
      className="bg-white rounded-lg shadow-md overflow-hidden"
    >
      <img
        src={product.image}
        alt={product.name}
        className="w-full h-48 object-cover"
      />
      <div className="p-4 md:p-6">
        <h3 className="text-lg md:text-xl font-semibold">
          {product.name}
        </h3>
        <p className="mt-2 text-gray-600 text-sm md:text-base">
          {product.description}
        </p>
        <div className="mt-4 flex justify-between items-center">
          <span className="text-xl font-bold">${product.price}</span>
          <button className="px-4 py-2 bg-blue-500 text-white rounded">
            Add to Cart
          </button>
        </div>
      </div>
    </div>
  ))}
</div>

Responsive Sidebar Layout

Terminal
<div className="flex flex-col md:flex-row min-h-screen">
  {/* Sidebar */}
  <aside className="
    w-full md:w-64
    bg-gray-800
    md:min-h-screen
    p-4
  ">
    <nav className="flex md:flex-col space-x-4 md:space-x-0 md:space-y-2">
      <SidebarLink icon={Home} label="Dashboard" />
      <SidebarLink icon={Users} label="Users" />
      <SidebarLink icon={Settings} label="Settings" />
    </nav>
  </aside>

  {/* Main content */}
  <main className="flex-1 p-4 md:p-8">
    {children}
  </main>
</div>

Dark Mode

Setup

tailwind.config.js:

Terminal
export default {
  darkMode: 'class', // or 'media' for system preference
  // ...
}
  • 'class': Toggle via .dark class on <html>
  • 'media': Follow system preference automatically

Using Dark Mode Classes

Terminal
<div className="
  bg-white dark:bg-gray-900
  text-gray-900 dark:text-gray-100
">
  <h1 className="text-2xl font-bold">
    Title
  </h1>
  <p className="text-gray-600 dark:text-gray-400">
    Description text that adapts to theme.
  </p>
</div>

Dark Mode Color Patterns

Terminal
// Backgrounds
<div className="bg-white dark:bg-gray-900">        // Main background
<div className="bg-gray-50 dark:bg-gray-800">      // Secondary background
<div className="bg-gray-100 dark:bg-gray-700">     // Tertiary background

// Text
<p className="text-gray-900 dark:text-white">      // Primary text
<p className="text-gray-600 dark:text-gray-300">   // Secondary text
<p className="text-gray-500 dark:text-gray-400">   // Muted text

// Borders
<div className="border-gray-200 dark:border-gray-700">

// Cards
<div className="bg-white dark:bg-gray-800 shadow dark:shadow-gray-900/50">

Theme Toggle Component

Terminal
'use client'

import { useTheme } from 'next-themes'
import { Moon, Sun } from 'lucide-react'

export function ThemeToggle() {
  const { theme, setTheme } = useTheme()

  return (
    <button
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
      className="
        p-2 rounded-lg
        bg-gray-100 dark:bg-gray-800
        hover:bg-gray-200 dark:hover:bg-gray-700
        transition-colors
      "
    >
      <Sun className="h-5 w-5 hidden dark:block text-gray-100" />
      <Moon className="h-5 w-5 dark:hidden text-gray-900" />
    </button>
  )
}

Next.js Theme Setup

Terminal
npm install next-themes
Terminal
// app/providers.tsx
'use client'

import { ThemeProvider } from 'next-themes'

export function Providers({ children }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
      {children}
    </ThemeProvider>
  )
}
Terminal
// app/layout.tsx
import { Providers } from './providers'

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

Complete Dark Mode Component

Terminal
export function DashboardCard({ title, value, change }) {
  return (
    <div className="
      bg-white dark:bg-gray-800
      rounded-lg shadow-sm dark:shadow-gray-900/30
      p-6
      border border-gray-100 dark:border-gray-700
    ">
      <h3 className="text-sm font-medium text-gray-500 dark:text-gray-400">
        {title}
      </h3>
      <div className="mt-2 flex items-baseline">
        <span className="text-3xl font-bold text-gray-900 dark:text-white">
          {value}
        </span>
        <span className={`
          ml-2 text-sm font-medium
          ${change >= 0
            ? 'text-green-600 dark:text-green-400'
            : 'text-red-600 dark:text-red-400'
          }
        `}>
          {change >= 0 ? '+' : ''}{change}%
        </span>
      </div>
    </div>
  )
}

Container Queries (New)

For component-level responsiveness:

Terminal
// Parent with container
<div className="@container">
  <div className="@md:flex @md:gap-4">
    <div className="@md:w-1/2">Left</div>
    <div className="@md:w-1/2">Right</div>
  </div>
</div>

Requires Tailwind v3.2+ and plugin or v4:

Terminal
// tailwind.config.js
plugins: [require('@tailwindcss/container-queries')]

AI-Generated Responsive Patterns

What AI Often Generates

Terminal
// AI typically generates responsive grids:
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">

// AI handles mobile navigation:
<nav className="hidden md:flex space-x-4">
<button className="md:hidden">Menu</button>

// AI includes dark mode:
<div className="bg-white dark:bg-slate-900">

Prompting for Responsive Design

Terminal
"Create a responsive pricing table that:
- Shows one card per row on mobile
- Two cards per row on tablets
- Three cards per row on desktop
- Has hover effects and dark mode support"
Terminal
"Build a responsive header with:
- Logo on the left
- Navigation links in center (desktop only)
- Action buttons on the right
- Mobile hamburger menu"

Testing Responsive Design

Browser DevTools

Terminal
Chrome DevTools:
1. F12 or Cmd+Option+I
2. Toggle device toolbar (Cmd+Shift+M)
3. Select device or resize freely

Tailwind CSS IntelliSense

VS Code extension that shows:

  • Class autocomplete
  • Color previews
  • Responsive breakpoint information

Summary

  • Mobile-first: Start with base styles, add md:, lg: for larger screens
  • Breakpoints: sm (640px), md (768px), lg (1024px), xl (1280px)
  • Dark mode: Use dark: prefix with darkMode: 'class' config
  • Common patterns: Stack-to-row, responsive grids, show/hide elements
  • Theme toggle: Use next-themes with ThemeProvider

Next Steps

Learn to customize Tailwind's configuration and create your own design system in the final lesson.

Mark this lesson as complete to track your progress