Tailwind CSS with React
Tailwind CSS is a utility-first framework that integrates beautifully with React.
Installation
bash
1npm install -D tailwindcss postcss autoprefixer
2npx tailwindcss init -pjavascript
1// tailwind.config.js
2export default {
3 content: [
4 "./index.html",
5 "./src/**/*.{js,ts,jsx,tsx}",
6 ],
7 theme: {
8 extend: {},
9 },
10 plugins: [],
11}css
1/* index.css */
2@tailwind base;
3@tailwind components;
4@tailwind utilities;Basic Usage
jsx
1function Card({ title, children }) {
2 return (
3 <div className="bg-white rounded-lg shadow-md p-6 max-w-md mx-auto">
4 <h2 className="text-2xl font-bold text-gray-800 mb-4">{title}</h2>
5 <p className="text-gray-600 leading-relaxed">{children}</p>
6 </div>
7 )
8}Responsive Design
jsx
1function ResponsiveGrid({ items }) {
2 return (
3 <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 p-4">
4 {items.map(item => (
5 <div
6 key={item.id}
7 className="bg-white p-4 rounded shadow
8 sm:p-6
9 md:p-8"
10 >
11 <h3 className="text-lg md:text-xl lg:text-2xl font-bold">
12 {item.title}
13 </h3>
14 </div>
15 ))}
16 </div>
17 )
18}Interactive States
jsx
1function Button({ children }) {
2 return (
3 <button className="
4 bg-blue-500 text-white px-4 py-2 rounded
5 hover:bg-blue-600
6 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
7 active:bg-blue-700
8 disabled:opacity-50 disabled:cursor-not-allowed
9 transition-colors duration-200
10 ">
11 {children}
12 </button>
13 )
14}Conditional Classes with clsx
bash
1npm install clsxjsx
1import clsx from 'clsx'
2
3function Button({ variant, size, disabled, children }) {
4 return (
5 <button
6 className={clsx(
7 // Base styles
8 'font-medium rounded transition-colors',
9
10 // Variants
11 {
12 'bg-blue-500 text-white hover:bg-blue-600': variant === 'primary',
13 'bg-gray-200 text-gray-800 hover:bg-gray-300': variant === 'secondary',
14 'bg-red-500 text-white hover:bg-red-600': variant === 'danger',
15 'bg-transparent border border-gray-300 hover:bg-gray-50': variant === 'outline',
16 },
17
18 // Sizes
19 {
20 'text-sm px-3 py-1.5': size === 'small',
21 'px-4 py-2': size === 'medium',
22 'text-lg px-6 py-3': size === 'large',
23 },
24
25 // States
26 {
27 'opacity-50 cursor-not-allowed': disabled,
28 }
29 )}
30 disabled={disabled}
31 >
32 {children}
33 </button>
34 )
35}Dark Mode
javascript
1// tailwind.config.js
2export default {
3 darkMode: 'class',
4 // ...
5}jsx
1function ThemeToggle() {
2 const [dark, setDark] = useState(false)
3
4 useEffect(() => {
5 document.documentElement.classList.toggle('dark', dark)
6 }, [dark])
7
8 return (
9 <button onClick={() => setDark(!dark)}>
10 {dark ? '☀️' : '🌙'}
11 </button>
12 )
13}
14
15function Card() {
16 return (
17 <div className="bg-white dark:bg-gray-800 text-gray-900 dark:text-white p-6 rounded-lg shadow">
18 <h2 className="text-xl font-bold">Title</h2>
19 <p className="text-gray-600 dark:text-gray-300">Content</p>
20 </div>
21 )
22}Component Patterns
Reusable Input
jsx
1function Input({ label, error, ...props }) {
2 return (
3 <div className="mb-4">
4 {label && (
5 <label className="block text-sm font-medium text-gray-700 mb-1">
6 {label}
7 </label>
8 )}
9 <input
10 className={clsx(
11 'w-full px-3 py-2 border rounded-md shadow-sm',
12 'focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500',
13 error
14 ? 'border-red-500 focus:ring-red-500 focus:border-red-500'
15 : 'border-gray-300'
16 )}
17 {...props}
18 />
19 {error && (
20 <p className="mt-1 text-sm text-red-600">{error}</p>
21 )}
22 </div>
23 )
24}Modal
jsx
1function Modal({ isOpen, onClose, title, children }) {
2 if (!isOpen) return null
3
4 return (
5 <div className="fixed inset-0 z-50 overflow-y-auto">
6 {/* Backdrop */}
7 <div
8 className="fixed inset-0 bg-black bg-opacity-50 transition-opacity"
9 onClick={onClose}
10 />
11
12 {/* Modal */}
13 <div className="flex min-h-full items-center justify-center p-4">
14 <div className="relative bg-white rounded-lg shadow-xl max-w-lg w-full p-6">
15 <div className="flex items-center justify-between mb-4">
16 <h2 className="text-xl font-bold">{title}</h2>
17 <button
18 onClick={onClose}
19 className="text-gray-400 hover:text-gray-600"
20 >
21 ✕
22 </button>
23 </div>
24 <div>{children}</div>
25 </div>
26 </div>
27 </div>
28 )
29}Badge
jsx
1function Badge({ variant = 'default', children }) {
2 const variants = {
3 default: 'bg-gray-100 text-gray-800',
4 success: 'bg-green-100 text-green-800',
5 warning: 'bg-yellow-100 text-yellow-800',
6 danger: 'bg-red-100 text-red-800',
7 info: 'bg-blue-100 text-blue-800',
8 }
9
10 return (
11 <span className={clsx(
12 'inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium',
13 variants[variant]
14 )}>
15 {children}
16 </span>
17 )
18}Custom Theme
javascript
1// tailwind.config.js
2export default {
3 theme: {
4 extend: {
5 colors: {
6 primary: {
7 50: '#eff6ff',
8 500: '#3b82f6',
9 600: '#2563eb',
10 700: '#1d4ed8',
11 },
12 brand: '#ff6b6b',
13 },
14 fontFamily: {
15 sans: ['Inter', 'sans-serif'],
16 },
17 spacing: {
18 '128': '32rem',
19 },
20 },
21 },
22}jsx
1<button className="bg-primary-500 hover:bg-primary-600">
2 Primary
3</button>@apply Directive
For reusable component styles:
css
1/* styles.css */
2@layer components {
3 .btn {
4 @apply px-4 py-2 font-medium rounded transition-colors;
5 }
6
7 .btn-primary {
8 @apply bg-blue-500 text-white hover:bg-blue-600;
9 }
10
11 .card {
12 @apply bg-white rounded-lg shadow-md p-6;
13 }
14}jsx
1<button className="btn btn-primary">Click me</button>
2<div className="card">Card content</div>Tailwind CSS makes styling React components fast and consistent!
