साइडनेव कॉम्पोनेंट बनाना

रिस्पॉन्सिव स्लाइड आउट साइडनेव बनाने के तरीके के बारे में बुनियादी जानकारी

इस पोस्ट में, मैं आपके साथ यह जानकारी शेयर करना चाहता हूं कि मैंने वेब के लिए एक Sidenav कॉम्पोनेंट का प्रोटोटाइप कैसे बनाया. यह कॉम्पोनेंट इन सुविधाओं के साथ काम करता है: रिस्पॉन्सिव, स्टेटफ़ुल, कीबोर्ड नेविगेशन की सुविधा, JavaScript के साथ और बिना JavaScript के काम करता है, और सभी ब्राउज़र पर काम करता है. डेमो आज़माएं.

अगर आपको वीडियो देखना ज़्यादा पसंद है, तो इस पोस्ट का YouTube वर्शन यहां दिया गया है:

खास जानकारी

रिस्पॉन्सिव नेविगेशन सिस्टम बनाना मुश्किल होता है. कुछ लोग कीबोर्ड का इस्तेमाल करेंगे, कुछ के पास पावरफ़ुल डेस्कटॉप होंगे, और कुछ लोग छोटे मोबाइल डिवाइस से विज़िट करेंगे. वेबसाइट पर आने वाले हर व्यक्ति के पास, मेन्यू को खोलने और बंद करने का विकल्प होना चाहिए.

डेस्कटॉप से मोबाइल पर रिस्पॉन्सिव लेआउट का डेमो
iOS और Android पर लाइट और डार्क थीम उपलब्ध नहीं है

वेब रणनीति

इस कॉम्पोनेंट एक्सप्लोरेशन में, मुझे वेब प्लैटफ़ॉर्म की कुछ अहम सुविधाओं को एक साथ इस्तेमाल करने का मौका मिला:

  1. सीएसएस :target
  2. सीएसएस ग्रिड
  3. सीएसएस ट्रांसफ़ॉर्म
  4. व्यू पोर्ट और उपयोगकर्ता की प्राथमिकताओं के लिए सीएसएस मीडिया क्वेरी
  5. focus उपयोगकर्ता अनुभव को बेहतर बनाने के लिए JS

मेरे समाधान में एक साइडबार है और यह सिर्फ़ तब टॉगल होता है, जब व्यूपोर्ट 540px या उससे कम का "मोबाइल" व्यूपोर्ट हो. 540px हमारा ब्रेकपॉइंट होगा. इससे मोबाइल के इंटरैक्टिव लेआउट और डेस्कटॉप के स्टैटिक लेआउट के बीच स्विच किया जा सकेगा.

सीएसएस :target सूडो-क्लास

एक <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>

इनमें से हर लिंक पर क्लिक करने से, हमारे पेज के यूआरएल का हैश स्टेटस बदल जाता है. इसके बाद, मैं सूडो-क्लास की मदद से साइडनेव को दिखाता और छिपाता हूं:

@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>, ऐनिमेशन वाला एलिमेंट है. इसमें साइड नेविगेशन शामिल होता है. इसमें दो चाइल्ड हैं: नेविगेशन कंटेनर <nav>, जिसका नाम [nav] है और बैकड्रॉप <a>, जिसका नाम [escape] है. इसका इस्तेमाल मेन्यू को बंद करने के लिए किया जाता है.

#sidenav-open {
  display: grid;
  grid-template-columns: [nav] 2fr [escape] 1fr;
}

मेन्यू ओवरले और उसके क्लोज़ बटन के लिए, अपनी पसंद का अनुपात ढूंढने के लिए 2fr और 1fr को अडजस्ट करें.

अनुपात बदलने पर क्या होता है, इसका डेमो.

सीएसएस 3D ट्रांसफ़ॉर्म और ट्रांज़िशन

अब हमारा लेआउट, मोबाइल व्यूपोर्ट के साइज़ पर स्टैक हो गया है. जब तक मैं कुछ नई स्टाइल नहीं जोड़ता, तब तक यह डिफ़ॉल्ट रूप से हमारे लेख पर ओवरले हो रहा है. इस अगले सेक्शन में, मुझे यह यूज़र एक्सपीरियंस देना है:

  • खुलने और बंद होने का ऐनिमेशन
  • अगर उपयोगकर्ता को मोशन से कोई समस्या नहीं है, तो ही ऐनिमेशन में मोशन का इस्तेमाल करें
  • 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 in

जब #sidenav एलिमेंट, :target से मेल खाता है, तब translateX() की पोज़िशन को होमबेस 0 पर सेट करें. इसके बाद, देखें कि यूआरएल हैश बदलने पर, सीएसएस #sidenav एलिमेंट को -110vw की पोज़िशन से 0 की "इन" पोज़िशन पर var(--duration) में कैसे स्लाइड करती है.

@media (max-width: 540px) {
  #sidenav-open:target {
    visibility: visible;
    transform: translateX(0);
    transition:
      transform var(--duration) var(--easeOutExpo);
  }
}

ट्रांज़िशन की विज़िबिलिटी

अब हमारा मकसद यह है कि जब मेन्यू स्क्रीन पर न हो, तो स्क्रीन रीडर से उसे छिपाया जाए. इससे सिस्टम, स्क्रीन पर मौजूद मेन्यू पर फ़ोकस नहीं करेंगे. इसके लिए, :target के बदलने पर, दिखने की स्थिति में बदलाव करने की सुविधा सेट की जाती है.

  • जब कोई एलिमेंट अंदर की ओर जाता है, तब उसकी विज़िबिलिटी में बदलाव न करें. उसे तुरंत दिखाएं, ताकि मैं एलिमेंट को स्लाइड इन होते हुए देख सकूँ और उस पर फ़ोकस कर सकूँ.
  • जब कोई एलिमेंट स्क्रीन से बाहर जा रहा हो, तब उसकी पारदर्शिता में बदलाव करें. हालांकि, ऐसा कुछ समय बाद करें, ताकि स्क्रीन से बाहर जाते समय वह hidden में बदल जाए.

सुलभता से जुड़े उपयोगकर्ता अनुभव को बेहतर बनाने के लिए किए गए सुधार

यह समाधान, यूआरएल में बदलाव करने पर निर्भर करता है, ताकि स्थिति को मैनेज किया जा सके. इसलिए, यहां <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)

यह सीएसएस फ़ंक्शनल सूडो-सिलेक्टर, हमें तेज़ी से समावेशी होने में मदद करता है. इसके लिए, हमें अपनी होवर स्टाइल को फ़ोकस के साथ शेयर करना होता है.

.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() को कॉल किया जाता है.

नतीजा

अब आपको पता चल गया है कि मैंने यह कैसे किया. अब आप इसे कैसे करेंगे?! इससे कॉम्पोनेंट आर्किटेक्चर को मज़ेदार बनाया जा सकता है! स्लॉट के साथ पहला वर्शन कौन बनाएगा? 🙂

आइए, हम अपने तरीकों में विविधता लाएं और वेब पर कॉन्टेंट बनाने के सभी तरीके जानें. एक Glitch बनाएँ, मुझे ट्वीट करें और मैं इसे नीचे मौजूद कम्यूनिटी रीमिक्स सेक्शन में जोड़ दूँगा.

कम्यूनिटी रीमिक्स