रिस्पॉन्सिव स्लाइड बनाने के तरीके के बारे में खास जानकारी
इस पोस्ट में मैं आपको बताना चाहती हूँ कि मैंने वेब के लिए एक Sidenav कॉम्पोनेंट को कैसे प्रोटोटाइप किया है जो रिस्पॉन्सिव, स्टेटफ़ुल, कीबोर्ड नेविगेशन के साथ काम करता है, JavaScript के साथ और उसके बिना काम करता है, और सभी ब्राउज़र पर काम करता है. डेमो आज़माएं.
अगर आपको वीडियो देखना है, तो इस पोस्ट का YouTube वर्शन यहां देखें:
खास जानकारी
रिस्पॉन्सिव नेविगेशन सिस्टम बनाना मुश्किल है. कुछ उपयोगकर्ताओं के पास कीबोर्ड होगा, कुछ के पास शक्तिशाली डेस्कटॉप होगा और कुछ उपयोगकर्ता एक छोटे मोबाइल डिवाइस से आएंगे. वेबसाइट पर आने वाले सभी लोग मेन्यू को खोल और बंद कर सकेंगे.
वेब रणनीति
इस कॉम्पोनेंट एक्सप्लोरेशन में, मुझे वेब प्लैटफ़ॉर्म की कुछ ज़रूरी सुविधाओं को एक साथ इस्तेमाल करने में खुशी हो रही है:
- सीएसएस
:target
- सीएसएस ग्रिड
- सीएसएस के transforms
- व्यूपोर्ट और उपयोगकर्ता की पसंद के लिए सीएसएस मीडिया क्वेरी
focus
के लिए JS UX को बेहतर बनाने की सुविधा
मेरे समाधान में एक साइडबार है और सिर्फ़ तब टॉगल करता है, जब 540px
या इससे कम के "मोबाइल" व्यूपोर्ट पर हो.
मोबाइल इंटरैक्टिव लेआउट और स्टैटिक डेस्कटॉप लेआउट के बीच स्विच करने के लिए, 540px
हमारा ब्रेकपॉइंट होगा.
सीएसएस :target
pseudo-class
एक <a>
लिंक, यूआरएल हैश को #sidenav-open
पर और दूसरे को खाली (''
) पर सेट करता है.
आखिर में, हैश से मैच करने के लिए एलिमेंट में id
होता है:
<a href="#sidenav-open" id="sidenav-button" title="Open Menu" aria-label="Open Menu">
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<aside id="sidenav-open">
…
</aside>
इनमें से हर लिंक पर क्लिक करने से हमारे पेज के यूआरएल की हैश स्थिति बदल जाती है, फिर एक pseudo-class जैसे कि साइडनेव को दिखाया और छिपाया जाता है:
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
}
#sidenav-open:target {
visibility: visible;
}
}
सीएसएस ग्रिड
पहले, मैं सिर्फ़ ऐब्सलूट या फ़िक्स्ड पोज़िशन
साइडनव लेआउट और कॉम्पोनेंट का इस्तेमाल करता था. हालांकि, ग्रिड के grid-area
सिंटैक्स की मदद से हम एक ही पंक्ति या कॉलम के लिए कई एलिमेंट असाइन कर सकते हैं.
स्टैक
मुख्य लेआउट एलिमेंट #sidenav-container
एक ग्रिड है, जो एक पंक्ति और दो कॉलम बनाता है. हर कॉलम का नाम stack
है. जगह की कमी होने पर सीएसएस, <main>
एलिमेंट के सभी बच्चों को एक ही ग्रिड नाम असाइन करता है. इस तरह, सभी एलिमेंट को एक ही स्पेस में रखा जाता है और एक स्टैक बन जाता है.
#sidenav-container {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
min-height: 100vh;
}
@media (max-width: 540px) {
#sidenav-container > * {
grid-area: stack;
}
}
मेन्यू का बैकड्रॉप
<aside>
ऐनिमेशन वाला ऐसा एलिमेंट है जिसमें साइड नेविगेशन मौजूद होता है. इसमें
2 बच्चे हैं: नेविगेशन कंटेनर <nav>
जिसका नाम [nav]
है और एक बैकग्राउंड <a>
है जिसका नाम [escape]
है. इसका इस्तेमाल मेन्यू को बंद करने के लिए किया जाता है.
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
2fr
और 1fr
को अडजस्ट करके, मेन्यू ओवरले और इसके नेगेटिव स्पेस को बंद करने वाले बटन के लिए पसंदीदा अनुपात चुनें.
सीएसएस 3D में बदलाव और ट्रांज़िशन
हमारा लेआउट अब मोबाइल व्यूपोर्ट साइज़ के हिसाब से स्टैक किया गया है. जब तक में कुछ नई स्टाइल नहीं जोड़ी जातीं, तब तक वे डिफ़ॉल्ट रूप से हमारे लेख को ओवरले कर रही हैं. अगले सेक्शन में, यहां कुछ UX के बारे में बताया गया है, जिसकी जानकारी मुझे चाहिए:
- खुला और बंद ऐनिमेट करें
- मोशन के साथ ऐनिमेशन को सिर्फ़ तब ही ऐनिमेट करें, जब उपयोगकर्ता इससे सहमत हो
visibility
को ऐनिमेट करें, ताकि कीबोर्ड फ़ोकस, ऑफ़स्क्रीन एलिमेंट पर न जा सके
मोशन ऐनिमेशन का इस्तेमाल शुरू करते समय, मुझे सुलभता सुविधाओं के बारे में सबसे पहले जानना है.
व्हीलचेयर लाने और ले जाने की सुविधा
हर कोई स्लाइड आउट मोशन अनुभव नहीं चाहता. हमारे समाधान में, यह प्राथमिकता
मीडिया क्वेरी में --duration
सीएसएस वैरिएबल को अडजस्ट करके लागू की जाती है. यह मीडिया क्वेरी मान, मोशन के लिए उपयोगकर्ता की ऑपरेटिंग सिस्टम की प्राथमिकता (अगर उपलब्ध हो) दिखाता है.
#sidenav-open {
--duration: .6s;
}
@media (prefers-reduced-motion: reduce) {
#sidenav-open {
--duration: 1ms;
}
}
अब जब साइडनेव स्लाइड को खोलकर बंद किया जा रहा है, तब अगर उपयोगकर्ता को मोशन इफ़ेक्ट को कम करना पसंद है, तो मैंने एलिमेंट को तुरंत अपने व्यू में ले जाया है, ताकि कोई भी हलचल न हो.
ट्रांज़िशन, ट्रांसफ़ॉर्म, अनुवाद
साइडेनव आउट (डिफ़ॉल्ट)
मोबाइल पर साइडनेव की डिफ़ॉल्ट स्थिति को ऑफ़स्क्रीन स्थिति पर सेट करने के लिए,
मैं एलिमेंट को transform: translateX(-110vw)
पर सेट करती हूँ.
ध्यान दें, मैंने -100vw
के सामान्य ऑफ़स्क्रीन कोड में एक और 10vw
जोड़ा है, ताकि यह पक्का किया जा सके कि साइडनेव का box-shadow
, छिपे होने पर मुख्य व्यूपोर्ट में न दिखे.
@media (max-width: 540px) {
#sidenav-open {
visibility: hidden;
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
}
}
साइडनेव इन
जब #sidenav
एलिमेंट, :target
के तौर पर मैच हो, तो translateX()
की पोज़िशन को होमबेस 0
पर सेट करें. साथ ही, जब यूआरएल हैश बदला जाए, तो सीएसएस एलिमेंट को उसकी -110vw
से बाहर की पोज़िशन से, var(--duration)
के बजाय 0
की "इन" पर स्लाइड करें.
@media (max-width: 540px) {
#sidenav-open:target {
visibility: visible;
transform: translateX(0);
transition:
transform var(--duration) var(--easeOutExpo);
}
}
ट्रांज़िशन किसको दिखे
अब हमारा लक्ष्य स्क्रीन रीडर के बाहर होने पर उन्हें छिपाना है,
ताकि सिस्टम ऑफ़स्क्रीन मेन्यू पर फ़ोकस न करें. :target
में बदलाव होने पर, 'किसको दिखे' ट्रांज़िशन सेट करके ऐसा किया जा सकता है.
- अंदर जाते समय, विज़िबिलिटी को ट्रांसफ़र न करें. यह तुरंत दिख जाएगा, ताकि मैं एलिमेंट को स्लाइड करके फ़ोकस को स्वीकार कर सकूं.
- बाहर जाते समय, ट्रांज़िशन के दिखने पर रोक लगाएं, लेकिन थोड़ा इंतज़ार करें. इसलिए, ट्रांज़िशन खत्म होने के बाद, यह
hidden
पर फ़्लिप हो जाएगा.
सुलभता के लिए UX को बेहतर बनाया गया
लिंक
इस समाधान के लिए, यूआरएल में बदलाव किया जाता है, ताकि राज्य को मैनेज किया जा सके.
ज़ाहिर है कि यहां <a>
एलिमेंट का इस्तेमाल किया जाना चाहिए और इसे कुछ अच्छी सुलभता सुविधाएं बिना किसी शुल्क के मिलती हैं. आइए, हमारे इंटरैक्टिव एलिमेंट को उन लेबल से सजाएं जो साफ़ तौर पर, मैसेज दिखाने वाले हैं.
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
<svg>...</svg>
</a>
अब हमारे प्राइमरी इंटरैक्शन वाले बटन, माउस और कीबोर्ड, दोनों के लिए अपने इंटेंट के बारे में साफ़ तौर पर बताते हैं.
:is(:hover, :focus)
सीएसएस फ़ंक्शन वाले pseudo-selector से, हम अपनी होवर स्टाइल को फ़ोकस के साथ शेयर करके तेज़ी से उनमें शामिल हो पाते हैं.
.hamburger:is(:hover, :focus) svg > line {
stroke: hsl(var(--brandHSL));
}
JavaScript पर स्प्रिंकल करें
बंद करने के लिए escape
दबाएं
क्या आपके कीबोर्ड पर मौजूद Escape
बटन से, मेन्यू को बंद करना चाहिए? चलिए, इसे शुरू करते हैं.
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', event => {
if (event.code === 'Escape') document.location.hash = '';
});
ब्राउज़र इतिहास
ओपन और क्लोज़ इंटरैक्शन को ब्राउज़र इतिहास में एक से ज़्यादा एंट्री स्टैक होने से रोकने के लिए, 'बंद करें' बटन में यहां दिया गया JavaScript इनलाइन जोड़ें:
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu" onchange="history.go(-1)"></a>
ऐसा करने से यूआरएल इतिहास की एंट्री बंद हो जाएगी, जिससे ऐसा लगेगा जैसे मेन्यू कभी खोला ही नहीं गया था.
उपयोगकर्ता अनुभव पर फ़ोकस करें
अगला स्निपेट, खुलने या बंद होने के बाद, खुले और बंद होने वाले बटन पर फ़ोकस करने में हमारी मदद करता है. मैं टॉगल करना आसान बनाना चाहता हूँ.
sidenav.addEventListener('transitionend', e => {
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? document.querySelector('#sidenav-close').focus()
: document.querySelector('#sidenav-button').focus();
})
साइडनेव खुलने पर, 'बंद करें' बटन पर फ़ोकस करें. साइडनेव बंद हो जाने पर,
खोलें बटन पर फ़ोकस करें. मैं JavaScript में एलिमेंट पर focus()
को कॉल करके ऐसा करता/करती हूं.
नतीजा
अब जब आपको पता है कि मैंने इसे कैसे किया, तो कैसे करेंगे?! यह कुछ मज़ेदार कॉम्पोनेंट आर्किटेक्चर बनाता है! स्लॉट के साथ पहला वर्शन कौन बनाएगा? 🙂
आइए, अलग-अलग तरह के काम करते हैं और वेब पर काम करने के सभी तरीके सीखते हैं. कोई ग्लिच बनाएं, अपना वर्शन मुझे ट्वीट करें. इसके बाद, हम इसे नीचे दिए कम्यूनिटी रीमिक्स सेक्शन में जोड़ देंगे.
कम्यूनिटी रीमिक्स
- कस्टम एलिमेंट के साथ @_devit: डेमो और कोड
- एचटीएमएल/सीएसएस/JS के साथ @maineedwin1: डेमो और कोड
- Glitch रीमिक्स के साथ @a_nurella: डेमो और कोड
- एचटीएमएल/सीएसएस/जेएस के साथ @EvroMalarkey: डेमो और कोड