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

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

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

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

खास जानकारी

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

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

वेब रणनीति

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

  1. सीएसएस :target
  2. सीएसएस ग्रिड
  3. सीएसएस transforms
  4. व्यूपोर्ट और उपयोगकर्ता की पसंद के लिए सीएसएस मीडिया क्वेरी
  5. focus UX को बेहतर बनाने के लिए 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>

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

@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 पर फ़्लिप हो जाए.

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

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

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

फ़ोकस 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() को कॉल करके ऐसा किया जाता है.

नतीजा

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

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

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