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

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

इस कॉम्पोनेंट को बनाने के लिए चुनी गई सीएसएस वेब प्लैटफ़ॉर्म की सुविधाओं के बारे में जानने के लिए, मेरी ब्लॉग पोस्ट Sidenav कॉम्पोनेंट बनाना देखें.

सेटअप

  1. प्रोजेक्ट में बदलाव करने के लिए, बदलाव करने के लिए रीमिक्स करें पर क्लिक करें.
  2. app/index.html खोलें.

एचटीएमएल

सबसे पहले, HTML सेटअप की ज़रूरी जानकारी हासिल कर लें, ताकि काम करने के लिए कॉन्टेंट और कुछ बॉक्स उपलब्ध रहें.

इस एचटीएमएल को <body> टैग में छोड़ें.

<aside></aside>
<main></main>

<aside> में नेविगेशन मेन्यू को <main> के लिए मुफ़्त एलिमेंट के तौर पर रखा जाता है. इसमें मुख्य पेज का कॉन्टेंट होता है.

इसके बाद, हम पेज के बाकी कॉन्टेंट के साथ उन सिमैंटिक एलिमेंट को भरेंगे.

<aside> एलिमेंट में नेविगेशन एलिमेंट, कुछ नेविगेशन लिंक, और बंद करने का लिंक जोड़ें.

<aside>
  <nav>
    <h4>My</h4>
    <a href="#">Dashboard</a>
    <a href="#">Profile</a>
    <a href="#">Preferences</a>
    <a href="#">Archive</a>

    <h4>Settings</h4>
    <a href="#">Accessibility</a>
    <a href="#">Theme</a>
    <a href="#">Admin</a>
  </nav>

  <a href="#"></a>
</aside>

लिंक, <nav> एलिमेंट में शानदार तरीके से दिखते हैं. साथ ही, <nav> एलिमेंट <aside> साइडबार में शानदार तरीके से दिखते हैं. फिर भी, हम इसे बेहतर बनाने के लिए और भी बहुत कुछ कर सकते हैं.

लेआउट कॉन्टेंट को शब्दों के हिसाब से बनाए रखने के लिए, मुख्य कॉन्टेंट एलिमेंट में एक हेडर और लेख जोड़ें.

<main>
  <header>
    <a href="#sidenav-open" class="hamburger">
      <svg viewBox="0 0 50 40">
        <line x1="0" x2="100%" y1="10%" y2="10%" />
        <line x1="0" x2="100%" y1="50%" y2="50%" />
        <line x1="0" x2="100%" y1="90%" y2="90%" />
      </svg>
    </a>
    <h1>Site Title</h1>
  </header>

  <article>
    {put some placeholder content here}
  </article>
</main>

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

<article> एलिमेंट में, हमने प्लेसहोल्डर वाला एक वाक्य चिपकाया. `` को अपनी चीज़ों से बदलें या यहां दिए गए lorem को चिपकाएं:

<h2>Totam Header</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum consectetur, necessitatibus velit officia ut impedit veritatis temporibus soluta? Totam odit cupiditate facilis nisi sunt hic necessitatibus voluptatem nihil doloribus! Enim.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>

<h3>Subhead Totam Odit</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>

<h3>Subhead</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>

इस कॉन्टेंट और इसकी लंबाई की वजह से, जब पेज आपके व्यूपोर्ट की ऊंचाई से ज़्यादा हो जाता है, तो पेज को स्क्रोल किया जा सकता है.

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

हेडर ओपन लिंक एलिमेंट में title और aria-label एट्रिब्यूट जोड़ें:

<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">

खुले हुए SVG आइकॉन को भी ज़्यादा साफ़ तौर पर मार्क किया जा सकता है. ओपन लिंक एलिमेंट के अंदर SVG में इन एट्रिब्यूट को जोड़ें:

<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">

साइडनेव में मौजूद क्लोज़ लिंक को ज़्यादा साफ़ तौर पर मार्क किया जा सकता है. साइडनेविगेशन बंद करें लिंक एलिमेंट में title और aria-label एट्रिब्यूट जोड़ें:

<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>

सीएसएस

एलिमेंट को लेआउट करने का समय. मुख्य कॉन्टेंट और साइडनेव, <body> टैग से सीधे तौर पर जुड़े हैं. इसलिए, इस तरह से शुरुआत करना बेहतर होगा.

नीचे दिए गए सीएसएस को css/sidenav.css में जोड़ें, ताकि <body> एलिमेंट चिल्ड्रेन दिखा सके.

