मीडिया स्क्रोलर कॉम्पोनेंट बनाना

टीवी, फ़ोन, डेस्कटॉप वगैरह के लिए, रिस्पॉन्सिव हॉरिज़ॉन्टल स्क्रोल व्यू बनाने का बुनियादी तरीका.

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

डेमो

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

खास जानकारी

हम एक हॉरिज़ॉन्टल स्क्रोल लेआउट बना रहे हैं. इसका मकसद, मीडिया या प्रॉडक्ट के थंबनेल होस्ट करना है. यह कॉम्पोनेंट, एक साधारण <ul> सूची के तौर पर शुरू होता है. हालांकि, सीएसएस की मदद से इसे बेहतर और आसानी से स्क्रोल किए जा सकने वाले कॉम्पोनेंट में बदल दिया जाता है. इसमें इमेज दिखाई जाती हैं और उन्हें ग्रिड में स्नैप किया जाता है. JavaScript को रोविंग-इंडेक्स इंटरैक्शन को आसान बनाने के लिए जोड़ा गया है. इससे कीबोर्ड का इस्तेमाल करने वाले लोग, 100 से ज़्यादा आइटम को स्किप कर सकते हैं. साथ ही, मीडिया स्क्रोलर को हलके टाइटल स्क्रोलर में बदलने के लिए, एक्सपेरिमेंट वाली मीडिया क्वेरी prefers-reduced-data का इस्तेमाल किया जाता है.

सुलभ मार्कअप से शुरू करना

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

<ul> एलिमेंट वाली सूची डिलीवर करने के लिए:

<ul class="horizontal-media-scroller">
  <li></li>
  <li></li>
  <li></li>
  ...
<ul>

<a> एलिमेंट की मदद से, सूची के आइटम इंटरैक्टिव बनाएं:

<li>
  <a href="#">
    ...
  </a>
</li>

किसी इमेज और उसके कैप्शन को सिमेंटिक तरीके से दिखाने के लिए, <figure> एलिमेंट का इस्तेमाल करें:

<figure>
  <picture>
    <img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
  </picture>
  <figcaption>Legends</figcaption>
</figure>

<img> पर alt और loading एट्रिब्यूट देखें. मीडिया स्क्रोलर के लिए वैकल्पिक टेक्स्ट, यूज़र एक्सपीरियंस (यूएक्स) को बेहतर बनाने का एक मौका है. इससे थंबनेल के बारे में ज़्यादा जानकारी मिलती है. इसके अलावा, अगर इमेज लोड नहीं होती है, तो वैकल्पिक टेक्स्ट फ़ॉलबैक टेक्स्ट के तौर पर काम करता है. साथ ही, यह स्क्रीन रीडर जैसी सहायक तकनीक का इस्तेमाल करने वाले उपयोगकर्ताओं के लिए बोला गया यूज़र इंटरफ़ेस (यूआई) उपलब्ध कराता है. अनुपालन करने वाले वैकल्पिक टेक्स्ट के लिए पांच बुनियादी नियम के बारे में ज़्यादा जानें.

loading एट्रिब्यूट में lazy कीवर्ड का इस्तेमाल किया जा सकता है. इससे यह पता चलता है कि इमेज सोर्स को सिर्फ़ तब फ़ेच किया जाना चाहिए, जब इमेज व्यूपोर्ट में हो. यह बड़ी सूचियों के लिए काफ़ी अच्छा हो सकता है, क्योंकि उपयोगकर्ता सिर्फ़ उन आइटम की इमेज डाउनलोड करेंगे जिन्हें उन्होंने स्क्रोल करके देखा है.

उपयोगकर्ता की कलर स्कीम की प्राथमिकता के हिसाब से काम करना

color-scheme को <meta> टैग के तौर पर इस्तेमाल करें, ताकि ब्राउज़र को यह सिग्नल दिया जा सके कि आपके पेज पर, उपयोगकर्ता-एजेंट के लाइट और डार्क, दोनों स्टाइल उपलब्ध कराने हैं. यह एक मुफ़्त डार्क मोड या लाइट मोड है. यह इस बात पर निर्भर करता है कि आप इसे किस तरह देखते हैं:

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

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

थॉमस स्टाइनर से ज़्यादा जानें. इसके लिए, https://web.dev/color-scheme/ पर जाएं.

कॉन्टेंट जोड़ें

ul > li > a > figure > picture > img के ऊपर दिए गए कॉन्टेंट स्ट्रक्चर के हिसाब से, अगला काम स्क्रोल करने के लिए इमेज और टाइटल जोड़ना है. मैंने डेमो में स्टैटिक प्लेसहोल्डर इमेज और टेक्स्ट का इस्तेमाल किया है. हालांकि, इसे अपने पसंदीदा डेटा सोर्स से भी इस्तेमाल किया जा सकता है.

