Animations और CSS Variables
@keyframes से अनंत एनीमेशन (Pulse radar, gradient text) और :root CSS Variables से डार्क मोड थीमिंग की पूरी महारत।
🎯 इस अंतिम अध्याय में आप क्या सीखेंगे
from/to और percentage stops।:root design tokens, var() syntax, fallbacks और scope।animation-delay से cascading entrance animations।🎬 दो ऐसे concepts जो CSS का आखिरी दरवाज़ा खोल देते हैं
कोड लिखने से पहले इन दो real-world ideas को समझ लो — यही समझते ही सब कुछ click हो जाएगा:
@keyframes = फिल्म डायरेक्टर का Storyboard
एक एनिमेटर जब सुपरहीरो की छलांग बनाता है, तो वह सिर्फ शुरुआत और अंत नहीं बनाता। वह मुख्य poses बनाता है: 0%: ज़मीन पर झुकना → 50%: बादलों में उड़ना → 100%: छत पर उतरना। ब्राउज़र बीच के सैकड़ों frames अपने आप मक्खन जैसी smoothness से भर देता है।
@keyframes = आपका storyboard। ब्राउज़र = animation team जो बीच के frames भरती है।
CSS Variables = दिवाली का Master Switchboard
मान लीजिए आपने मकान पर 1,000 बल्बों की दिवाली लड़ियाँ लगाई हैं। अगर तारें fixed हों, सुनहरे से नीला करने के लिए 1,000 बल्ब हाथ से बदलने पड़ेंगे। Master switchboard (:root { --theme: blue; }) पर एक button दबाते ही पूरा घर 1 millisecond में नीला!
CSS variables = आपका switchboard। :root में एक value बदलो — 500 components एक साथ update।
🎞️ @keyframes की बनावट — अपनी Timeline खुद लिखना
@keyframes block एक named timeline recipe है। इसके दो हिस्से हैं: एक name, और percentage stops जो बताते हैं कि हर moment पर element कैसा दिखना चाहिए।
Option A: Simple Two-State (from / to)
/* 0% → 100% का shorthand */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Element पर लगाएँ: */
.hero-title {
animation: fadeIn 0.6s ease forwards;
}
Option B: Full Multi-Stop Timeline (%)
/* कोई भी % value use कर सकते हो */
@keyframes radarPing {
0% { transform: scale(0.5); opacity: 1; }
50% { transform: scale(1.4); opacity: 0.6; }
100% { transform: scale(2.2); opacity: 0; }
}
.radar-ring {
animation: radarPing 1.8s ease infinite;
}
@keyframes लिखते समय ज़रूरी नियम
- ①
@keyframesके बाद जो name लिखो (radarPing) वह element केanimation-nameसे बिल्कुल match होना चाहिए। Case-sensitive है। - ②जितने चाहो percentage stops लिख सकते हो:
0%, 20%, 45%, 80%, 100%। सबको define करना ज़रूरी नहीं। - ③Infinite loops में सिर्फ
transformऔरopacityanimate करो।box-shadow,filter,widthहर frame पर Paint trigger करते हैं — battery खत्म! - ④
@keyframesblock खुद से कुछ नहीं करता — यह सिर्फ recipe है। इसे element परanimationproperty से apply करना होगा।
Animation के 8 Sub-Properties — हर Knob की जानकारी
| Property | उदाहरण | यह क्या तय करती है? |
|---|---|---|
| animation-name | radarPing | आपके @keyframes block का exact नाम। Case-sensitive है। |
| animation-duration | 1.8s | एक पूरा चक्र कितने समय में होगा। ज़रूरी है — बिना इसके animation नहीं चलेगा (default 0s)। |
| animation-timing-function | ease, linear | हर keyframe stop के बीच speed curve। transition की तरह ही काम करता है। |
| animation-delay | 0.2s | शुरू होने से पहले कितनी देरी। Stagger cascade के लिए। Negative value animation को बीच से start करती है। |
| animation-iteration-count | infinite, 3, 1.5 | कितनी बार दोहराएगा। infinite = हमेशा। Decimal values = आधा cycle। |
| animation-direction | normal, alternate | alternate हर odd cycle में reverse चलाता है — seamless breathing effect बनता है, कोई jump नहीं। |
| animation-fill-mode | forwards, both | forwards = last frame पर freeze। backwards = delay के दौरान first frame apply। both = दोनों। |
| animation-play-state | running, paused | Animation को position खोए बिना pause/resume। Hover पर spinner रोकने के लिए: :hover { animation-play-state: paused; } |
Shorthand क्रम (सबसे common 6 values)
animation: radarPing 1.8s ease 0s infinite normal;क्रम: name duration timing delay iteration-count direction। सिर्फ infinite loop के लिए 3-value shorthand भी काम करता है: animation: radarPing 1.8s infinite;
🎭 Stagger Pattern — Cascading Entrance Animations
Modern UI का सबसे elegant animation pattern: हर element को थोड़ा-थोड़ा बढ़ता हुआ animation-delay देकर waterfall cascade effect बनाना:
/* हर card को पिछले से थोड़ी ज़्यादा delay */
.card:nth-child(1) { animation-delay: 0s; }
.card:nth-child(2) { animation-delay: 0.1s; }
.card:nth-child(3) { animation-delay: 0.2s; }
/* सभी cards एक ही @keyframes share करते हैं */
.card {
animation: slideUp 0.5s ease forwards;
opacity: 0; /* शुरुआत में छुपे रहते हैं */
}
यह pattern लगभग हर premium landing page पर use होता है — Stripe, Linear, Vercel सब staggered card entrances use करते हैं।
🎨 CSS Custom Properties (Variables) — Design Token System
CSS Custom Properties (CSS Variables) आपको values को named slots में store करने और हर जगह reuse करने देते हैं। Sass/Less variables build time पर compile होकर गायब हो जाते हैं, लेकिन CSS Variables ब्राउज़र के actual DOM में ज़िंदा रहते हैं।
Step 1: :root में Declare करो (Global Scope)
/* :root = html element — global scope */
:root {
/* Name हमेशा -- (दो dash) से शुरू होना चाहिए */
--brand-primary: #4f46e5;
--brand-secondary: #7c3aed;
--bg-surface: #ffffff;
--text-primary: #0f172a;
--spacing-lg: 2rem;
}
Step 2: var() से Use करो
/* CSS में कहीं भी var(--name) use करो */
.btn-primary {
background: var(--brand-primary);
padding: var(--spacing-lg);
}
/* Fallback के साथ — अगर variable न मिले: */
.card {
color: var(--text-primary, #1e293b);
/* ↑ fallback अगर undefined हो */
}
CSS Variables vs Sass/Less Variables — असली फ़र्क
❌ Sass Variable (compile-time)
// .scss file में:
$brand: #4f46e5;
.btn { background: $brand; }
/* Compile के बाद plain CSS: */
.btn { background: #4f46e5; }
Build के बाद variable गायब। JavaScript नहीं पढ़ सकता। Media query में override नहीं हो सकता।
✅ CSS Custom Property (live, browser में)
/* .css file — DOM में ज़िंदा रहता है: */
:root { --brand: #4f46e5; }
.btn { background: var(--brand); }
/* JavaScript से runtime में बदल सकते हो: */
document.documentElement.style
.setProperty('--brand', '#10b981');
DOM में ज़िंदा। JS से real-time में बदल सकते हो। Media queries, class changes, cascade scope — सब respond करता है।
Variable Scope — :root में Global, Components में Local
Variables normal CSS की तरह cascade करते हैं — child elements parents से inherit करते हैं। किसी component के अंदर global :root variable को locally override कर सकते हो:
:root { --accent: #4f46e5; } /* Global: purple */
/* पूरी site के सभी buttons → purple */
.btn { background: var(--accent); }
/* Local override — सिर्फ .danger-zone के अंदर */
.danger-zone { --accent: #ef4444; } /* red */
/* .danger-zone के अंदर buttons → red। बाकी site untouched! */
🌙 Zero-JavaScript Dark Mode का Formula
सबसे elegant dark mode technique: :root में light values define करो, फिर prefers-color-scheme: dark media query के अंदर उन्हें override करो। पूरी site की हर var() usage automatically switch हो जाती है:
/* Light mode (default) */
:root {
--bg: #ffffff; --text: #0f172a; --card-bg: #f8fafc;
}
/* Dark mode — सिर्फ variable values बदलते हैं! */
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a; --text: #f1f5f9; --card-bg: #1e293b;
}
}
/* var(--bg), var(--text), var(--card-bg) use करने वाले सभी elements */
/* automatically light/dark switch करते हैं — ZERO JavaScript! */
💻 लाइव Animations और Custom Properties एडिटर
Radar beacon एक multi-stop @keyframes timeline use करता है। Gradient heading में -webkit-background-clip: text technique है। Dark mode toggle :root variable values swap करता है। Keyframe percentages, colors और duration बदलकर देखें!
Code का एक-एक लाइन विश्लेषण
Playground की सबसे important techniques का विस्तृत विश्लेषण:
@media (prefers-color-scheme: dark) { :root { --bg-surface: #1e293b; } }Zero-JavaScript dark mode का formula। जब user के OS में dark mode चालू होता है तो media query fire होती है। :root variables को redefine करने से CSS में var(--bg-surface) use करने वाला हर element automatically update हो जाता है — एक भी element selector को छुए बिना, एक भी line JavaScript लिखे बिना।
-webkit-background-clip: text; -webkit-text-fill-color: transparent;Gradient text का secret formula। पहले linear-gradient को background set किया जाता है। फिर -webkit-background-clip: text उस gradient को अक्षरों के exact shapes पर clip कर देता है। अंत में -webkit-text-fill-color: transparent original text fill को invisible कर देता है, जिससे gradient background अक्षरों के अंदर से दिखता है। @keyframes animation background-position को shift करके gradient को बहता हुआ दिखाती है।
animation: radarPing 1.8s cubic-bezier(0, 0, 0.2, 1) infinite;Radar beacon ring। cubic-bezier(0, 0, 0.2, 1) timing curve तेज़ शुरू होकर decelerate होती है — जैसे एक point से निकलने वाली physical wave naturally फैलती है। infinite इसे हमेशा loop करता रखता है। यह एक ::after pseudo-element पर apply होता है जिससे HTML clean रहता है।
animation-fill-mode: forwards; + initial state में opacity: 0;Entrance animation pattern। Element शुरुआत में छुपा (opacity: 0) रहता है। Keyframe animation उसे fade-in करती है। animation-fill-mode: forwards उसे final visible (opacity: 1) state में freeze कर देता है। बिना forwards के animation खत्म होते ही element फिर invisible हो जाएगा।
Q1CSS `transition` और `@keyframes` एनीमेशन में सबसे मुख्य अंतर क्या है?
Q2CSS एनीमेशन खत्म होने पर `animation-fill-mode: forwards;` क्या करता है?
Q3`color: var(--accent-color, #4f46e5);` में यह `#4f46e5` क्या काम करता है?
खुद ट्राई करो: 4-Tier Animation System बनाओ
ऊपर के live editor में ये 4 experiments order में करो:
- Beacon का रंग बदलो:
@keyframes radarPingमें pulse dot का रंग हरे (#10b981) से लाल (#ef4444) करो।rgbavalue भी match करके update करो। यह urgent red alert beacon बनाएगा! - Heartbeat तेज़ करो:
animation-durationको1.8sसे0.6sकरो। Urgency कितना बदल जाती है feel करो — Live streaming के "LIVE" indicator dot यही technique use करते हैं। - Stagger जोड़ो: Radar section HTML को दो बार copy करो। दूसरे को
animation-delay: 0.3sऔर तीसरे कोanimation-delay: 0.6sदो। तीन beacons का cascading ripple देखो! - Bonus — सांस लेता button: CSS में यह जोड़ो:
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }। Dark mode toggle button परanimation: breathe 2s ease-in-out infinite alternate;apply करो। Button सोते हुए device की तरह saans लेगा!
💡 पूरा solution देखने के लिए क्लिक करें
/* Red alert beacon */
.pulse-dot { background: #ef4444; }
.pulse-dot::after {
background: rgba(239, 68, 68, 0.4);
animation: radarPing 0.6s cubic-bezier(0, 0, 0.2, 1) infinite;
}
/* Breathing button */
@keyframes breathe {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.toggle-btn { animation: breathe 2s ease-in-out infinite alternate; }
आम गलतियाँ और इंटरव्यू के सवाल
❌ गलती 1: Infinite Loop में Layout Properties
कभी भी box-shadow, width, height, या filter पर infinite @keyframes मत चलाएँ। 60fps animation = 60 repaints per second — लगातार mobile battery drain और device overheat। Infinite loops में सिर्फ transform और opacity।
❌ गलती 2: `animation-fill-mode: forwards` भूल जाना
opacity: 0 से opacity: 1 entrance animation में अगर forwards भूल गए, तो animation खत्म होते ही element फिर invisible हो जाएगा। Entrance animations में हमेशा animation-fill-mode: forwards लगाओ।
✅ Best Practice: `prefers-reduced-motion` Accessibility
सभी animations को motion-safe guard में wrap करो। Professional pattern: सभी animations @media (prefers-reduced-motion: no-preference) { ... } के अंदर रखो — वे सिर्फ तभी चलेंगी जब user ने reduced motion request नहीं की।
✅ Best Practice: Variables को Semantic नाम दो
CSS variables का नाम उनके काम के हिसाब से रखो, value के हिसाब से नहीं। --color-dark-gray के बजाय --color-text-primary लिखो। Dark mode में जब value #f1f5f9 (white) हो जाए, तो --color-dark-gray confusing लगता है।
💬 इंटरव्यू प्रश्न: क्या CSS Variables को JavaScript से पढ़ा और बदला जा सकता है?
हाँ! Sass/Less variables build के बाद गायब हो जाते हैं, लेकिन CSS Custom Properties ब्राउज़र के actual DOM में ज़िंदा रहते हैं और JavaScript से fully accessible हैं।
// CSS variable READ करो:
getComputedStyle(document.documentElement)
.getPropertyValue('--brand-primary');
// CSS variable WRITE/UPDATE करो:
document.documentElement.style
.setProperty('--brand-primary', '#10b981');
यही React, Vue, Angular apps में theme switchers काम करते हैं — CSS variables write करते हैं, पूरा UI instantly update होता है, individual components re-render नहीं होते।
💬 इंटरव्यू प्रश्न: `animation-direction: alternate` क्या है और कब काम आता है?
animation-direction: alternate हर odd cycle में animation को reverse में चलाता है। इससे seamless ping-pong effect बनता है।
Alternate के बिना: Animation 0%→100% चलती है, फिर jump करके 0% पर आती है और फिर चलती है। हर loop पर jarring snap।
Alternate के साथ: 0%→100% (forward), फिर smoothly 100%→0% (backward) — continuous breathing जैसा loop, zero jump।
💬 इंटरव्यू प्रश्न: CSS Variable का Scope और Cascade कैसे काम करता है?
CSS Custom Properties normal CSS cascade और inheritance के नियम follow करते हैं। Parent पर define किया गया variable उसके सभी children inherit करते हैं।
:root <html> element को target करता है — सबसे ऊँचे ancestor — इसलिए वहाँ define variables globally हर element पर available होते हैं। लेकिन कोई भी descendant अपने subtree के लिए same variable locally override कर सकता है बाहर के बाकी site को affect किए बिना।
यही component-per-theme systems काम करते हैं: .dark-section --bg और --text locally override करता है, सिर्फ वह हिस्सा dark हो जाता है।
💬 इंटरव्यू प्रश्न: `animation-play-state` क्या है और practically कैसे use होता है?
animation-play-state: paused running animation को उसकी current position पर freeze करता है। running exactly वहीं से resume करता है जहाँ pause हुआ था।
Common real use: carousel auto-scroll पर user hover करने पर pause करना (accessibility best practice), या loading spinner को hover पर रोककर inspect करना: