ब्रेडक्रंब कॉम्पोनेंट बनाना

उपयोगकर्ताओं के लिए, आपकी साइट पर नेविगेट करने में मदद करने वाला रिस्पॉन्सिव और ऐक्सेस किया जा सकने वाला ब्रेडक्रंब कॉम्पोनेंट बनाने के बारे में बुनियादी जानकारी.

इस पोस्ट में, मुझे ब्रेडक्रंब कॉम्पोनेंट बनाने के तरीके के बारे में अपनी राय शेयर करनी है. डेमो आज़माएं.

डेमो

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

खास जानकारी

ब्रेडक्रंब कॉम्पोनेंट से पता चलता है कि साइट के पेजों के क्रम में उपयोगकर्ता किस जगह है. इसका नाम हंसल और ग्रेटेल की कहानी से लिया गया है. इस कहानी में, हंसल और ग्रेटेल ने जंगल में अपने पीछे ब्रेडक्रंब गिराए थे. इससे उन्हें वापस घर जाने का रास्ता मिल गया था.

इस पोस्ट में मौजूद ब्रेडक्रंब, स्टैंडर्ड ब्रेडक्रंब नहीं हैं. ये ब्रेडक्रंब की तरह दिखते हैं. ये <select> के साथ नेविगेशन में सिबलिंग पेजों को सीधे तौर पर रखकर, अतिरिक्त सुविधाएं देते हैं. इससे कई लेवल का ऐक्सेस मुमकिन हो पाता है.

बैकग्राउंड यूज़र एक्सपीरियंस

ऊपर दिए गए कॉम्पोनेंट के डेमो वीडियो में, प्लेसहोल्डर कैटगरी वीडियो गेम के जॉनर हैं. यह ट्रेल, नीचे दिखाए गए तरीके से home » rpg » indie » on sale पर जाकर बनाई जाती है.

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

इन्फ़ॉर्मेशन आर्किटेक्चर

संग्रहों और आइटम के हिसाब से सोचने पर, मुझे यह ज़्यादा मददगार लगता है.

कलेक्शन

कलेक्शन, चुनने के लिए उपलब्ध विकल्पों का एक कलेक्शन होता है. इस पोस्ट के ब्रेडक्रंब प्रोटोटाइप के होम पेज पर, कलेक्शन के नाम FPS, RPG, brawler, dungeon crawler, sports, और puzzle हैं.

आइटम

वीडियो गेम एक आइटम है. अगर कोई खास कलेक्शन किसी दूसरे कलेक्शन को दिखाता है, तो वह भी एक आइटम हो सकता है. उदाहरण के लिए, आरपीजी एक आइटम है और मान्य कलेक्शन है. अगर यह कोई आइटम है, तो उपयोगकर्ता को उस कलेक्शन पेज पर ले जाया जाता है. उदाहरण के लिए, वे आरपीजी पेज पर हैं. इस पेज पर आरपीजी गेम की सूची दिखती है. इसमें AAA, Indie, और Self Published जैसी अतिरिक्त उप-कैटगरी शामिल हैं.

कंप्यूटर साइंस की भाषा में, यह ब्रेडक्रंब कॉम्पोनेंट एक मल्टीडाइमेंशनल ऐरे को दिखाता है:

const rawBreadcrumbData = {
  "FPS": {...},
  "RPG": {
    "AAA": {...},
    "indie": {
      "new": {...},
      "on sale": {...},
      "under 5": {...},
    },
    "self published": {...},
  },
  "brawler": {...},
  "dungeon crawler": {...},
  "sports": {...},
  "puzzle": {...},
}

आपके ऐप्लिकेशन या वेबसाइट में कस्टम इन्फ़ॉर्मेशन आर्किटेक्चर (आईए) होगा, जिससे एक अलग मल्टीडाइमेंशनल ऐरे बनेगा. हालांकि, हमें उम्मीद है कि कलेक्शन लैंडिंग पेजों और हैरारकी ट्रैवर्सल का कॉन्सेप्ट, आपके ब्रेडक्रंब में भी शामिल किया जा सकता है.

लेआउट

मार्कअप

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

गहरे और हल्के रंग वाली स्कीम

<meta name="color-scheme" content="dark light">

ऊपर दिए गए स्निपेट में मौजूद color-scheme मेटा टैग, ब्राउज़र को बताता है कि इस पेज को ब्राउज़र के लाइट और डार्क स्टाइल चाहिए. उदाहरण के तौर पर दिए गए ब्रेडक्रंब में, इन कलर स्कीम के लिए कोई सीएसएस शामिल नहीं है. इसलिए, ब्रेडक्रंब में ब्राउज़र की ओर से दिए गए डिफ़ॉल्ट रंगों का इस्तेमाल किया जाएगा.