सीएसएस की मदद से स्टाइल जोड़ना

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

स्क्रोलर लेआउट बनाना

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

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

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

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
  margin: 0;
}

इसके बाद, <picture> एलिमेंट, बेस आसपेक्ट रेशियो बनाने के लिए कस्टम प्रॉपर्टी का इस्तेमाल करता है: बॉक्स:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

मीडिया स्क्रोलर को कुछ और छोटी-मोटी स्टाइल के साथ पूरा करें:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  & > li {
    display: inline-block; /* removes the list-item bullet */
  }

  & picture {
    inline-size: var(--size);
    block-size: var(--size);
  }
}

overflow सेटिंग, <ul> को सेट अप करती है, ताकि उसकी सूची में स्क्रोल किया जा सके और कीबोर्ड से नेविगेट किया जा सके. इसके बाद, हर डायरेक्ट चाइल्ड <li> एलिमेंट से ::marker हटा दिया जाता है. इसके लिए, inline-block का नया डिसप्ले टाइप मिलता है.

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

img {
  /* smash into whatever box it's in */
  inline-size: 100%;
  block-size: 100%;

  /* don't squish but do cover the space */
  object-fit: cover;

  /* soften the edges */
  border-radius: 1ex;
  overflow: hidden;

  /* if empty, show a gradient placeholder */
  background-image:
    linear-gradient(
      to bottom,
      hsl(0 0% 40%),
      hsl(0 0% 20%)
    );
}

स्क्रोल पैडिंग

पेज के कॉन्टेंट के साथ अलाइनमेंट और किनारे से किनारे तक स्क्रोल करने की सुविधा, एक बेहतर और कम कॉम्पोनेंट के लिए ज़रूरी है.

हमारे टाइपोग्राफ़ी और लेआउट लाइनों के साथ अलाइन होने वाले, किनारे से किनारे तक स्क्रोल करने वाले लेआउट को पूरा करने के लिए, scroll-padding से मैच करने वाले padding का इस्तेमाल करें:

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}

हॉरिज़ॉन्टल स्क्रोल पैडिंग की गड़बड़ी को ठीक करना ऊपर दिए गए उदाहरण से पता चलता है कि स्क्रोल कंटेनर को पैड करना कितना आसान है. हालांकि, इसमें काम करने से जुड़ी समस्याएं हैं. हालांकि, Chromium 91 और उसके बाद के वर्शन में इसे ठीक कर दिया गया है! इस बारे में ज़्यादा जानने के लिए, यहां जाएं. हालांकि, इसका लब्बोलुआब यह है कि स्क्रोल व्यू में पैडिंग का हमेशा ध्यान नहीं रखा जाता था.

आखिरी सूची आइटम के इनलाइन-एंड साइड पर एक बॉक्स हाइलाइट किया गया है. इससे पता चलता है कि पैडिंग और एलिमेंट की चौड़ाई एक जैसी है, ताकि मनमुताबिक अलाइनमेंट बनाया जा सके.

ब्राउज़र को स्क्रोलर के आखिर में पैडिंग डालने के लिए, मैं हर सूची में आखिरी आंकड़े को टारगेट करूंगा और एक स्यूडो एलिमेंट जोड़ूंगा, जो पैडिंग की ज़रूरत के हिसाब से होगा.

.horizontal-media-scroller > li:last-of-type figure {
  position: relative;

  &::after {
    content: "";
    position: absolute;

    inline-size: var(--gap);
    block-size: 100%;

    inset-block-start: 0;
    inset-inline-end: calc(var(--gap) * -1);
  }
}

लॉजिकल प्रॉपर्टी का इस्तेमाल करने से, मीडिया स्क्रोलर किसी भी लेखन मोड और दस्तावेज़ की दिशा में काम कर सकता है.

स्क्रोल स्नैपिंग

ओवरफ़्लो वाला स्क्रोलिंग कंटेनर, सीएसएस की एक लाइन की मदद से स्नैपिंग व्यूपोर्ट बन सकता है. इसके बाद, यह बच्चों पर निर्भर करता है कि वे उस व्यूपोर्ट के साथ कैसे अलाइन करना चाहते हैं.

.horizontal-media-scroller {
  --size: 150px;

  display: grid;
  grid-auto-flow: column;
  gap: calc(var(--gap) / 2);
  margin: 0;

  overflow-x: auto;
  overscroll-behavior-inline: contain;

  padding-inline: var(--gap);
  scroll-padding-inline: var(--gap);
  padding-block-end: calc(var(--gap) / 2);

  scroll-snap-type: inline mandatory;

  & figure {
    scroll-snap-align: start;
  }
}

फ़ोकस

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

.horizontal-media-scroller a {
  outline-offset: 12px;

  &:focus {
    outline-offset: 7px;
  }

  @media (prefers-reduced-motion: no-preference) {
    & {
      transition: outline-offset .25s ease;
    }
  }
}

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

