Styling --- CSS Modules, Tailwind & Global CSS
⏱ 12 min read read
Three Main Styling Approaches:
1. CSS Modules --- scoped CSS per component (.module.css files)
2. Tailwind CSS --- utility-first CSS framework (most popular with
Next.js)
3. Global CSS --- app/globals.css, imported in root layout
CSS Modules --- Scoped Styles:
/* components/Button.module.css */
.button {
background: #0070f3;
color: white;
padding: 8px 16px;
border-radius: 6px;
border: none;
cursor: pointer;
}
.button:hover { background: #0051cc; }
// components/Button.tsx
import styles from './Button.module.css';
export default function Button({ children }: { children:
React.ReactNode }) {
return <button className={styles.button}>{children}</button>;
}
Tailwind CSS --- Utility-First:
Tailwind is pre-installed when you choose it during create-next-app.
Write styles as class names --- no separate CSS file needed.
export default function Card({ title, desc }: { title: string; desc:
string }) {
return (
<div className="rounded-xl border border-gray-200 p-6 shadow-sm
hover:shadow-md transition">
<h2 className="text-xl font-bold text-gray-900
mb-2">{title}</h2>
<p className="text-gray-600 text-sm">{desc}</p>
</div>
);
}
Conditional Classes with clsx / cn:
import { clsx } from 'clsx';
function Button({ variant = 'primary', disabled }: Props) {
return (
<button
className={clsx(
'px-4 py-2 rounded font-medium transition',
variant === 'primary' && 'bg-blue-600 text-white
hover:bg-blue-700',
variant === 'ghost' && 'border border-gray-300 hover:bg-gray-50',
disabled && 'opacity-50 cursor-not-allowed',
)}
>
Click
</button>
);
}
shadcn/ui is the most popular component library for Next.js +
Tailwind.
Install: npx shadcn-ui@latest init
Add components: npx shadcn-ui@latest add button card input
Components are copied into your project --- fully customisable.
1. CSS Modules --- scoped CSS per component (.module.css files)
2. Tailwind CSS --- utility-first CSS framework (most popular with
Next.js)
3. Global CSS --- app/globals.css, imported in root layout
CSS Modules --- Scoped Styles:
/* components/Button.module.css */
.button {
background: #0070f3;
color: white;
padding: 8px 16px;
border-radius: 6px;
border: none;
cursor: pointer;
}
.button:hover { background: #0051cc; }
// components/Button.tsx
import styles from './Button.module.css';
export default function Button({ children }: { children:
React.ReactNode }) {
return <button className={styles.button}>{children}</button>;
}
Tailwind CSS --- Utility-First:
Tailwind is pre-installed when you choose it during create-next-app.
Write styles as class names --- no separate CSS file needed.
export default function Card({ title, desc }: { title: string; desc:
string }) {
return (
<div className="rounded-xl border border-gray-200 p-6 shadow-sm
hover:shadow-md transition">
<h2 className="text-xl font-bold text-gray-900
mb-2">{title}</h2>
<p className="text-gray-600 text-sm">{desc}</p>
</div>
);
}
Conditional Classes with clsx / cn:
import { clsx } from 'clsx';
function Button({ variant = 'primary', disabled }: Props) {
return (
<button
className={clsx(
'px-4 py-2 rounded font-medium transition',
variant === 'primary' && 'bg-blue-600 text-white
hover:bg-blue-700',
variant === 'ghost' && 'border border-gray-300 hover:bg-gray-50',
disabled && 'opacity-50 cursor-not-allowed',
)}
>
Click
</button>
);
}
shadcn/ui is the most popular component library for Next.js +
Tailwind.
Install: npx shadcn-ui@latest init
Add components: npx shadcn-ui@latest add button card input
Components are copied into your project --- fully customisable.
Log in to track your progress and earn badges as you complete lessons.
Log In to Track Progress