<nav class="breadcrumbs" role="navigation"></nav>

साइट पर नेविगेट करने के लिए, <nav> एलिमेंट का इस्तेमाल करना सही है. इसमें ARIA की नेविगेशन की भूमिका होती है. जांच के दौरान, मुझे पता चला कि role एट्रिब्यूट की वजह से, स्क्रीन रीडर एलिमेंट के साथ अलग तरीके से इंटरैक्ट कर रहा था. इसे नेविगेशन के तौर पर दिखाया जा रहा था. इसलिए, मैंने इसे जोड़ने का फ़ैसला किया है.

आइकॉन

जब किसी पेज पर कोई आइकॉन बार-बार दिखता है, तो SVG <use> एलिमेंट का मतलब है कि path को एक बार तय किया जा सकता है. इसके बाद, आइकॉन के सभी इंस्टेंस के लिए इसका इस्तेमाल किया जा सकता है. इससे एक ही पाथ की जानकारी को बार-बार दोहराने से रोका जाता है. इससे बड़े दस्तावेज़ और पाथ में अंतर होने की संभावना कम हो जाती है.

इस तकनीक का इस्तेमाल करने के लिए, पेज में एक छिपा हुआ SVG एलिमेंट जोड़ें. साथ ही, आइकॉन को यूनीक आईडी वाले <symbol> एलिमेंट में रैप करें:

<svg style="display: none;">

  <symbol id="icon-home">
    <title>A home icon</title>
    <path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
  </symbol>

  <symbol id="icon-dropdown-arrow">
    <title>A down arrow</title>
    <path d="M19 9l-7 7-7-7"/>
  </symbol>

</svg>

ब्राउज़र, SVG एचटीएमएल को पढ़ता है और आइकॉन की जानकारी को मेमोरी में सेव करता है. इसके बाद, वह पेज के बाकी हिस्से को प्रोसेस करता है. इसमें आइकॉन के आईडी का रेफ़रंस दिया जाता है, ताकि आइकॉन का इस्तेमाल अन्य जगहों पर भी किया जा सके. जैसे:

<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
  <use href="#icon-home" />
</svg>

<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
  <use href="#icon-dropdown-arrow" />
</svg>

DevTools में, रेंडर किया गया SVG इस्तेमाल करने वाला एलिमेंट दिखाया गया है.

इसे एक बार तय करें और जितनी बार चाहें उतनी बार इस्तेमाल करें. इससे पेज की परफ़ॉर्मेंस पर कम से कम असर पड़ता है. साथ ही, इसे अपनी ज़रूरत के हिसाब से स्टाइल किया जा सकता है. सूचना aria-hidden="true" को SVG एलिमेंट में जोड़ा जाता है. जो लोग सिर्फ़ कॉन्टेंट सुनते हैं उनके लिए ये आइकॉन काम के नहीं होते. इसलिए, इन आइकॉन को ऐसे लोगों से छिपाने पर, उन्हें बिना वजह की आवाज़ें नहीं सुनाई देंगी.

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

<span class="crumb">
  <a href="#sub-collection-b">Category B</a>
  <span class="crumbicon">
    <svg>...</svg>
    <select class="disguised-select" title="Navigate to another category">
      <option>Category A</option>
      <option selected>Category B</option>
      <option>Category C</option>
    </select>
  </span>
</span>

लिंक और कुछ विकल्प खास नहीं होते, लेकिन ये सामान्य ब्रेडक्रंब में ज़्यादा सुविधाएं जोड़ते हैं. <select> एलिमेंट में title जोड़ने से, स्क्रीन रीडर इस्तेमाल करने वाले लोगों को मदद मिलती है. इससे उन्हें बटन की कार्रवाई के बारे में जानकारी मिलती है. हालांकि, यह सुविधा अन्य लोगों के लिए भी उतनी ही मददगार है. आपको यह सुविधा iPad पर सबसे ऊपर और बीच में दिखेगी. एक एट्रिब्यूट, कई उपयोगकर्ताओं को बटन का कॉन्टेक्स्ट उपलब्ध कराता है.

इस स्क्रीनशॉट में, अदृश्य SELECT एलिमेंट पर कर्सर घुमाते हुए दिखाया गया है. साथ ही, इसके कॉन्टेक्स्ट के हिसाब से टूलटिप दिख रही है.

सेपरेटर डेकोरेशन

<span class="crumb-separator" aria-hidden="true">→</span>

