Dev Logs
/Tailwind CSS/ Colors and Theme Customization
Chapters
  • 01Introduction to Tailwind CSS
  • 02Installation and Setup
  • 03Tailwind Configuration
  • 04Typography and Spacing
  • 05Colors and Theme Customization
    • Tailwind's Color System
    • Using Colors in Tailwind
    • Text Colors
    • Background Colors
    • Border Colors
    • Other Color Utilities
    • Color Opacity
    • Modern Color Syntax (Tailwind v3.0+)
    • Arbitrary Colors
    • Default Color Palette
    • Customizing the Color Palette
    • Extending the Default Palette
    • Replacing the Default Palette
    • Theme Customization Beyond Colors
    • Spacing
    • Border Radius
    • Box Shadow
    • Creating a Cohesive Theme
    • Dark Mode
    • Enabling Dark Mode
    • Using Dark Mode Variants
    • Dark Mode with CSS Variables
    • Visual Layout Diagram
    • Common Pitfalls & Anti-Patterns
    • Inconsistent Color Usage
    • Consistent Color System
    • Too Many Colors
    • Limited, Cohesive Palette
    • Ignoring Accessibility
    • Accessible Color Combinations
    • When and Why to Use Theme Customization
    • When to Customize
    • Why Customize
    • Mini Challenges
    • Challenge 1: Brand Color System
    • Challenge 2: Dark Mode Toggle
    • Challenge 3: Accessible Button System
    • Interview Tips
    • Challenge Answers
    • Answer 1: Brand Color System
    • Answer 2: Dark Mode Toggle
    • Answer 3: Accessible Button System
  • 06Flexbox Utilities
  • 07Responsive Design
  • 08Grid Utilities
  • 09Pseudo-Classes and State-Based Styling
  • 10Dark Mode
  • 11Customizing and Extending Tailwind Configuration
  • 12Advanced Layout Techniques
  • 13Final Project: Dashify - Complete Dashboard Application
All chapters

Colors and Theme Customization

Tailwind's Color System

Tailwind CSS provides a beautiful, well-thought-out color palette that serves as an excellent foundation for most projects. The default color palette includes a range of colors with varying shades (from 50 to 900), giving you fine-grained control over your design.

Using Colors in Tailwind

Text Colors

html
<!-- Basic text colors -->
<p class="text-black">Black text</p>
<p class="text-white">White text</p>

<!-- Gray scale -->
<p class="text-gray-50">Very light gray</p>
<p class="text-gray-100">Light gray</p>
<p class="text-gray-500">Medium gray</p>
<p class="text-gray-900">Very dark gray</p>

<!-- Colors with shades -->
<p class="text-red-500">Medium red</p>
<p class="text-blue-700">Dark blue</p>
<p class="text-green-300">Light green</p>

Background Colors

html
<!-- Basic background colors -->
<div class="bg-white">White background</div>
<div class="bg-black">Black background</div>

<!-- Gray scale -->
<div class="bg-gray-50">Very light gray background</div>
<div class="bg-gray-900">Very dark gray background</div>

<!-- Colors with shades -->
<div class="bg-blue-500">Medium blue background</div>
<div class="bg-red-100">Light red background</div>
<div class="bg-green-800">Dark green background</div>

Border Colors

html
<!-- Basic border colors (requires border width) -->
<div class="border border-black">Black border</div>
<div class="border-2 border-white">White border</div>

<!-- Colors with shades -->
<div class="border-2 border-purple-500">Medium purple border</div>
<div class="border-4 border-yellow-300">Light yellow border</div>

Other Color Utilities

html
<!-- Placeholder text color -->
<input class="placeholder-gray-400" placeholder="Search..." />

<!-- Gradient backgrounds -->
<div class="bg-gradient-to-r from-blue-500 to-purple-500">
  Blue to purple gradient
</div>
<div class="bg-gradient-to-br from-pink-500 via-red-500 to-yellow-500">
  Three-color gradient
</div>

<!-- Divide colors (for children) -->
<div class="divide-y divide-gray-200">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</div>

<!-- Ring colors (focus rings) -->
<button class="ring-2 ring-blue-500 focus:ring-4">Button with ring</button>

Color Opacity

Tailwind allows you to control the opacity of colors:

