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

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

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

#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 एलिमेंट, :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 पर स्विच हो जाए.

सुलभता से जुड़े यूज़र एक्सपीरियंस को बेहतर बनाना

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

Sprinkle on 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>

ऐसा करने पर, मेन्यू बंद होने पर यूआरएल के इतिहास की एंट्री हट जाएगी. इससे ऐसा लगेगा कि मेन्यू कभी भी नहीं खोला गया था.

Focus UX

अगले स्निपेट से, हमें यह पता चलता है कि स्क्रीन खुलने या बंद होने के बाद, खोलने और बंद करने वाले बटन पर फ़ोकस कैसे किया जाता है. मुझे टॉगल करने की सुविधा को आसान बनाना है.

sidenav.addEventListener('transitionend', e => {
  const isOpen = document.location.hash === '#sidenav-open';

  isOpen
      ? document.querySelector('#sidenav-close').focus()
      : document.querySelector('#sidenav-button').focus();
})

साइडनेवि खोलने पर, बंद करने के बटन पर फ़ोकस करें. साइडनेव बंद होने पर, 'खोलें' बटन पर फ़ोकस करें. मैं ऐसा JavaScript में एलिमेंट पर focus() कॉल करके करता/करती हूं.

नतीजा

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

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

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