सेपरेटर जोड़ना ज़रूरी नहीं है. सिर्फ़ एक सेपरेटर जोड़ने से भी अच्छा नतीजा मिलता है. इसके लिए, ऊपर दिए गए वीडियो में तीसरा उदाहरण देखें. इसके बाद, मैं हर aria-hidden="true" को यह भूमिका असाइन करता हूं, क्योंकि ये सजावटी हैं और स्क्रीन रीडर को इनके बारे में बताने की ज़रूरत नहीं है.

अगले सेक्शन में बताई गई gap प्रॉपर्टी की मदद से, इस स्पेसिंग को आसानी से सेट किया जा सकता है.

स्टाइल

कलर के लिए सिस्टम कलर का इस्तेमाल किया जाता है. इसलिए, स्टाइल के लिए ज़्यादातर गैप और स्टैक होते हैं!

लेआउट की दिशा और फ़्लो

DevTools में, ब्रेडक्रंब नेविगेशन का अलाइनमेंट दिखाया गया है. इसमें फ़्लेक्सबॉक्स ओवरले की सुविधा का इस्तेमाल किया गया है.

प्राइमरी नेविगेशन एलिमेंट nav.breadcrumbs, चाइल्ड एलिमेंट के लिए स्कोप की गई कस्टम प्रॉपर्टी सेट करता है. इसके अलावा, यह हॉरिज़ॉन्टल वर्टिकल अलाइनमेंट वाला लेआउट बनाता है. इससे यह पक्का होता है कि क्रमसूचक, डिवाइडर, और आइकॉन एक लाइन में हों.

.breadcrumbs {
  --nav-gap: 2ch;

  display: flex;
  align-items: center;
  gap: var(--nav-gap);
  padding: calc(var(--nav-gap) / 2);
}

एक ब्रेडक्रंब दिखाया गया है, जो फ़्लेक्सबॉक्स ओवरले के साथ वर्टिकल अलाइन किया गया है.

हर .crumb, कुछ अंतर के साथ वर्टिकल अलाइनमेंट वाला हॉरिज़ॉन्टल लेआउट भी बनाता है. हालांकि, यह खास तौर पर अपने लिंक चाइल्ड को टारगेट करता है और स्टाइल white-space: nowrap तय करता है. यह एक से ज़्यादा शब्दों वाले ब्रेडक्रंब के लिए ज़रूरी है, क्योंकि हम नहीं चाहते कि वे एक से ज़्यादा लाइन में दिखें. इस पोस्ट में आगे चलकर, हम इस white-space प्रॉपर्टी की वजह से होने वाले हॉरिज़ॉन्टल ओवरफ़्लो को मैनेज करने के लिए स्टाइल जोड़ेंगे.

.crumb {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--nav-gap) / 4);

  & > a {
    white-space: nowrap;

    &[aria-current="page"] {
      font-weight: bold;
    }
  }
}

aria-current="page" को इसलिए जोड़ा जाता है, ताकि मौजूदा पेज का लिंक बाकी लिंक से अलग दिखे. इससे स्क्रीन रीडर का इस्तेमाल करने वाले लोगों को साफ़ तौर पर पता चलेगा कि यह लिंक मौजूदा पेज के लिए है. साथ ही, हमने इस एलिमेंट को इस तरह से स्टाइल किया है कि दृष्टिबाधित लोगों को भी ऐसा ही अनुभव मिल सके.

.crumbicon कॉम्पोनेंट, SVG आइकॉन को "लगभग अदृश्य" <select> एलिमेंट के साथ स्टैक करने के लिए, ग्रिड का इस्तेमाल करता है.

DevTools में ग्रिड लेआउट को दिखाया गया है. इसमें एक बटन पर ओवरले किया गया है. इस बटन की लाइन और कॉलम, दोनों को स्टैक कहा जाता है.

.crumbicon {
  --crumbicon-size: 3ch;

  display: grid;
  grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
  place-items: center;

  & > * {
    grid-area: stack;
  }
}

<select> एलिमेंट, डीओएम में सबसे आखिर में है. इसलिए, यह स्टैक में सबसे ऊपर है और इंटरैक्टिव है. opacity: .01 की स्टाइल जोड़ें, ताकि एलिमेंट का इस्तेमाल किया जा सके. साथ ही, नतीजा एक ऐसा बॉक्स हो जो आइकॉन के आकार के हिसाब से पूरी तरह फ़िट हो. यह <select> एलिमेंट के लुक को पसंद के मुताबिक बनाने का एक अच्छा तरीका है. इससे, एलिमेंट में पहले से मौजूद फ़ंक्शन पर कोई असर नहीं पड़ता.