html
<!-- Text opacity -->
<p class="text-blue-500 text-opacity-100">100% opacity</p>
<p class="text-blue-500 text-opacity-75">75% opacity</p>
<p class="text-blue-500 text-opacity-50">50% opacity</p>
<p class="text-blue-500 text-opacity-25">25% opacity</p>

<!-- Background opacity -->
<div class="bg-black bg-opacity-100">100% opacity</div>
<div class="bg-black bg-opacity-75">75% opacity</div>
<div class="bg-black bg-opacity-50">50% opacity</div>
<div class="bg-black bg-opacity-25">25% opacity</div>

<!-- Border opacity -->
<div class="border-4 border-blue-500 border-opacity-100">100% opacity</div>
<div class="border-4 border-blue-500 border-opacity-50">50% opacity</div>

Modern Color Syntax (Tailwind v3.0+)

Tailwind v3.0+ introduced a more concise syntax for color opacity:

html
<!-- Text with opacity -->
<p class="text-blue-500/100">100% opacity</p>
<p class="text-blue-500/75">75% opacity</p>
<p class="text-blue-500/50">50% opacity</p>
<p class="text-blue-500/25">25% opacity</p>

<!-- Background with opacity -->
<div class="bg-black/100">100% opacity</div>
<div class="bg-black/75">75% opacity</div>
<div class="bg-black/50">50% opacity</div>
<div class="bg-black/25">25% opacity</div>

<!-- Border with opacity -->
<div class="border-4 border-blue-500/100">100% opacity</div>
<div class="border-4 border-blue-500/50">50% opacity</div>

Arbitrary Colors

Tailwind v3.0+ also allows for arbitrary color values:

html
<!-- Arbitrary hex colors -->
<div class="bg-[#ff5733]">Custom hex background</div>
<p class="text-[#bada55]">Custom hex text</p>

<!-- Arbitrary RGB/HSL colors -->
<div class="bg-[rgb(255,0,127)]">RGB background</div>
<div class="bg-[hsl(200,100%,50%)]">HSL background</div>

<!-- With opacity -->
<div class="bg-[#ff5733]/50">Custom hex with 50% opacity</div>
<div class="bg-[rgb(255,0,127)]/75">RGB with 75% opacity</div>

Default Color Palette

Tailwind includes these color families by default:

  • slate, gray, zinc, neutral, stone (gray scales)
  • red, orange, amber, yellow, lime, green
  • emerald, teal, cyan, sky, blue, indigo
  • violet, purple, fuchsia, pink, rose

Each color has shades from 50 (lightest) to 900 (darkest).

Customizing the Color Palette

You can customize the color palette in your tailwind.config.js file:

Extending the Default Palette

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        // Add a single color
        "brand-blue": "#1e40af",

        // Add a color with shades
        primary: {
          50: "#eff6ff",
          100: "#dbeafe",
          200: "#bfdbfe",
          300: "#93c5fd",
          400: "#60a5fa",
          500: "#3b82f6", // Default shade
          600: "#2563eb",
          700: "#1d4ed8",
          800: "#1e40af",
          900: "#1e3a8a",
        },

        // Add semantic colors
        success: "#10b981",
        warning: "#f59e0b",
        error: "#ef4444",
      },
    },
  },
};

Replacing the Default Palette

javascript
// tailwind.config.js
module.exports = {
  theme: {
    // This replaces the entire default color palette
    colors: {
      transparent: "transparent",
      current: "currentColor",
      black: "#000000",
      white: "#ffffff",
      gray: {
        50: "#f9fafb",
        100: "#f3f4f6",
        // ... other shades
        900: "#111827",
      },
      // ... other colors
    },
  },
};

Theme Customization Beyond Colors

Tailwind's theme system extends beyond colors. You can customize almost every aspect of your design system:

Spacing

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      spacing: {
        72: "18rem",
        84: "21rem",
        96: "24rem",
        128: "32rem",
      },
    },
  },
};

Border Radius

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      borderRadius: {
        "4xl": "2rem",
        "5xl": "2.5rem",
        pill: "9999px",
      },
    },
  },
};

Box Shadow

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      boxShadow: {
        soft: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
        hard: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
        "inner-lg": "inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)",
      },
    },
  },
};