रोविंग इंडेक्स

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

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

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

import {rovingIndex} from 'roving-ux';

rovingIndex({
  element: someElement
});

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

document.querySelectorAll('.horizontal-media-scroller')
  .forEach(scroller =>
    rovingIndex({
      element: scroller,
      target: 'a',
}))

इस इफ़ेक्ट के बारे में ज़्यादा जानने के लिए, ओपन सोर्स लाइब्रेरी roving-ux देखें.

आसपेक्ट-रेशियो

इस पोस्ट को लिखने के समय, Firefox में aspect-ratio के लिए सहायता, फ़्लैग के पीछे है. हालांकि, यह सुविधा Chromium ब्राउज़र या सेट-टॉप बॉक्स में उपलब्ध है. मीडिया स्क्रोलर ग्रिड लेआउट में सिर्फ़ दिशा और स्पेसिंग की जानकारी दी जाती है. इसलिए, मीडिया क्वेरी में साइज़ बदल सकता है. यह क्वेरी, आसपेक्ट रेशियो के साथ काम करने की सुविधा की जांच करती है. कुछ और डाइनैमिक मीडिया स्क्रोलर में प्रगतिशील बेहतर बनाने की सुविधा.

16:9 और 4:3 के आसपेक्ट रेशियो वाले डिज़ाइन के बगल में, 4:4 आसपेक्ट रेशियो वाला बॉक्स दिखाया गया है

@supports (aspect-ratio: 1) {
  .horizontal-media-scroller figure > picture {
    inline-size: auto; /* for a block-size driven ratio */
    aspect-ratio: 1; /* boxes by default */

    @nest section:nth-child(2) & {
      aspect-ratio: 16/9;
    }

    @nest section:nth-child(3) & {
      /* double the size of the others */
      block-size: calc(var(--size) * 2);
      aspect-ratio: 4/3;

      /* adjust size to fit more items into the viewport */
      @media (width <= 480px) {
        block-size: calc(var(--size) * 1.5);
      }
    }
  }
}

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

इस सीएसएस की मदद से, आसानी से मैनेज किया जा सकने वाला, लेकिन विज़ुअल तौर पर ज़्यादा आकर्षक लेआउट रेंडर होगा. ऐसा इसलिए, क्योंकि यह सुविधा ज़्यादा ब्राउज़र इंजन में उपलब्ध है.

कम डेटा का इस्तेमाल करना

यह अगली तकनीक, Canary में सिर्फ़ फ़्लैग के पीछे उपलब्ध है. हालांकि, हम आपको बताना चाहते हैं कि सीएसएस की कुछ लाइनों की मदद से, पेज लोड होने में लगने वाले समय और डेटा के इस्तेमाल को कैसे कम किया जा सकता है. prefers-reduced-data मीडिया क्वेरी की मदद से, लेवल 5 से यह पता लगाया जा सकता है कि डिवाइस, डेटा सेवर मोड जैसी किसी ऐसी स्थिति में है या नहीं जिसमें कम डेटा का इस्तेमाल किया जा रहा है. अगर ऐसा है, तो मैं दस्तावेज़ में बदलाव कर सकता/सकती हूं. इस मामले में, इमेज छिपाई जा सकती हैं.

ALT_TEXT_HERE

figure {
  @media (prefers-reduced-data: reduce) {
    & {
      min-inline-size: var(--size);

      & > picture {
        display: none;
      }
    }
  }
}

कॉन्टेंट अब भी नेविगेट किया जा सकता है. हालांकि, इसके लिए बड़ी इमेज डाउनलोड करने की ज़रूरत नहीं होती. prefers-reduced-data सीएसएस जोड़ने से पहले, साइट की इमेज यहां दी गई है:

(सात अनुरोध, 131 मिलीसेकंड में 100 केबी के संसाधन)

ALT_TEXT_HERE

prefers-reduced-data CSS जोड़ने के बाद, साइट की परफ़ॉर्मेंस यहां दी गई है:

ALT_TEXT_HERE

(71 अनुरोध, 1.07 सेकंड में 1.2 एमबी के संसाधन)

64 अनुरोध कम किए गए. इसका मतलब है कि इस ब्राउज़र टैब के व्यूपोर्ट में ~60 इमेज होंगी. ये टेस्ट, वाइड स्क्रीन डिसप्ले पर किए गए हैं. साथ ही, पेज लोड होने में ~80% की बढ़ोतरी हुई है और 10% डेटा तार से भेजा गया है. काफ़ी असरदार सीएसएस.

नतीजा

अब आपको पता है कि मैंने इसे कैसे किया, तो आप इसे कैसे करेंगे?! 🙂

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

सोर्स

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

अभी यहां देखने के लिए कुछ नहीं है!