body {
  display: grid;
  grid: [stack] 1fr / min-content [stack] 1fr;

  @media (max-width: 540px) {
    & > :matches(aside, main) {
      grid-area: stack;
    }
  }
}

इस लेआउट के हिसाब से यह ज़रूरी है: नाम वाली एक पंक्ति stack बनाएं, जिसमें मौजूद सारी जानकारी शामिल हो. साथ ही, उस पंक्ति में दो कॉलम बनाएं, जिनमें से दूसरे का नाम stack भी है. पहले कॉलम का साइज़, कॉन्टेंट की ज़रूरत के हिसाब से होना चाहिए और दूसरे कॉलम का साइज़, बाकी हिस्सों को ले सकता है. इसके बाद, अगर 540px या इससे कम व्यूपोर्ट के सीमित व्यूपोर्ट में हैं, तो साइडनेव और मुख्य कॉन्टेंट एलिमेंट को एक ही पंक्ति और कॉलम में रखें. इससे वे 1x1 ग्रिड में एक-दूसरे के ऊपर बने रहेंगे.

बेस के तौर पर, रिस्पॉन्सिव स्टैकिंग की इस सुविधा की मदद से, अब हम यूआरएल बार की स्थिति का इस्तेमाल करके, साइडनेव के दिखने और बदलने की स्टाइल को टॉगल कर सकते हैं.

app/index.html में <aside> एलिमेंट को वापस अपडेट करें:

<aside>
<aside id="sidenav-open">

इससे सीएसएस, किसी एलिमेंट और यूआरएल हैश का एक साथ मिलान कर पाती है. :target के इस्तेमाल के लिए यह ज़रूरी है. अब एलिमेंट का आईडी, <a> टैग की मदद से सेट किए जाने वाले यूआरएल हैश से मैच हो सकता है.

इसके अलावा, JavaScript को आसानी से टारगेट करने के लिए, साइडनेव को कंट्रोल करने वाले मुख्य एलिमेंट के लिए आईडी जोड़ें. सबसे पहले, साइडनेव खोलने के लिंक में एक आईडी जोड़ें:

<a href="#sidenav-open" class="hamburger" title="Open Menu" aria-label="Open Menu">
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">

इसके बाद, साइडनेव बंद करें लिंक में एक आईडी जोड़ें:

<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>

यह मैक्रो <body> रिस्पॉन्सिव स्टैकिंग लेआउट को पूरा करता है और हमें यूआरएल बार में बांध देता है. चलिए आगे बढ़ना जारी रखें!

<aside> का लेआउट भी शानदार है. इसमें 2 चिल्ड्रन हैं, एक <nav> है जो काग़ज़ जैसा दिखता है जिसे बाहर स्लाइड किया जाता है. साथ ही, बंद होने वाला <a> लिंक एलिमेंट जो यूआरएल को # पर सेट करता है. यह लिंक पेपर स्लाइड आउट नेविगेशन के दाईं ओर दिखाई नहीं देता है; ऐसा लगता है कि लोग विज़ुअल कॉम्पोनेंट को "बंद" करके उसे खारिज कर सकते हैं.

css/sidenav.css में यह सीएसएस जोड़ें:

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

मुझे लगा कि अनुपात और नाम इस जगह पर बहुत अच्छा काम करते हैं. यहां ग्रिड चमक सकती हैं और डिज़ाइनर को कई सारे नियंत्रण दे सकती हैं.

इसके बाद, मुझे मुख्य कॉन्टेंट को कुछ शर्तों के साथ ओवरले करना होगा और दस्तावेज़ पर स्क्रोल करते समय अपनी स्थिति को बरकरार रखना होगा. यह position: sticky और कुछ overscroll-behavior के लिए बहुत बढ़िया है.

साइडनेव के लिए ये स्टाइल जोड़ें:

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

  @media (max-width: 540px) {
    position: sticky;
    top: 0;
    max-height: 100vh;
    overflow: hidden auto;
    overscroll-behavior: contain;

    visibility: hidden; /* not keyboard accessible when closed */
  }
}

इन स्टाइल से यह पक्का होता है कि साइडनेव, व्यूपोर्ट की ऊंचाई के बराबर है, वर्टिकल तरीके से स्क्रोल किया जाता है, और इसमें स्क्रोल शामिल होता है. सबसे अहम बात, यह एलिमेंट को छिपा देता है. डिफ़ॉल्ट रूप से, जब व्यूपोर्ट 540px या छोटा हो, तो उस साइडनेव को छिपाएं. जब तक कि नहीं!