Creating a Cohesive Theme

A well-designed theme should have a cohesive feel. Here's an example of a complete theme customization:

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          50: "#eff6ff",
          100: "#dbeafe",
          // ... other shades
          500: "#3b82f6",
          // ... other shades
          900: "#1e3a8a",
        },
        secondary: {
          50: "#f8fafc",
          // ... other shades
          500: "#64748b",
          // ... other shades
          900: "#0f172a",
        },
        accent: "#f59e0b",
        success: "#10b981",
        warning: "#f59e0b",
        error: "#ef4444",
      },
      fontFamily: {
        sans: ["Inter", "system-ui", "sans-serif"],
        heading: ["Poppins", "sans-serif"],
      },
      borderRadius: {
        sm: "0.125rem",
        DEFAULT: "0.25rem",
        md: "0.375rem",
        lg: "0.5rem",
        xl: "0.75rem",
        "2xl": "1rem",
      },
      boxShadow: {
        sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
        DEFAULT:
          "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)",
        md: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
        lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
        xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
      },
    },
  },
};

Dark Mode

Tailwind makes it easy to support dark mode in your design:

Enabling Dark Mode

javascript
// tailwind.config.js
module.exports = {
  darkMode: "class", // or 'media' for OS preference
  // ... rest of your config
};

Using Dark Mode Variants

html
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">
  This div has a white background and dark text in light mode, but a dark gray
  background and white text in dark mode.
</div>

<button
  class="bg-blue-500 hover:bg-blue-600 dark:bg-blue-700 dark:hover:bg-blue-800"
>
  Button with different colors in dark mode
</button>

Dark Mode with CSS Variables

For more flexibility, you can use CSS variables:

css
/* globals.css */
:root {
  --background: 255, 255, 255;
  --text: 17, 24, 39;
}

.dark {
  --background: 31, 41, 55;
  --text: 255, 255, 255;
}
javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        background: "rgb(var(--background))",
        text: "rgb(var(--text))",
      },
    },
  },
  darkMode: "class",
};
html
<div class="bg-background text-text">
  This div automatically adapts to dark mode
</div>

Visual Layout Diagram

Color Palette Structure:

┌─────────────────────────────────────────────────────┐
│                   Color Palette                     │
├─────────────┬─────────────┬─────────────┬──────────┤
│    Gray     │    Blue     │    Red      │   ...    │
├─────────────┼─────────────┼─────────────┼──────────┤
│  50 (light) │  50 (light) │  50 (light) │   ...    │
│     100     │     100     │     100     │   ...    │
│     200     │     200     │     200     │   ...    │
│     300     │     300     │     300     │   ...    │
│     400     │     400     │     400     │   ...    │
│     500     │     500     │     500     │   ...    │
│     600     │     600     │     600     │   ...    │
│     700     │     700     │     700     │   ...    │
│     800     │     800     │     800     │   ...    │
│ 900 (dark)  │ 900 (dark)  │ 900 (dark)  │   ...    │
└─────────────┴─────────────┴─────────────┴──────────┘

Color Application:

┌─────────────────────────────────────────────────────┐
│                                                     │
│  ┌─────────────────────────────────────────────┐   │
│  │ bg-blue-500                                 │   │
│  │                                             │   │
│  │  ┌─────────────────────────────────────┐   │   │
│  │  │ bg-white text-gray-800              │   │   │
│  │  │                                     │   │   │
│  │  │                                     │   │   │
│  │  │                                     │   │   │
│  │  └─────────────────────────────────────┘   │   │
│  │                                             │   │
│  └─────────────────────────────────────────────┘   │
│                                                     │
└─────────────────────────────────────────────────────┘

Common Pitfalls & Anti-Patterns

❌ Inconsistent Color Usage

html
<!-- Bad: Inconsistent, arbitrary colors -->
<button class="bg-blue-500">Primary Action</button>
<button class="bg-[#3b82f6]">Also Primary Action</button>
<button class="bg-[rgb(59,130,246)]">Still Primary Action</button>

✅ Consistent Color System

html
<!-- Good: Consistent color system -->
<button class="bg-primary-500">Primary Action</button>
<button class="bg-secondary-500">Secondary Action</button>
<button class="bg-accent">Accent Action</button>

