Website Markup with Tailwind CSS
Tailwind CSS is a utility-first framework with generation of only used classes. In production bundle — only those classes that actually appear in JSX/HTML. Average project: 8–15 KB CSS after gzip. This is not a component framework — it's a tool for rapid prototyping and scalable markup without context switching between files.
Installation and Setup (Tailwind v4)
Tailwind v4 transitions to CSS-first configuration:
npm install tailwindcss @tailwindcss/vite
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [
react(),
tailwindcss(),
],
});
/* src/styles/globals.css */
@import "tailwindcss";
/* Customization via CSS variables (v4) */
@theme {
--color-brand-50: #eff6ff;
--color-brand-500: #3b82f6;
--color-brand-600: #2563eb;
--font-sans: 'Inter', ui-sans-serif, system-ui;
--font-mono: 'JetBrains Mono', ui-monospace;
--radius-card: 0.75rem;
--breakpoint-xs: 375px;
}
Components: clsx + tailwind-merge
Without tailwind-merge, class merging doesn't work properly. twMerge solves this:
npm install clsx tailwind-merge
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// components/Button/Button.tsx
import { ButtonHTMLAttributes, FC } from 'react';
import { cn } from '@/lib/utils';
import { cva, type VariantProps } from 'class-variance-authority';
const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-blue-600 text-white hover:bg-blue-700',
ghost: 'bg-transparent text-blue-600 border border-blue-600 hover:bg-blue-50',
destructive: 'bg-red-600 text-white hover:bg-red-700',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4 text-sm',
lg: 'h-12 px-6 text-base',
},
},
defaultVariants: {
variant: 'default',
size: 'md',
},
}
);
interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {}
const Button: FC<ButtonProps> = ({ className, variant, size, ...props }) => (
<button className={cn(buttonVariants({ variant, size }), className)} {...props} />
);
Typical Markup Patterns
Responsive Card Grid
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{items.map((item) => (
<article
key={item.id}
className="flex flex-col rounded-lg bg-white p-5 shadow-sm ring-1 ring-black/5 hover:shadow-md"
>
<img
src={item.image}
alt={item.title}
className="mb-4 h-48 w-full rounded-md object-cover"
/>
<h3 className="mb-2 text-lg font-semibold text-gray-900">{item.title}</h3>
<p className="flex-1 text-sm text-gray-500">{item.description}</p>
<Button className="mt-4" size="sm">More</Button>
</article>
))}
</div>
Navigation with Mobile Menu
<header className="sticky top-0 z-50 border-b border-gray-100 bg-white/80 backdrop-blur-md">
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 lg:px-8">
<Logo className="h-8" />
<nav className="hidden items-center gap-6 lg:flex">
{navLinks.map((link) => (
<a
key={link.href}
href={link.href}
className="text-sm font-medium text-gray-600 transition-colors hover:text-gray-900"
>
{link.label}
</a>
))}
</nav>
<Button className="hidden lg:inline-flex">Contact</Button>
<MobileMenuButton className="lg:hidden" />
</div>
</header>
Dark Mode
/* globals.css */
@import "tailwindcss";
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
<div className="bg-white text-gray-900 dark:bg-gray-950 dark:text-gray-50">
Arbitrary Values
<div className="top-[72px] h-[calc(100svh-72px)] grid-cols-[280px_1fr] bg-[#1a1a2e]">
Use only when needed — stay within design system.
Timelines
Tailwind setup + token configuration: 2–3 hours. Markup speed with Tailwind roughly 1.5–2x faster than CSS by eliminating file switching. Landing page with all sections: 1–2 days. Full multi-page site: 3–7 days.







