स्क्रोल-स्टेट कंटेनर क्वेरी की मदद से, एलिमेंट को उनकी मौजूदा स्क्रोल स्थिति के आधार पर स्टाइल किया जा सकता है. जैसे, कोई एलिमेंट "स्टक" (स्टिकी पोज़िशनिंग के ज़रिए) है या "स्नैप" (स्क्रोल स्नैपिंग के ज़रिए) है. इससे कैरसेल या गैलरी के अनुभव मिलते हैं. इनमें, JavaScript इंटरसेक्शन ऑब्ज़र्वर या स्क्रोल इवेंट लिसनर पर भरोसा किए बिना, ऐक्टिव आइटम को विज़ुअल तौर पर अलग किया जा सकता है.
मुख्य तौर पर लागू करना
स्नैप किए गए आइटम हाइलाइट करने के लिए, आपको स्क्रोल-स्नैप कंटेनर बनाना होगा. साथ ही, स्नैप टारगेट को स्क्रोल-स्टेट कंटेनर के तौर पर तय करना होगा. इसके बाद, डिसेंडेंट को स्टाइल देने के लिए, उस स्टेट को क्वेरी करना होगा.
1. स्क्रोल स्नैप कंटेनर सेट अप करना
पैरंट कंटेनर में scroll-snap-type चालू होना चाहिए.
<div class="carousel">
<div class="carousel-item">
<div class="card">Product 1 content</div>
</div>
<div class="carousel-item">
<div class="card">Product 2 content</div>
</div>
</div>
.carousel {
display: flex;
overflow-x: auto;
/* MANDATORY: Enable scroll snapping on the container */
scroll-snap-type: x mandatory;
}
2. स्नैप टारगेट को स्क्रोल-स्टेट कंटेनर के तौर पर तय करना
कैरसेल में मौजूद हर उस आइटम को scroll-state कंटेनर के तौर पर एलान किया जाना चाहिए जिसे स्नैप करने के लिए ट्रैक किया जाना चाहिए.
.carousel-item {
/* Define where the item snaps within the container */
scroll-snap-align: center;
/* MANDATORY: Establish this element as a scroll-state query container */
container-type: scroll-state;
}
3. snapped की स्थिति के बारे में क्वेरी करना
कंटेनर क्वेरी, डिसेंडेंट को स्टाइल करती हैं. इसलिए, आपको स्नैप टारगेट के अंदर मौजूद किसी एलिमेंट पर हाइलाइट स्टाइल लागू करनी होंगी. स्क्रोल कंटेनर को x ऐक्सिस पर ओवरफ़्लो करने के लिए सेट किया गया है. इसलिए, scroll-state(snapped: x) क्वेरी का इस्तेमाल करें.
ज़रूरी: स्टाइल को @media (prefers-reduced-motion: no-preference) में रैप करें, ताकि इफ़ेक्ट सिर्फ़ उन उपयोगकर्ताओं को दिखे जिन्होंने कम मोशन का अनुरोध नहीं किया है. इस्तेमाल के उदाहरण के आधार पर, इफ़ेक्ट के कुछ हिस्सों को बनाए रखा जा सकता है. हालांकि, इस मामले में कार्ड सफ़ेद से नीले रंग में फ़्लैश होते हैं. इससे कुछ उपयोगकर्ताओं को समस्या हो सकती है. इसलिए, हम इसे पूरी तरह से बंद कर देते हैं.
/* Specify transition outside of queries so that it is applied regardless of state. */
.card {
transition:
scale 0.4s cubic-bezier(0.25, 0.8, 0.25, 1),
background-color 0.4s,
color 0.4s,
box-shadow 0.4s;
}
/*
Only show the effect for users not requesting reduced motion. Disable completely, including the color change, as it causes a flash that may be problematic.
*/
@media (prefers-reduced-motion: no-preference) {
/* Style the content when its parent .carousel-item is snapped on the x axis */
@container scroll-state(snapped: x) {
.card {
background: #007bff;
color: white;
scale: 1.15;
box-shadow: 0 10px 25px rgba(0, 123, 255, 0.3);
}
}
}
/* MANDATORY Copy-Paste Safety: Disable highlight scaling/flashing for motion sensitive users */
@media (prefers-reduced-motion: reduce) {
.card {
transition: none !important;
scale: 1 !important;
}
}
snapped डिस्क्रिप्टर, खास ऐक्सिस के बारे में क्वेरी कर सकता है: x, y, inline, block या both.
सुलभता
AVOID: इंटरैक्टिव एलिमेंट के साथ scroll-state का इस्तेमाल करना.
स्नैप किए गए आइटम के लिए विज़ुअल हाइलाइट, उपयोगकर्ता अनुभव को बेहतर बना सकते हैं. हालांकि, स्नैप किया गया आइटम, सुलभता ट्री में नहीं दिखता. स्नैप किए गए किसी आइटम पर लागू की गई विज़ुअल थीम से यह नहीं लगना चाहिए कि वह एलिमेंट चालू है या उस पर फ़ोकस किया गया है. साथ ही, कीबोर्ड फ़ोकस रिंग साफ़ तौर पर दिखनी चाहिए और snapped हाइलाइट से अलग होनी चाहिए. अगर स्नैप किया गया आइटम इंटरैक्टिव है, तो उसे ऐक्सेस करने के लिए आपको सुलभता के अन्य स्टैंडर्ड तरीकों का इस्तेमाल करना होगा.
स्नैपिंग, स्क्रोल करने की वजह से होती है. इससे कीबोर्ड फ़ोकस नहीं बदलता. हालांकि, कीबोर्ड फ़ोकस की वजह से स्क्रोल कंटेनर मूव हो सकता है. इससे स्नैप किए गए आइटम में बदलाव हो सकता है. यह आइटम, फ़ोकस किया गया आइटम हो भी सकता है और नहीं भी. इससे उपयोगकर्ताओं को भ्रम हो सकता है. इसलिए, हम ऐसा करने का सुझाव नहीं देते.
फ़ॉलबैक रणनीतियां
स्क्रोल-स्टेट क्वेरी के साथ काम न करने वाले ब्राउज़र के लिए, आपको एक ऐसा फ़ंक्शनल बेस अनुभव देना चाहिए जिसमें सभी आइटम पढ़े जा सकें. भले ही, "ऐक्टिव" हाइलाइट न हो.
सुविधा का पता लगाने की सुविधा
@supports का इस्तेमाल करके, सिर्फ़ उन ब्राउज़र को बेहतर बनाया जा सकता है जिन पर यह काम करता है:
@supports (container-type: scroll-state) {
/* Enhancement styles here */
}
JavaScript फ़ॉलबैक
अगर हाइलाइट, उपयोगकर्ता अनुभव के लिए ज़रूरी है, तो स्नैप किए गए आइटम का पता लगाने के लिए IntersectionObserver का इस्तेमाल करें. कैरसेल के बीच में मौजूद स्लाइस को पतला करने के लिए, rootMargin को नेगेटिव इनलाइन वैल्यू के साथ सेट करें. उदाहरण के लिए, अगर किसी एलिमेंट को इंटरसेक्ट करने वाला तब माना जाए, जब वह कैरसेल के बीच के 2% हिस्से में हो, तो rootMargin को "0px -49%" पर सेट करें.
// Optional: detect support and apply a JS-based fallback
if (!CSS.supports('container-type', 'scroll-state')) {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
// Toggle a class based on intersection
entry.target.classList.toggle('is-snapped', entry.isIntersecting);
});
}, {
root: document.querySelector(".carousel"),
// Carousel item intersects if any part of the carousel item is in the middle 2% of the carousel.
rootMargin: "0px -49%"
});
document.querySelectorAll('.carousel-item').forEach(item => {
observer.observe(item);
});
}