❌ Too Many Colors

html
<!-- Bad: Too many different colors -->
<div>
  <h1 class="text-purple-700">Heading</h1>
  <p class="text-blue-800">Paragraph</p>
  <button class="bg-green-500">Button</button>
  <button class="bg-red-500">Another Button</button>
  <button class="bg-yellow-500">Yet Another Button</button>
</div>

✅ Limited, Cohesive Palette

html
<!-- Good: Limited, cohesive palette -->
<div>
  <h1 class="text-gray-900">Heading</h1>
  <p class="text-gray-700">Paragraph</p>
  <button class="bg-primary-500">Primary Button</button>
  <button class="bg-secondary-500">Secondary Button</button>
  <button class="bg-gray-200 text-gray-800">Tertiary Button</button>
</div>

❌ Ignoring Accessibility

html
<!-- Bad: Poor contrast ratio -->
<div class="bg-yellow-200">
  <p class="text-yellow-500">This text is hard to read</p>
</div>

✅ Accessible Color Combinations

html
<!-- Good: Sufficient contrast ratio -->
<div class="bg-yellow-200">
  <p class="text-gray-800">This text is easy to read</p>
</div>

When and Why to Use Theme Customization

When to Customize

  • Brand Identity: When you need to match specific brand colors
  • Design Systems: When implementing a comprehensive design system
  • Accessibility: When you need to ensure proper contrast ratios
  • Dark Mode: When supporting light and dark themes
  • Consistency: When you want to enforce design consistency

Why Customize

  • Brand Alignment: Ensures your UI matches your brand identity
  • Design Efficiency: Makes it easier to maintain consistent design
  • Developer Experience: Simplifies the process of applying brand colors
  • Reduced CSS: Prevents the need for custom CSS classes
  • Scalability: Makes it easier to update the design system globally

Mini Challenges

Challenge 1: Brand Color System

Create a color system for a fictional brand with:

  • Primary color with shades
  • Secondary color with shades
  • Accent color
  • Semantic colors (success, warning, error)

Challenge 2: Dark Mode Toggle

Implement a dark mode toggle that:

  • Switches between light and dark themes
  • Persists the user's preference
  • Uses appropriate colors for both modes

Challenge 3: Accessible Button System

Create a button system with:

  • Primary, secondary, and tertiary variants
  • Different states (default, hover, focus, disabled)
  • Accessible color combinations
  • Dark mode support

Interview Tips

Q: "How do you approach color management in a large-scale Tailwind project?"

A: "I approach color management systematically by:

  1. Defining a core color palette in the Tailwind config with semantic naming
  2. Using CSS variables for theme switching (light/dark mode)
  3. Creating a color documentation page showing all colors and their usage
  4. Using tools like WCAG contrast checkers to ensure accessibility
  5. Limiting color usage to the defined palette to maintain consistency
  6. Creating component abstractions that use the correct colors by default"

Q: "How would you implement a themeable component library with Tailwind?"

A: "For a themeable component library, I would:

  1. Use CSS variables for all theme values (colors, spacing, etc.)
  2. Define multiple theme presets (light, dark, brand variations)
  3. Create a theme provider component to switch themes
  4. Use Tailwind's config to map CSS variables to utility classes
  5. Document the theming API clearly for consumers
  6. Provide theme customization options through a simple API
  7. Ensure all components use the theme values consistently"

Challenge Answers

Answer 1: Brand Color System

javascript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          50: "#f0f9ff",
          100: "#e0f2fe",
          200: "#bae6fd",
          300: "#7dd3fc",
          400: "#38bdf8",
          500: "#0ea5e9",
          600: "#0284c7",
          700: "#0369a1",
          800: "#075985",
          900: "#0c4a6e",
        },
        secondary: {
          50: "#fdf4ff",
          100: "#fae8ff",
          200: "#f5d0fe",
          300: "#f0abfc",
          400: "#e879f9",
          500: "#d946ef",
          600: "#c026d3",
          700: "#a21caf",
          800: "#86198f",
          900: "#701a75",
        },
        accent: "#f59e0b",
        success: "#10b981",
        warning: "#f59e0b",
        error: "#ef4444",
      },
    },
  },
};

Answer 2: Dark Mode Toggle

