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

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

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

डेमो

अगर आप वीडियो पसंद करते हैं, तो यहां इस पोस्ट का 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 एट्रिब्यूट पर ध्यान दें. मीडिया स्क्रोलर के लिए वैकल्पिक टेक्स्ट, UX के लिए एक अवसर है. इससे थंबनेल को ज़्यादा जानकारी देने में मदद मिलती है. इसके अलावा, इमेज लोड न होने पर, फ़ॉलबैक टेक्स्ट के तौर पर भी इसका इस्तेमाल किया जा सकता है. इसके अलावा, यह स्क्रीन रीडर जैसी सहायक टेक्नोलॉजी पर निर्भर उपयोगकर्ताओं के लिए, बोलकर सुनाया जाने वाला यूज़र इंटरफ़ेस (यूआई) भी उपलब्ध कराता है. ज़रूरी नीतियों का पालन करने के लिए पांच गोल्डन नियमों के बारे में ज़्यादा जानें.

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

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

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

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

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

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

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

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

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

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

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

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

2
स्क्रोल की जा रही लाइनें, दिख रही हैं. एक में इलिप्सिस नहीं है, जिसका मतलब है कि वह लंबा है और हर शीर्षक को पूरी तरह पढ़ा जा सकता है. दूसरी छोटी और कई टाइटल
इलिप्सिस के साथ कटऑफ़ हैं.

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

.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;
  }
}

फ़ोकस

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

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

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

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

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

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

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

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

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

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 ब्राउज़र या सेट टॉप बॉक्स में उपलब्ध है. मीडिया स्क्रोलर ग्रिड लेआउट में सिर्फ़ दिशा और स्पेसिंग के बारे में जानकारी होती है. इसलिए, मीडिया क्वेरी के अंदर साइज़ बदल सकता है और यह सुविधा, आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) की जांच करती है. कुछ और डाइनैमिक मीडिया स्क्रोलर में, प्रोग्रेस के हिसाब से बेहतर बनाने की सुविधा.

4:4 आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) वाला बॉक्स, 16:9 और 4:3 वाले दूसरे डिज़ाइन रेशियो के बगल में दिखाया जाता है

@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 साइज़ पर अपग्रेड कर दिया जाता है. ड्राफ़्ट नेस्टिंग सिंटैक्स का इस्तेमाल करके हर तस्वीर का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) इस आधार पर बदलता है कि वह पहली, दूसरी या तीसरी लाइन में है या नहीं. नेस्ट सिंटैक्स की मदद से, दूसरे साइज़िंग लॉजिक के साथ छोटे व्यूपोर्ट में भी बदलाव किए जा सकते हैं.

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

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

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

ALT_TEXT_HERE

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

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

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

(7 अनुरोध, 131 मि॰से॰ में 100 केबी रिसोर्स)

ALT_TEXT_HERE

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

ALT_TEXT_HERE

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

64 कम अनुरोध, जो इस ब्राउज़र टैब के व्यूपोर्ट (चौड़ी स्क्रीन डिसप्ले पर लिए गए टेस्ट) के अंदर ~60 इमेज, ~80% का पेज लोड बूस्ट, और वायर पर मौजूद 10% डेटा होगा. शानदार सीएसएस.

नतीजा

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

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

सोर्स

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

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