.disguised-select {
  inline-size: 100%;
  block-size: 100%;
  opacity: .01;
  font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}

ओवरफ़्लो

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

.breadcrumbs {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: calc(var(--nav-gap) / 2);

  & > .crumb:last-of-type {
    scroll-snap-align: end;
  }

  @supports (-webkit-hyphens:none) { & {
    scroll-snap-type: none;
  }}
}

ओवरफ़्लो स्टाइल से, उपयोगकर्ता को यह अनुभव मिलता है:

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

मीडिया क्वेरी

छोटे व्यूपोर्ट के लिए, "होम" लेबल को छिपाया जा सकता है. इससे सिर्फ़ आइकॉन दिखेगा:

@media (width <= 480px) {
  .breadcrumbs .home-label {
    display: none;
  }
}

तुलना करने के लिए, होम लेबल वाले और होम लेबल के बिना ब्रेडक्रंब की अगल-बगल में इमेज.

सुलभता

मोशन

इस कॉम्पोनेंट में ज़्यादा मोशन नहीं है. हालांकि, ट्रांज़िशन को prefers-reduced-motion चेक में रैप करके, हम अनचाहे मोशन को रोक सकते हैं.

@media (prefers-reduced-motion: no-preference) {
  .crumbicon {
    transition: box-shadow .2s ease;
  }
}

अन्य स्टाइल में कोई बदलाव करने की ज़रूरत नहीं है. होवर और फ़ोकस इफ़ेक्ट, transition के बिना भी शानदार और काम के हैं. हालांकि, अगर मोशन ठीक है, तो हम इंटरैक्शन में एक छोटा सा ट्रांज़िशन जोड़ देंगे.

JavaScript

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

उपयोगकर्ता अनुभव को बेहतर बनाने के लिए, JavaScript की मदद से दो अहम मेज़रमेंट किए जाते हैं: select has changed और eager <select> change event firing prevention.

<select> एलिमेंट का इस्तेमाल करने की वजह से, ईगर इवेंट को रोकने की सुविधा ज़रूरी है. Windows Edge और शायद अन्य ब्राउज़र पर भी, उपयोगकर्ता के कीबोर्ड से विकल्पों को ब्राउज़ करने पर, select changed इवेंट ट्रिगर होता है. इसलिए, मैंने इसे ईगर कहा है, क्योंकि उपयोगकर्ता ने सिर्फ़ विकल्प को छद्म रूप से चुना है. जैसे, होवर करना या फ़ोकस करना. हालांकि, उसने enter या click से विकल्प की पुष्टि नहीं की है. ईगर इवेंट की वजह से, कॉम्पोनेंट की कैटगरी बदलने की सुविधा का इस्तेमाल नहीं किया जा सकता. ऐसा इसलिए, क्योंकि सेलेक्ट बॉक्स खोलने और किसी आइटम को ब्राउज़ करने पर, इवेंट ट्रिगर हो जाएगा और पेज बदल जाएगा. हालांकि, ऐसा उपयोगकर्ता के तैयार होने से पहले ही हो जाएगा.

<select> बदले गए इवेंट की बेहतर जानकारी

const crumbs = document.querySelectorAll('.breadcrumbs select')
const allowedKeys = new Set(['Tab', 'Enter', ' '])
const preventedKeys = new Set(['ArrowUp', 'ArrowDown'])

// watch crumbs for changes,
// ensures it's a full value change, not a user exploring options via keyboard
crumbs.forEach(nav => {
  let ignoreChange = false

  nav.addEventListener('change', e => {
    if (ignoreChange) return
    // it's actually changed!
  })

  nav.addEventListener('keydown', ({ key }) => {
    if (preventedKeys.has(key))
      ignoreChange = true
    else if (allowedKeys.has(key))
      ignoreChange = false
  })
})

इसके लिए, हर <select> एलिमेंट पर कीबोर्ड डाउन इवेंट पर नज़र रखी जाती है. साथ ही, यह तय किया जाता है कि दबाई गई कुंजी नेविगेशन की पुष्टि करने वाली कुंजी (Tab या Enter) थी या स्पेशल नेविगेशन वाली कुंजी (ArrowUp या ArrowDown). इससे कॉम्पोनेंट यह तय कर पाता है कि <select> एलिमेंट के लिए इवेंट फ़ायर होने पर, उसे इंतज़ार करना है या आगे बढ़ना है.

नतीजा

अब आपको पता चल गया है कि मैंने यह कैसे किया. अब आप कैसे करेंगे‽ 🙂

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

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