html
<!-- HTML -->
<button id="theme-toggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700">
  <!-- Sun icon for dark mode (shown when in dark mode) -->
  <svg
    class="w-6 h-6 text-gray-800 dark:text-yellow-300 hidden dark:block"
    fill="currentColor"
    viewBox="0 0 20 20"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      fill-rule="evenodd"
      d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
      clip-rule="evenodd"
    ></path>
  </svg>
  <!-- Moon icon for light mode (shown when in light mode) -->
  <svg
    class="w-6 h-6 text-gray-800 dark:text-gray-200 block dark:hidden"
    fill="currentColor"
    viewBox="0 0 20 20"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"
    ></path>
  </svg>
</button>

<div
  class="mt-6 p-6 bg-white dark:bg-gray-800 text-gray-900 dark:text-white rounded-lg shadow-md"
>
  <h2 class="text-2xl font-bold mb-4">Dark Mode Example</h2>
  <p class="mb-4">This content automatically adapts to the current theme.</p>
  <button
    class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-md"
  >
    Primary Button
  </button>
</div>
javascript
// JavaScript for theme toggle
document.addEventListener("DOMContentLoaded", () => {
  const themeToggle = document.getElementById("theme-toggle");

  // Check for saved theme preference or use OS preference
  if (
    localStorage.theme === "dark" ||
    (!("theme" in localStorage) &&
      window.matchMedia("(prefers-color-scheme: dark)").matches)
  ) {
    document.documentElement.classList.add("dark");
  } else {
    document.documentElement.classList.remove("dark");
  }

  // Toggle theme on click
  themeToggle.addEventListener("click", () => {
    if (document.documentElement.classList.contains("dark")) {
      document.documentElement.classList.remove("dark");
      localStorage.theme = "light";
    } else {
      document.documentElement.classList.add("dark");
      localStorage.theme = "dark";
    }
  });
});

Answer 3: Accessible Button System

html
<!-- Primary Button -->
<button
  class="
  px-4 py-2 rounded-md font-medium
  bg-primary-600 hover:bg-primary-700 focus:bg-primary-700
  text-white
  focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2
  disabled:opacity-50 disabled:cursor-not-allowed
  dark:bg-primary-500 dark:hover:bg-primary-600 dark:focus:bg-primary-600
  transition-colors
"
>
  Primary Button
</button>

<!-- Secondary Button -->
<button
  class="
  px-4 py-2 rounded-md font-medium
  bg-secondary-100 hover:bg-secondary-200 focus:bg-secondary-200
  text-secondary-800
  focus:outline-none focus:ring-2 focus:ring-secondary-500 focus:ring-offset-2
  disabled:opacity-50 disabled:cursor-not-allowed
  dark:bg-secondary-700 dark:hover:bg-secondary-600 dark:focus:bg-secondary-600
  dark:text-secondary-100
  transition-colors
"
>
  Secondary Button
</button>

<!-- Tertiary Button (Ghost) -->
<button
  class="
  px-4 py-2 rounded-md font-medium
  bg-transparent hover:bg-gray-100 focus:bg-gray-100
  text-gray-700
  focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2
  disabled:opacity-50 disabled:cursor-not-allowed
  dark:text-gray-300 dark:hover:bg-gray-800 dark:focus:bg-gray-800
  transition-colors
"
>
  Tertiary Button
</button>

<!-- Danger Button -->
<button
  class="
  px-4 py-2 rounded-md font-medium
  bg-red-600 hover:bg-red-700 focus:bg-red-700
  text-white
  focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2
  disabled:opacity-50 disabled:cursor-not-allowed
  dark:bg-red-500 dark:hover:bg-red-600 dark:focus:bg-red-600
  transition-colors
"
>
  Danger Button
</button>

<!-- Success Button -->
<button
  class="
  px-4 py-2 rounded-md font-medium
  bg-green-600 hover:bg-green-700 focus:bg-green-700
  text-white
  focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2
  disabled:opacity-50 disabled:cursor-not-allowed
  dark:bg-green-500 dark:hover:bg-green-600 dark:focus:bg-green-600
  transition-colors
"
>
  Success Button
</button>
PreviousTypography and SpacingNextFlexbox Utilities

Open source, free forever. Built by iammhador.

Contribute on GitHub