R
Rishtaara
Knowledge Hub
Technology & IT

Tailwind CSS Fundamentals: Utility-First Styling

By Rishtaara Editorial Team30 min read
#Tailwind#CSS#Responsive#Dark Mode#React

Setup, layout utilities, typography, responsive breakpoints, dark mode, @apply, and Tailwind + React patterns with real examples.

What is Tailwind CSS?

Tailwind CSS is a utility-first CSS framework. Instead of writing custom CSS classes, you compose designs by applying small, single-purpose utility classes directly in HTML or JSX.

Rishtaara itself uses Tailwind v4. Tailwind powers GitHub, Shopify, NASA, and thousands of modern products because it speeds up development and keeps design consistent.

Utility-first vs traditional CSS

  • Traditional: write .card { padding: 1rem; border-radius: 8px; } in a CSS file.
  • Tailwind: <div className='p-4 rounded-lg border'> — styles live in markup.
  • Benefits: no naming fatigue, no unused CSS, consistent design tokens, fast iteration.
  • Tradeoff: longer class strings — solved with @apply or component extraction.

Tailwind with Vite + React

Install Tailwind v4
npm create vite@latest my-app -- --template react
cd my-app
npm install tailwindcss @tailwindcss/vite
vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [react(), tailwindcss()],
});
src/index.css
@import "tailwindcss";

tailwind.config (optional customization)

Extend theme colors and fonts
// tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        brand: { cyan: "#06b6d4", violet: "#8b5cf6" },
      },
      fontFamily: {
        display: ["Outfit", "sans-serif"],
      },
    },
  },
};

Core layout utilities

Container, flex, grid, gap
<!-- Centered container -->
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">

<!-- Flex navbar -->
<nav class="flex items-center justify-between gap-4 py-4">

<!-- Grid cards -->
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">

<!-- Spacing -->
<div class="p-6 m-4 mt-8 space-y-4">
  <div class="w-full h-48 max-w-md min-h-[200px]">

Spacing scale

  • p-4 = padding 1rem (16px). m-2 = margin 0.5rem.
  • px-4 py-2 — horizontal and vertical padding.
  • space-y-4 — gap between stacked children.
  • gap-6 — gap in flex/grid containers.
  • Scale: 1=4px, 2=8px, 4=16px, 6=24px, 8=32px, 12=48px.

Text and color utilities

Typography
<h1 class="font-display text-4xl font-bold tracking-tight text-slate-900">
  Learn Web Development
</h1>
<p class="mt-4 text-lg leading-relaxed text-slate-600">
  Build modern UIs with utility classes.
</p>
<span class="text-sm font-medium uppercase tracking-wider text-cyan-600">
  Featured
</span>
Colors and backgrounds
<div class="bg-slate-50 text-slate-900">
<div class="bg-gradient-to-r from-cyan-500 to-violet-500 text-white">
<button class="bg-cyan-500 hover:bg-cyan-600 text-white">
<div class="border border-slate-200 bg-white/80 backdrop-blur">

Opacity and gradients

  • text-white/80 — 80% opacity white text.
  • bg-black/50 — semi-transparent overlay.
  • from-*, via-*, to-* for linear gradients.

Visual polish utilities

Cards and buttons
<!-- Card -->
<article class="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm
  hover:shadow-md transition-shadow">

<!-- Pill badge -->
<span class="rounded-full bg-cyan-100 px-3 py-1 text-xs font-semibold text-cyan-700">

<!-- Button -->
<button class="rounded-xl bg-cyan-500 px-4 py-2 font-semibold text-white
  shadow-lg shadow-cyan-500/25 hover:bg-cyan-600 active:scale-95 transition">

Mobile-first breakpoints

Tailwind is mobile-first. Unprefixed utilities apply to all sizes. Prefix with sm:, md:, lg:, xl:, 2xl: for larger screens.

Responsive patterns
<!-- Stack on mobile, row on tablet+ -->
<div class="flex flex-col md:flex-row gap-4">

<!-- Hide on mobile, show on desktop -->
<aside class="hidden lg:block w-64">

<!-- Responsive text -->
<h1 class="text-2xl sm:text-3xl lg:text-5xl">

<!-- Responsive grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">

