टीवी, फ़ोन, डेस्कटॉप वगैरह के लिए रिस्पॉन्सिव हॉरिज़ॉन्टल स्क्रोलव्यू बनाने के तरीके के बारे में बुनियादी जानकारी
इस पोस्ट में, मैं वेब के लिए हॉरिज़ॉन्टल स्क्रोलिंग वाले ऐसे अनुभव बनाने के तरीकों के बारे में बताना चाहता हूं जो कम से कम हों, रिस्पॉन्सिव हों, ऐक्सेस किए जा सकें, और सभी ब्राउज़र और प्लैटफ़ॉर्म (जैसे कि टीवी!) पर काम करें. डेमो आज़माएं.
अगर आपको वीडियो देखना ज़्यादा पसंद है, तो इस पोस्ट का 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%)
);
}
स्क्रोल पैडिंग
पेज के कॉन्टेंट के साथ अलाइनमेंट और किनारे से किनारे तक स्क्रोल करने की सुविधा, कॉम्पोनेंट को बेहतर और कम से कम बनाने के लिए ज़रूरी है.
किनारे से किनारे तक स्क्रोल करने वाले लेआउट को पूरा करने के लिए, हमारी टाइपोग्राफ़ी और लेआउट लाइनों के साथ अलाइन करें. इसके लिए, padding
का इस्तेमाल करें, जो scroll-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 से ज़्यादा बार दबाने की ज़रूरत नहीं होती.
डेमो के पहले स्क्रोलर में 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 देखें.
आस्पेक्ट रेशियो
यह पोस्ट लिखते समय, aspect-ratio
के लिए सहायता Firefox में फ़्लैग के पीछे है. हालांकि, यह Chromium ब्राउज़र या सेट टॉप बॉक्स में उपलब्ध है. मीडिया स्क्रोलर ग्रिड लेआउट में सिर्फ़ दिशा और स्पेसिंग तय की जाती है. इसलिए, मीडिया क्वेरी के अंदर साइज़िंग बदल सकती है. यह सुविधा, आसपेक्ट रेशियो के साथ काम करने की सुविधा की जांच करती है.
कुछ और डाइनैमिक मीडिया स्क्रोलर में प्रोग्रेसिव एन्हांसमेंट.
@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 पर यह पूछा जा सकता है कि डिवाइस, डेटा बचाने वाले मोड जैसे किसी भी ऐसे मोड में है या नहीं जिसमें डेटा का इस्तेमाल कम होता है. अगर ऐसा है, तो मैं दस्तावेज़ में बदलाव कर सकता हूँ. साथ ही, इस मामले में इमेज छिपा सकता हूँ.
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
कॉन्टेंट को अब भी नेविगेट किया जा सकता है. हालांकि, इसमें ज़्यादा साइज़ वाली इमेज डाउनलोड नहीं की जाती हैं. prefers-reduced-data
सीएसएस जोड़ने से पहले साइट ऐसी दिखती थी:
(सात अनुरोध, 131 मि॰से॰ में 100 केबी के संसाधन)
prefers-reduced-data
सीएसएस जोड़ने के बाद, साइट की परफ़ॉर्मेंस यहां दी गई है:
(71 अनुरोध, 1.07 सेकंड में 1.2 एमबी के संसाधन)
इस ब्राउज़र टैब के व्यूपोर्ट में मौजूद ~60 इमेज के लिए, 64 कम अनुरोध किए गए. ये टेस्ट, वाइड स्क्रीन डिसप्ले पर किए गए थे. इससे पेज लोड होने की स्पीड में ~80% की बढ़ोतरी हुई और 10% डेटा कम इस्तेमाल हुआ. यह सीएसएस बहुत काम की है.
नतीजा
अब आपको पता चल गया है कि मैंने यह कैसे किया. अब आप इसे कैसे करेंगे?! 🙂
आइए, हम अपने तरीकों में विविधता लाएं और वेब पर काॅन्टेंट पोस्ट करने के सभी तरीके जानें. Codepen बनाएं या अपना डेमो होस्ट करें. इसके बाद, मुझे ट्वीट करके इसकी जानकारी दें. मैं इसे यहां दिए गए कम्यूनिटी रीमिक्स सेक्शन में जोड़ दूंगा.
सोर्स
कम्यूनिटी रीमिक्स
अभी यहां देखने के लिए कुछ नहीं है!