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

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

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

सेटअप

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

एचटीएमएल

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

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

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

<aside>, <main> के साथ नेविगेशन मेन्यू को एक अतिरिक्त एलिमेंट के तौर पर रखता है. <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> एलिमेंट में, प्लेसहोल्डर वाक्य चिपकाया है. `` को अपने कॉन्टेंट से बदलें या यहां दिया गया कॉन्टेंट चिपकाएं:

<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 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 ग्रिड में एक-दूसरे के ऊपर दिखेंगे.

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

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

<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> का लेआउट भी बेहतर है. इसमें दो चाइल्ड एलिमेंट हैं. पहला <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/index.js में यह 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 पर अपने कोड के साथ टिप्पणी करें. इससे सभी को मदद मिलेगी!