Positioning और Z-Index
Static, Relative, Absolute, Fixed और Sticky का सच। Z-Index और Stacking Context की उलझनों को हमेशा के लिए सुलझाएं।
🎯 इस पाठ में आप क्या सीखेंगे
📍 CSS पोजीशनिंग के 5 मोड्स की तुलना
`position` प्रॉपर्टी किसी भी तत्व को डॉक्यूमेंट के सामान्य बहाव (normal flow) से अलग करती है या उसके संदर्भ बिंदु को बदलती है:
डॉक्यूमेंट का सामान्य बहाव। Top, left, right, bottom, और `z-index` का इस पर शून्य असर होता है।
अपनी मूल जगह सुरक्षित रखता है। `top/left` से खिसक सकता है। यह अंदरूनी Absolute बच्चों के लिए लंगर (Anchor) का काम करता है!
पेज के बहाव से पूरी तरह बाहर निकल जाता है (पीछे शून्य जगह छोड़ता है)। सबसे करीबी पोजीशन्ड पैरेंट के अनुसार तैरता है।
सीधे ब्राउज़र स्क्रीन (Viewport) से चिपक जाता है। पेज कितना भी स्क्रॉल हो, यह अपनी जगह पर जमा रहता है — नैवबार और चैट बटन के लिए आदर्श।
शुरुआत में सामान्य रहता है, लेकिन जैसे ही यूज़र तय सीमा (जैसे `top: 0`) तक स्क्रॉल करता है, यह स्क्रीन पर चिपक जाता है जब तक कि पैरेंट समाप्त न हो जाए।
`top: 0; right: 0; bottom: 0; left: 0;` का एक शब्द वाला सिंटैक्स। `margin: auto;` के साथ मिलकर स्क्रीन के ठीक बीच में मोडल सेंटर करता है।
⚓ लंगर पैटर्न (Anchor Pattern): Relative Parent + Absolute Child
पूरी वेब डेवलपमेंट में यह सबसे ज्यादा इस्तेमाल होने वाला पैटर्न है। यदि आपको किसी आइकन पर लाल नोटिफिकेशन बैज लगाना हो, या ई-कॉमर्स कार्ड पर “50% छूट” का स्टीकर चिपकाना हो:
/* 1. पैरेंट कंटेनर निर्देशांक प्रणाली (Coordinate System) बनाता है */
.card {
position: relative; /* लंगर (Anchor): यह सीमा रेखा तय करता है */
width: 320px;
padding: 24px;
}
/* 2. बच्चा उस पैरेंट की दीवार के अनुसार आज़ादी से तैरता है */
.card-badge {
position: absolute;
top: -12px; /* कार्ड की ऊपरी दीवार से 12px ऊपर तैरता है */
right: 16px; /* कार्ड के दाएँ किनारे से 16px अंदर */
z-index: 10;
}⚠️ यदि आप `.card` पर `position: relative` लगाना भूल जाएँ तो क्या होगा? बैज पूर्वजों में ढूंढते हुए सीधे `<body>` तक पहुँच जाएगा और आपकी पूरी स्क्रीन के सबसे ऊपरी दाएँ कोने में जाकर चिपक जाएगा!
💻 लाइव पोजीशनिंग और Z-Index प्लेग्राउंड
🥞 स्टैकिंग कॉन्टेक्स्ट (Stacking Context): `z-index: 999999` क्यों फेल होता है?
क्या आपने कभी `z-index: 999999` लगाया है और फिर भी आपका मोडल या ड्रॉपडाउन नीचे वाले एलिमेंट के पीछे दब गया? ऐसा इसलिए होता है क्योंकि `z-index` एक चपटी ज़मीन नहीं है। ब्राउज़र त्रि-आयामी परतों के समूह (Stacking Contexts) बनाता है:
स्टैकिंग कॉन्टेक्स्ट को एक बहुमंजिला इमारत की मंजिलों की तरह समझें:
- कंटेनर A पहली मंजिल पर है। कंटेनर B दूसरी मंजिल पर है।
- कंटेनर A के अंदर एक कर्मचारी 100 फीट की सीढ़ी (`z-index: 999999`) पर चढ़ जाता है।
- वह सीढ़ी चाहे कितनी भी ऊंची हो, वह पहली मंजिल की छत के नीचे ही रहेगी। वह दूसरी मंजिल (`z-index: 1`) पर आराम से खड़े व्यक्ति से ऊंची कभी नहीं हो सकती!
- क्योंकि कंटेनर B डॉक्यूमेंट में कंटेनर A के ऊपर है, इसलिए B के सारे बच्चे A के सभी बच्चों से ऊपर ही दिखेंगे।
position: relative/absolute + z-index != autoposition: fixed या position: stickyopacity < 1transform != nonefilter != none या backdrop-filterisolation: isolate; (सबसे साफ समाधान!)🎯 सटीक सेंटरिंग: `inset: 0; margin: auto`
पुराने समय में मोडल को स्क्रीन के बीच में लाने के लिए `top: 50%; left: 50%; transform: translate(-50%, -50%);` लगाना पड़ता था, जिससे कई स्क्रीन्स पर धुंधले पिक्सल्स बनते थे। आधुनिक सबसे साफ तरीका है `inset: 0; margin: auto;`:
.modal-dialog {
position: absolute;
inset: 0;
margin: auto;
width: min(90vw, 480px);
height: fit-content;
border-radius: 16px;
}जब आप चारों दिशाओं को शून्य (inset: 0) करते हैं, तो ब्राउज़र उपलब्ध बाउंड्री को पूरे पैरेंट पर फैला देता है।
जैसे ही आप सीमित width और height तय करते हैं, margin: auto बची हुई सारी अतिरिक्त खाली जगह को चारों तरफ बराबर-बराबर बांट देता है, जिससे डिब्बा ठीक बीच में चिपक जाता है!
कोड का पंक्ति-दर-पंक्ति विश्लेषण
.sticky-header { position: sticky; top: 0; z-index: 10; }यूज़र के स्क्रॉल करते ही नैवबार को शीर्ष पर चिपका देता है। `z-index: 10` यह सुनिश्चित करता है कि नीचे के प्रोडक्ट कार्ड्स इसके नीचे से फिसलें।
.product-card { position: relative; }लंगर (Anchor)! डिस्काउंट बैज को कार्ड के अंदर सीमित रखने के लिए यह रिलेटिव पोजीशन अनिवार्य है।
.discount-badge { position: absolute; top: -10px; right: 14px; }कार्ड के ऊपरी किनारे से 10px बाहर लटकता है, जैसे दुकान पर कपड़ों पर लगा 50% छूट वाला स्टीकर।
.fixed-bubble { bottom: 16px; right: 16px; }निचले दाएँ कोने में चैट बबल को स्थिर रखता है ताकि स्क्रॉल करते समय भी ग्राहक आसानी से मदद मांग सके।
Q1किसी एलिमेंट पर `position: absolute; top: 10px; right: 10px;` लगा है। यह किस पैरेंट या पूर्वज (Ancestor) के सापेक्ष अपनी जगह तय करेगा?
Q2वास्तविक वेब ऐप्स में `position: sticky; top: 0;` अक्सर स्क्रॉल करते समय चिपकने में असफल क्यों हो जाता है?
Q3`z-index: 999999` लगाने के बावजूद कोई एलिमेंट `z-index: 1` वाले दूसरे एलिमेंट के पीछे क्यों दब जाता है?
Q4जब किसी पैरेंट पर `transform: translate(0, 0)` या `filter: blur(0)` लगा हो, तो उसके अंदर मौजूद `position: fixed` एलिमेंट के साथ क्या होता है?
प्रैक्टिस चैलेंज: सेल बैज को दूसरी दिशा में ले जाएं
दाएँ हाथ के लाइव कोड एडिटर में:
- स्टेप 1:
.discount-badgeमेंright: 14px;को बदलकरleft: 14px;करें ताकि बैज बाएँ कोने में सज जाए। - स्टेप 2: इसका बैकग्राउंड चमकीला हरा करें:
background: #10b981;और HTML में टेक्स्ट“नया आगमन” (NEW ARRIVAL)कर दें। - स्टेप 3: स्टैकिंग कॉन्टेक्स्ट का परीक्षण करें: थोड़ी देर के लिए
.product-cardपरz-index: 100;और.sticky-headerपरz-index: 5;लगाकर देखें। नीचे स्क्रॉल करें — देखें कि कैसे प्रोडक्ट कार्ड स्टिकी हेडर के ऊपर चढ़ जाता है! - स्टेप 4: सही पदानुक्रम बनाए रखने के लिए
.sticky-headerको वापसz-index: 10;कर दें।
💡 सही समाधान कोड देखने के लिए यहाँ क्लिक करें
सामान्य गलतियाँ और सीनियर डेवलपर इंटरव्यू प्रश्न
❌ गलती: CSS Transform द्वारा Fixed एलिमेंट का फंस जाना
यदि किसी पैरेंट पर transform: translateY(0) लगा हो, तो उसके अंदर के सारे position: fixed मोडल स्क्रीन पर जमना बंद कर देते हैं! Transform उस पैरेंट को स्क्रीन के बदले नया कंटेनर बना देता है। हमेशा फिक्स्ड मोडल और ओवरले को मुख्य `<body>` स्तर पर रेंडर करें (जैसे React Portals द्वारा)।
✅ प्रो टिप: Z-Index युद्ध रोकने के लिए `isolation: isolate`
पूरी टीम में z-index: 99999 की होड़ लगाने के बजाय, अपने घटकों के मुख्य कंटेनर पर isolation: isolate; लगा दें। यह बिना किसी नकली पोजीशनिंग के एकदम साफ नया स्थानीय Stacking Context बना देता है, जिससे अंदरूनी z-index बाहर नहीं छलकते।
💬 Interview Q: `position: fixed` और `position: sticky` में क्या तकनीकी अंतर है?
`position: fixed` पूरी तरह स्वतंत्र है: यह डॉक्यूमेंट फ्लो से बाहर निकल जाता है, पैरेंट में शून्य जगह घेरता है, और पूरी स्क्रीन विंडो से बंधा रहता है चाहे यूज़र कहीं भी स्क्रॉल करे।
`position: sticky` पैरेंट की सीमा में बंधा है: यह सामान्य डॉक्यूमेंट फ्लो में जगह घेरता है। स्क्रॉल करने पर यह फिक्स तो होता है, लेकिन केवल अपने सीधे पैरेंट की चारदीवारी तक ही! जैसे ही पैरेंट का निचला सिरा आता है, स्टिकी तत्व रुक जाता है और ऊपर बह जाता है।
💬 Interview Q: ब्राउज़र `position: absolute` के लिए कंटेनिंग ब्लॉक (Containing Block) कैसे तय करता है?
ब्राउज़र उल्टे क्रम में पूर्वजों (ancestors) की जाँच करता है:
- सबसे पहले ऐसे नजदीकी पूर्वज को ढूंढता है जिसकी `position` static न हो (`relative`, `absolute`, `fixed`, `sticky`)।
- यदि ऐसा कोई न मिले, तो देखता है कि क्या किसी पूर्वज पर `transform`, `perspective`, `filter`, या `contain: paint` लगा है।
- यदि तब भी कोई न मिले, तो डिफ़ॉल्ट रूप से Initial Containing Block (ब्राउज़र का Viewport / `<html>`) कंटेनिंग ब्लॉक बन जाता है।
💬 Interview Q: `position: sticky` को काम करने के लिए `top: 0` जैसा कोई थ्रेशोल्ड क्यों अनिवार्य है?
बिना किसी थ्रेशोल्ड (जैसे top, bottom, left, या right) के ब्राउज़र को यह पता ही नहीं चलता कि एलिमेंट को सामान्य फ्लो से स्टिकी स्थिति में कब बदलना है। यदि आप सिर्फ position: sticky; लिखकर छोड़ देंगे, तो थ्रेशोल्ड `auto` रहेगा और वह एक साधारण `position: relative` की तरह व्यवहार करेगा जो कभी नहीं चिपकेगा!