🎨 Styling, Images और Fonts · Lesson 15
CSS Modules और Global CSS
Next.js में styling के options
| Method | File | किसके लिए best |
|---|---|---|
| Global CSS | app/globals.css | Reset, variables, utility classes (.btn, .container) |
| CSS Modules | Card.module.css | Component-specific styles, name clash नहीं |
| Tailwind CSS | class="p-4 bg-white" | तेज़ utility-first styling (अगला lesson) |
| Inline style | style={{ }} | Dynamic one-off values (progress width) |
Global CSS (globals.css)
CSS – app/globals.css
/* app/globals.css (from the EduSite project) */
:root {
--brand: #4f46e5;
--brand-dark: #3730a3;
--ink: #0f172a;
--muted: #475569;
--line: #e2e8f0;
--bg: #f8fafc;
--radius: 16px;
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--ink); line-height: 1.65; }
a { color: var(--brand); text-decoration: none; }
img { max-width: 100%; height: auto; }
.container { width: min(1120px, calc(100% - 32px)); margin: 0 auto; }
.grid { display: grid; gap: 20px;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.btn { display: inline-block; background: var(--brand); color: #fff;
padding: 12px 22px; border-radius: 999px; font-weight: 700; }
.btn:hover { background: var(--brand-dark); }
.badge { background: #eef2ff; color: var(--brand-dark); font-size: .78rem;
padding: 3px 10px; border-radius: 999px; }JSX – root layout में एक बार import
// app/layout.jsx import './globals.css' // once, at the top – applies to the whole site
Theme के लिए CSS variables
सारे colours :root में हैं। --brand एक बार बदलिए और हर button, link, badge बदल जाता है — उस client के लिए perfect जो कहे "इसे green कर दो"।
CSS Modules (*.module.css)
CSS – components/CourseCard.module.css
/* components/CourseCard.module.css */
.card { background: #fff; border: 1px solid var(--line);
border-radius: var(--radius); overflow: hidden; transition: transform .2s; }
.card:hover { transform: translateY(-4px); box-shadow: 0 12px 30px rgba(0,0,0,.08); }
.body { padding: 16px 18px; }
.title { margin: 8px 0 4px; font-size: 1.15rem; }
.fee { font-weight: 800; color: var(--brand); }JSX – components/CourseCard.jsx
// components/CourseCard.jsx
import Link from 'next/link'
import styles from './CourseCard.module.css'
export default function CourseCard({ course }) {
return (
<Link href={`/courses/${course.slug}`} className={styles.card}>
<div className={styles.body}>
<span className="badge">{course.level}</span> {/* global class */}
<h3 className={styles.title}>{course.title}</h3> {/* module class */}
<p className={styles.fee}>₹{course.fee}</p>
</div>
</Link>
)
}CSS Modules clash कैसे रोकते हैं
Next.js build time पर हर class को unique नाम दे देता है:
Rendered HTML
<a class="CourseCard_card__x7Ab2" href="/courses/nextjs">
<div class="CourseCard_body__p0Qe1">
<h3 class="CourseCard_title__Lm3kZ">Next.js</h3>
Plain CSS
- Card.css में .card
- Blog.css में .card
- आखिरी वाला जीतता → bugs
CSS Modules
- CourseCard_card__x7Ab2
- PostCard_card__9kP1s
- कभी टकराते नहीं
Responsive mobile menu
CSS – components/Header.module.css
/* components/Header.module.css (EduSite) */
.header { position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,.92);
backdrop-filter: blur(8px); border-bottom: 1px solid var(--line); }
.bar { display: flex; align-items: center; justify-content: space-between; height: 64px; }
.nav { display: flex; gap: 6px; }
.nav a { color: var(--ink); font-weight: 600; padding: 8px 14px; border-radius: 999px; }
.nav a.active { background: var(--brand); color: #fff; }
.toggle { display: none; } /* hamburger hidden on desktop */
@media (max-width: 760px) {
.toggle { display: block; }
.nav { display: none; position: absolute; top: 64px; left: 0; right: 0;
flex-direction: column; background: #fff; padding: 12px 16px; }
.nav.open { display: flex; } /* shown when state open = true */
}JSX – state से toggle
// components/Header.jsx (part)
const [open, setOpen] = useState(false)
...
<button className={styles.toggle} aria-expanded={open} onClick={() => setOpen(!open)}>
{open ? '✕' : '☰'}
</button>
<nav className={`${styles.nav} ${open ? styles.open : ''}`}>
...links
</nav>Conditional class names
JSX – तीन patterns
// 1) template string
<p className={`${styles.fee} ${course.fee === 0 ? styles.free : ''}`}>
// 2) array join (cleaner with many classes)
<p className={[styles.fee, isFree && styles.free].filter(Boolean).join(' ')}>
// 3) inline style for one-off dynamic values
<div style={{ width: `${progress}%`, background: 'var(--brand)', height: 6 }} />आम गलतियाँ
className=की जगहclass=लिखना।styles.my-card→ hyphen JS तोड़ता है;styles['my-card']या camelCase.myCarduse करें।- Module में element selectors (
h1 { }) → modules को class चाहिए; element styles globals.css में रखें। * { box-sizing: border-box }भूलना → mobile पर widths overflow।
सारांश
- Variables, reset और shared utilities के लिए globals.css (layout में import)।
- Component styles के लिए CSS Modules — class names अपने आप unique।
- Media queries + state toggle से mobile menu बनता है।
✅ Practice
अपनी PostCard.module.css के साथ PostCard component बनाइए। --brand को green करके पूरी site बदलते देखिए।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
Next.js में global CSS कहाँ import कर सकते हैं?
Global stylesheets किसी भी layout या page में import हो सकती हैं, पर आमतौर पर app/layout.jsx में करते हैं ताकि हर page पर load हों।
Plain CSS की जगह CSS Modules क्यों?
CSS Modules हर file के class names unique बना देते हैं, इसलिए एक component का .card दूसरे का .card कभी नहीं बिगाड़ता। ये Next.js में बिना setup के built-in हैं।
क्या Sass use कर सकते हैं?
हाँ। npm install sass चलाइए और files को .scss या .module.scss नाम दीजिए। Next.js उन्हें अपने आप compile करता है।