#sidenav-open एलिमेंट में :target का स्यूडो-सिलेक्टर जोड़ें:

#sidenav-open {

  @media (max-width: 540px) {

    &:target {
      visibility: visible;
    }
  }
}

जब उस एलिमेंट का आईडी और यूआरएल बार एक जैसा हो, तो visibility को visible पर सेट करें. पेज को स्क्रोल करने के बाद साइड मेन्यू खोलें या साइडनेव चालू होने पर पेज को स्क्रोल करने की कोशिश करें. आपकी क्या राय है?

app/sidenav.css के नीचे यह सीएसएस जोड़ें:

#sidenav-button,
#sidenav-close {
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  user-select: none;
  touch-action: manipulation;

  @media (min-width: 540px) {
    display: none;
  }
}

ये स्टाइल हमारे 'खुले और बंद करें' बटन को टारगेट करती हैं और उनकी टैप और टच करने की स्टाइल को तय करती हैं. साथ ही, व्यूपोर्ट के 540px या बड़े होने पर उन्हें छिपा देती हैं.

कुछ चीज़ों के लिए, आइए बेहतर सुलभता के साथ सीएसएस ट्रांसफ़ॉर्म को जोड़ें. css/sidenav.css में यह सीएसएस जोड़ें:

#sidenav-open {
  --easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
  --duration: .6s;

  ...

  @media (max-width: 540px) {
    ...

    transform: translateX(-110vw);
    will-change: transform;
    transition:
      transform var(--duration) var(--easeOutExpo),
      visibility 0s linear var(--duration);

    &:target {
      visibility: visible;
      transform: translateX(0);
      transition: transform var(--duration) var(--easeOutExpo);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    --duration: 1ms;
  }
}
`prefers-reduced-motion` मीडिया क्वेरी के आधार पर, लागू किए गए इंटरैक्शन का डेमो. इसकी अवधि भी नहीं होती.

कुछ JavaScript में स्प्रिंकल करें

Escape बटन से मेन्यू बंद हो जाना चाहिए. इस JS को js/index.js में जोड़ें:

const sidenav = document.querySelector('#sidenav-open');

sidenav.addEventListener('keyup', e => {
  if (e.code === 'Escape') {
    document.location.hash = '';
  }
});

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

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

js/index.js में यह JavaScript जोड़ें:

const closenav = document.querySelector('#sidenav-close');
const opennav = document.querySelector('#sidenav-button');

sidenav.addEventListener('transitionend', e => {
  if (e.propertyName !== 'transform') {
    return;
  }

  const isOpen = document.location.hash === '#sidenav-open';

  isOpen
    ? closenav.focus()
    : opennav.focus();
});

इसे आज़माएं

  • साइट की झलक देखने के लिए, ऐप्लिकेशन देखें दबाएं. इसके बाद, फ़ुलस्क्रीन फ़ुलस्क्रीन दबाएं.

नतीजा

कॉम्पोनेंट से जुड़ी मेरी ज़रूरतों के मुताबिक, यह पूरा हो गया. इसे बेझिझक बनाएं, यूआरएल के बजाय JavaScript की स्थिति का इस्तेमाल करके ड्राइव करें, और सामान्य तौर पर इसे अपना बनाएं! जोड़ने के लिए हमेशा कुछ न कुछ होता है या इस्तेमाल के ज़्यादा उदाहरण दिए जाते हैं.

इस कॉम्पोनेंट पर लागू की गई नॉन-लेआउट से जुड़ी स्टाइल देखने के लिए css/brandnav.css खोलें. मुझे नहीं लगा कि मैं जिस सुविधा सेट पर फ़ोकस कर रहा था उसके लिए यह ज़रूरी है और मुझे उम्मीद थी कि लेआउट से स्टाइल को अलग करने से कॉपी और चिपकाने को बढ़ावा मिलेगा. वहां आपके लिए और बहुत कुछ सीखा जा सकता है!

स्लाइड आउट रिस्पॉन्सिव साइडनेव कॉम्पोनेंट कैसे बनाए जाते हैं? क्या आपके पास कभी एक से ज़्यादा हैं, जैसे कि दोनों तरफ़ एक? मुझे आपका समाधान YouTube वीडियो में दिखाना अच्छा लगेगा. इसके लिए, मुझ पर ट्वीट करें या YouTube में अपने कोड के साथ टिप्पणी करें. इससे सभी को मदद मिलेगी!