Default breakpoints

  • sm: 640px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px.
  • Design mobile layout first, then add breakpoint overrides.

Interactive states

State variants
<a class="text-slate-600 hover:text-cyan-600 hover:underline transition-colors">
<input class="border rounded-lg px-3 py-2 focus:border-cyan-500 focus:ring-2
  focus:ring-cyan-500/30 focus:outline-none">
<button class="disabled:opacity-50 disabled:cursor-not-allowed">

<!-- Group hover — parent triggers child style -->
<div class="group cursor-pointer">
  <h3 class="group-hover:text-cyan-600">Course Title</h3>
  <p class="text-slate-500 group-hover:text-slate-700">Description</p>
</div>

Class-based dark mode

dark: variant
<html class="dark">
<body class="bg-white text-slate-900 dark:bg-slate-950 dark:text-slate-100">
<div class="bg-slate-100 dark:bg-slate-800 border-slate-200 dark:border-slate-700">
<button class="bg-white dark:bg-slate-800 hover:bg-slate-50 dark:hover:bg-slate-700">
Toggle with JavaScript
function toggleDark() {
  document.documentElement.classList.toggle("dark");
  localStorage.setItem(
    "theme",
    document.documentElement.classList.contains("dark") ? "dark" : "light"
  );
}

When to extract components

Repeat the same utility combination 3+ times? Extract a React component or use @apply in CSS for a semantic class name.

React component vs @apply
// Preferred: React component
function Button({ children, variant = "primary" }) {
  const base = "rounded-xl px-4 py-2 font-semibold transition";
  const styles = {
    primary: "bg-cyan-500 text-white hover:bg-cyan-600",
    ghost: "border border-slate-200 hover:bg-slate-50",
  };
  return <button className={`${base} ${styles[variant]}`}>{children}</button>;
}
@apply in CSS (use sparingly)
@layer components {
  .btn-primary {
    @apply rounded-xl bg-cyan-500 px-4 py-2 font-semibold text-white
      hover:bg-cyan-600 transition;
  }
}

clsx / tailwind-merge for dynamic classes

Conditional class names
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";

function cn(...inputs) {
  return twMerge(clsx(inputs));
}

function Badge({ active, children }) {
  return (
    <span className={cn(
      "rounded-full px-3 py-1 text-xs font-medium",
      active
        ? "bg-cyan-100 text-cyan-700"
        : "bg-slate-100 text-slate-600"
    )}>
      {children}
    </span>
  );
}

Rishtaara-style patterns

  • Glass cards: bg-white/10 backdrop-blur border border-white/20.
  • Gradient text: bg-gradient-to-r from-cyan-400 to-violet-400 bg-clip-text text-transparent.
  • Sticky sidebar: sticky top-24.
  • Ad slots: aspect ratios with aspect-video, aspect-[728/90].

Project: learning dashboard

Build a responsive dashboard with sidebar, course cards, stats row, and dark mode toggle — all Tailwind, no custom CSS file.

  • Sidebar collapses on mobile with md:flex.
  • Stats row: grid grid-cols-2 lg:grid-cols-4.
  • Course cards with hover lift and gradient borders.
  • Deploy to Vercel.

Continue learning

  • Next.js course: /learn/web-development/nextjs-advanced-patterns
  • React: /learn/web-development/react-complete-guide
  • MCQ Quiz: /mcq/tailwind-mcq
  • Interview: /interview/tailwind-interview
  • Full guide: /knowledge/tailwind-css-fundamentals

Key Takeaways

  • Tailwind uses utility classes for layout, spacing, color, and typography.
  • Mobile-first: unprefixed for mobile, sm:/md:/lg: for larger screens.
  • Compose complex UIs from small utilities — extract React components when patterns repeat.
  • dark: variant enables dark mode with class strategy.
  • Use tailwind-merge to avoid conflicting classes in dynamic components.

Frequently Asked Questions

Isn't Tailwind just inline styles?
No. Tailwind uses a design system with consistent tokens, responsive variants, state variants, and purges unused CSS in production. Inline styles lack these features.
Tailwind vs Bootstrap?
Bootstrap gives pre-built components. Tailwind gives low-level utilities for fully custom designs. Tailwind fits modern component-based apps better.