tailwind

Tailwind CSS Custom Configuration

Tailwind CSS configuration with custom theme extensions, colors, fonts, animations, and plugin setup for production projects.

Overview

A Tailwind CSS configuration that extends the default theme with custom design tokens: colors, typography, spacing, breakpoints, and animations. Sets up dark mode, custom plugins, and content scanning for a production project.

Configuration

// tailwind.config.ts

import type { Config } from "tailwindcss";
import defaultTheme from "tailwindcss/defaultTheme";
import plugin from "tailwindcss/plugin";

const config: Config = {
  // ── Content Scanning ──
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx,mdx}",  // Scan all source files for classes
    "./components/**/*.{js,ts,jsx,tsx}",
  ],

  // ── Dark Mode ──
  darkMode: "class",                   // Toggle via .dark class on <html>

  theme: {
    // ── Custom Breakpoints ──
    screens: {
      xs: "475px",                     // Extra small (phones)
      ...defaultTheme.screens,         // Keep default sm, md, lg, xl, 2xl
    },

    extend: {
      // ── Custom Colors ──
      colors: {
        brand: {
          50: "#eff6ff",
          100: "#dbeafe",
          200: "#bfdbfe",
          300: "#93c5fd",
          400: "#60a5fa",
          500: "#3b82f6",              // Primary brand color
          600: "#2563eb",
          700: "#1d4ed8",
          800: "#1e40af",
          900: "#1e3a8a",
          950: "#172554",
        },
        gray: {
          // Override default gray with a warmer palette
          50: "#fafaf9",
          100: "#f5f5f4",
          200: "#e7e5e4",
          300: "#d6d3d1",
          400: "#a8a29e",
          500: "#78716c",
          600: "#57534e",
          700: "#44403c",
          800: "#292524",
          900: "#1c1917",
          950: "#0c0a09",
        },
      },

      // ── Typography ──
      fontFamily: {
        sans: ["Inter", ...defaultTheme.fontFamily.sans],
        mono: ["JetBrains Mono", ...defaultTheme.fontFamily.mono],
        display: ["Cal Sans", "Inter", ...defaultTheme.fontFamily.sans],
      },

      fontSize: {
        "2xs": ["0.625rem", { lineHeight: "0.875rem" }],  // 10px
      },

      // ── Spacing ──
      spacing: {
        "4.5": "1.125rem",            // 18px (between 4 and 5)
        "18": "4.5rem",               // 72px
        "112": "28rem",               // 448px
        "128": "32rem",               // 512px
      },

      // ── Border Radius ──
      borderRadius: {
        "4xl": "2rem",                // Extra round corners
      },

      // ── Animations ──
      keyframes: {
        "fade-in": {
          from: { opacity: "0" },
          to: { opacity: "1" },
        },
        "slide-up": {
          from: { opacity: "0", transform: "translateY(10px)" },
          to: { opacity: "1", transform: "translateY(0)" },
        },
        "slide-down": {
          from: { opacity: "0", transform: "translateY(-10px)" },
          to: { opacity: "1", transform: "translateY(0)" },
        },
        shimmer: {
          "100%": { transform: "translateX(100%)" },
        },
      },
      animation: {
        "fade-in": "fade-in 0.3s ease-out",
        "slide-up": "slide-up 0.4s ease-out",
        "slide-down": "slide-down 0.4s ease-out",
        shimmer: "shimmer 2s infinite",
      },

      // ── Box Shadow ──
      boxShadow: {
        "inner-sm": "inset 0 1px 2px 0 rgb(0 0 0 / 0.05)",
      },

      // ── Typography Plugin ──
      typography: {
        DEFAULT: {
          css: {
            maxWidth: "none",          // Remove prose max-width
            color: "var(--tw-prose-body)",
            a: {
              color: "var(--tw-prose-links)",
              textDecoration: "underline",
              fontWeight: "500",
            },
          },
        },
      },
    },
  },

  // ── Plugins ──
  plugins: [
    require("@tailwindcss/typography"),    // Prose styling for rich text
    require("@tailwindcss/forms"),         // Form element reset
    require("@tailwindcss/container-queries"),  // @container queries

    // Custom utility plugin
    plugin(function ({ addUtilities }) {
      addUtilities({
        ".text-balance": {
          "text-wrap": "balance",      // Balance text across lines
        },
        ".scrollbar-hide": {
          "-ms-overflow-style": "none",
          "scrollbar-width": "none",
          "&::-webkit-scrollbar": {
            display: "none",
          },
        },
      });
    }),
  ],
};

export default config;

Key Options Explained

  • content — Tells Tailwind which files to scan for class names. Only classes found in these files are included in the CSS output. Missing a path means missing utilities.
  • darkMode: "class" — Enables dark mode via a .dark class on a parent element (usually <html>). Alternative: "media" uses the OS preference via prefers-color-scheme.
  • extend — Adds to the default theme rather than replacing it. Properties outside extend (like screens) completely replace the defaults.
  • ...defaultTheme.fontFamily.sans — Spreads the default system font stack after your custom font, providing fallbacks if the custom font fails to load.
  • Color scale (50-950) — Follows Tailwind’s convention for color palettes. 500 is the primary shade, lower numbers are lighter, higher are darker.
  • @tailwindcss/typography — Provides the prose class for styling rendered Markdown or CMS content with sensible typographic defaults.
  • @tailwindcss/forms — Resets form elements (inputs, selects, textareas) to a consistent baseline that is easy to style with utilities.

Common Modifications

  • CSS variables for theming: Define colors as CSS custom properties (hsl(var(--brand-500))) for runtime theme switching.
  • Tailwind v4: In Tailwind v4, configuration moves to @theme in CSS. The tailwind.config.ts file is optional, replaced by @import "tailwindcss" and CSS-based configuration.
  • Container centered: Add container: { center: true, padding: "1rem" } to the theme for auto-centered container utilities.
  • Remove unused variants: Use safelist: ["dark"] to always include specific classes that are dynamically generated.
  • Design tokens from Figma: Generate the color palette and spacing from your design tool using tokens-studio or similar bridges.