देखने के लिए स्वाइप करें

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

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

इन्हें कैसे लागू करें

चाहे आपको सूची के किसी आइटम पर ऐक्शन बटन दिखाने हों या स्क्रोल किए जा सकने वाले पैनल के बगल में मौजूद साइड मेन्यू पर, दोनों के लिए एक ही तरीका अपनाया जाता है: फ़ोरग्राउंड कॉन्टेंट और छिपे हुए पैनल को, सीएसएस स्क्रोल स्नैप (scroll-snap-type: x mandatory) और overscroll-behavior: chain के साथ कॉन्फ़िगर किए गए बाहरी हॉरिज़ॉन्टल स्क्रोल कंटेनर में रैप करें. ब्राउज़र का नेटिव स्क्रोलिंग इंजन, JavaScript जेस्चर लिसनर के बिना मोमेंटम, स्नैपिंग, कीबोर्ड फ़ोकस स्क्रोलिंग, और स्क्रोल चेनिंग को मैनेज करता है.

पहला चरण: स्वाइप रैपर, कॉन्टेंट, और दिखाए गए पैनल को मार्क अप करना

.SwipeReveal स्क्रोल कंटेनर में, सबसे पहले फ़ोरग्राउंड कॉन्टेंट और उसके बाद, ऐक्शन बटन या साइड मेन्यू जैसे कंट्रोल रखें. कॉन्टेंट, DOM ऑर्डर में सबसे पहले होता है. इसलिए, स्क्रोल कंटेनर स्वाभाविक रूप से स्क्रोल ऑफ़सेट 0 से शुरू होता है. साथ ही, पैनल स्क्रीन के दाईं ओर छिपा होता है.

<!-- Example A: List item with revealable action buttons -->
<div class="SwipeReveal">
  <div class="SwipeReveal-content">
    <strong>Design review notes</strong>
    <p>Updated component specs for the Q3 release.</p>
  </div>
  <div class="SwipeReveal-panel" role="group" aria-label="Item actions">
    <button type="button">Pin</button>
    <button type="button">Archive</button>
    <button type="button">Delete</button>
  </div>
</div>

<!-- Example B: Scrollable content pane with a revealable side menu -->
<div class="SwipeReveal" role="region" aria-label="Document preview with swipeable side menu">
  <div class="SwipeReveal-content is-scrollable" tabindex="0">
    <h2>Article Preview</h2>
    <p>Scroll vertically through this pane, or swipe left to reveal the side menu...</p>
  </div>
  <nav class="SwipeReveal-panel" aria-label="Contextual menu">
    <a href="#share">Share</a>
    <a href="#bookmark">Bookmark</a>
    <a href="#export">Export PDF</a>
  </nav>
</div>

दूसरा चरण: हॉरिज़ॉन्टल स्नैप कंटेनर और overscroll-behavior: chain को कॉन्फ़िगर करना

जब किसी एलिमेंट को बाहरी स्क्रोल कंटेनर में सिर्फ़ स्वाइप-टू-रिवील इफ़ेक्ट बनाने के लिए रैप किया जाता है, तो वह बाहरी रैपर, दस्तावेज़ (या किसी अन्य पैरंट स्क्रोल कंटेनर) के अंदर एक इंटरमीडिएट स्क्रोलर बन जाता है.

overscroll-behavior के चार कीवर्ड, अलग-अलग तौर पर यह कंट्रोल करते हैं कि ज़्यादा स्क्रोल करने पर, वह ऐंसेस्टर स्क्रोल कंटेनर (स्क्रोल चेनिंग) पर लागू हो या नहीं. साथ ही, यह भी कंट्रोल करते हैं कि कंटेनर, लोकल ओवरस्क्रोल अफ़ोर्डेंस दिखाता है या नहीं. जैसे, इलास्टिक रबर-बैंड स्ट्रेचिंग या एज ग्लो (लोकल बाउंड्री इफ़ेक्ट):

वैल्यू स्क्रोल चेनिंग (पैरंट एलिमेंट पर लागू होता है) लोकल बाउंड्री इफ़ेक्ट (रबर-बैंड / ग्लो) स्वाइप-टू-रिवील में भूमिका
auto हां हां डिफ़ॉल्ट ऐक्शन और सेटिंग; इसे इनर कॉन्टेंट स्क्रोलर पर चालू रखें, जहां सामान्य बाउंस फ़ीडबैक की ज़रूरत होती है. हालांकि, इसे बाहरी स्वाइप रैपर पर चालू न करें, क्योंकि इससे मेन्यू बाउंस होता है
chain हां नहीं बाहरी .SwipeReveal स्क्रोलर पर इस्तेमाल करें, ताकि ज़्यादा स्क्रोल करने पर, पैरंट स्क्रोलर (जैसे कि दस्तावेज़) में स्क्रोल किया जा सके. इससे मेन्यू या ऐक्शन स्ट्रिप बाउंस नहीं होगी
contain नहीं हां कंटेनर के अंदर स्क्रोल को ट्रैप करता है, जबकि स्थानीय तौर पर बाउंस करता है
none नहीं नहीं यह लोकल बाउंस और स्क्रोल चेनिंग, दोनों को पैरंट एलिमेंट पर जाने से रोकता है

.SwipeReveal को दो कॉलम वाली ग्रिड (grid-template-columns: 100% max-content) बनाएं, जहां .SwipeReveal-content, start पर स्नैप हो और .SwipeReveal-panel, end पर स्नैप हो:

.SwipeReveal {
  /* Column 1: full-width content. Column 2: auto-sized actions or side menu. */
  display: grid;
  grid-template-columns: 100% max-content;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;

  /* Prevent the swipe wrapper and revealed panel from bouncing locally while
     still chaining excess scroll into the parent scroller (the document). */
  overscroll-behavior: chain;
}

@media (prefers-reduced-motion: no-preference) {
  .SwipeReveal {
    scroll-behavior: smooth;
  }
}

.SwipeReveal-content {
  scroll-snap-align: start;
  scroll-initial-target: nearest;
  background: Canvas;
}

.SwipeReveal-content:focus-visible {
  outline: auto;
  outline-offset: -2px;
}

.SwipeReveal-content.is-scrollable {
  block-size: 20rem;
  overflow: auto;
  /* Keeps default `overscroll-behavior: auto` so the content pane retains
     its normal bounce effect while chaining horizontal swipes to `.SwipeReveal`. */
}

.SwipeReveal-panel {
  /* Snapping a trailing panel to `end` (or a leading panel to `start`) brings
     all controls fully into view while keeping the adjacent edge of the content visible. */
  scroll-snap-align: end;
  display: flex;

  &:first-child {
    scroll-snap-align: start;
  }
}

अगर आपको तीन कॉलम (grid-template-columns: max-content 100% max-content) या दो कॉलम (max-content 100%) का इस्तेमाल करके, बाईं (inline-start) ओर भी कंट्रोल दिखाने हैं, तो .SwipeReveal-content से पहले लीडिंग .SwipeReveal-panel डालें. .SwipeReveal-content में scroll-initial-target: nearest होने की वजह से, स्क्रोल कंटेनर शुरुआत में लीडिंग पैनल के बजाय कॉन्टेंट कॉलम पर रहता है.

तीसरा चरण: कीबोर्ड फ़ोकस पर, फ़ोकस किए जा सकने वाले कॉन्टेंट पैनल को वापस व्यू में स्नैप करना

.SwipeReveal-panel के अंदर मौजूद बटन या लिंक, रेस्ट मोड में ऑफ़-स्क्रीन होते हैं. इसलिए, कीबोर्ड से टैब करने पर, .SwipeReveal अपने-आप स्क्रोल हो जाता है, ताकि फ़ोकस किया गया कंट्रोल दिख सके. हालांकि, .SwipeReveal-content बाहरी कंटेनर की चौड़ाई के 100% हिस्से में फैला होता है. इसलिए, साइड पैनल खुला होने पर भी इसका ज़्यादातर हिस्सा स्क्रोलपोर्ट के अंदर रहता है. इसलिए, फ़ोकस को वापस .SwipeReveal-content (या इसके अंदर मौजूद किसी ऐसे एलिमेंट पर जिस पर फ़ोकस किया जा सकता है) पर ले जाने के लिए, Shift+Tab दबाने से ट्रैक अपने-आप 0 पर स्क्रोल नहीं होगा.

.SwipeReveal-content पर focusin को सुनें और event.target.matches(':focus-visible') को चुनें, ताकि पेन या किसी भी डिसेंडेंट पर कीबोर्ड फ़ोकस, पॉइंटर क्लिक या टच ड्रैग में रुकावट डाले बिना .SwipeReveal-content को वापस शुरुआत पर ले जाए:

for (const content of document.querySelectorAll('.SwipeReveal-content')) {
  content.addEventListener('focusin', (event) => {
    if (event.target.matches(':focus-visible')) {
      content.scrollIntoView({
        block: 'nearest',
        inline: 'start',
      });
    }
  });
}

सबसे सही तरीके और नुकसान

  • proximity के बजाय scroll-snap-type: x mandatory का इस्तेमाल करें. proximity में, हल्के से स्वाइप करने पर, ऐक्शन बटन या साइड मेन्यू कुछ हद तक दिख सकता है.
  • बाहरी हॉरिज़ॉन्टल स्वाइप-टू-रिवील स्क्रोलर (.SwipeReveal) पर overscroll-behavior: chain सेट करें, ताकि स्क्रोल को पैरंट स्क्रोलर में चेन किया जा सके. ऐसा करने पर, दिखाया गया मेन्यू या ऐक्शन स्ट्रिप बाउंस नहीं होगी.
  • overscroll-behavior: auto (डिफ़ॉल्ट) को अंदर मौजूद स्क्रोल किए जा सकने वाले कॉन्टेंट पैनल (.SwipeReveal-content.is-scrollable) पर छोड़ें. ऐसा तब करें, जब आपको सामान्य बाउंस फ़ीडबैक चाहिए और हॉरिज़ॉन्टल स्वाइप को बाहरी स्वाइप स्क्रोलर से जोड़ना हो.
  • ज़रूर करें: सामने दिखने वाली कार्रवाइयों और साइड-मेन्यू के आइटम को, फ़ोकस किए जा सकने वाले असल डीओएम कंट्रोल (<button>, <a>) के तौर पर लागू करें. जब .SwipeReveal-content फ़ोकस किया जा सकता हो या उसमें फ़ोकस किए जा सकने वाले कंट्रोल शामिल हों, तो scrollIntoView({ block: 'nearest', inline: 'start' }) को कॉल करने के लिए, focusin लिसनर को event.target.matches(':focus-visible') के साथ जोड़ें. इससे, कॉन्टेंट पैनल में वापस टैब करने पर, पॉइंटर इंटरैक्शन पर असर डाले बिना साइड पैनल बंद हो जाता है.
  • DO NOT intercept wheel, touchmove, or pointermove events in JavaScript to manually translate the content or emulate scroll chaining. मुख्य थ्रेड के जेस्चर इंटरसेप्शन की वजह से, कंपोज़िटर से चलने वाली स्क्रोलिंग ब्लॉक हो जाती है. साथ ही, नेटिव स्क्रोल मोमेंटम टूट जाता है और रिस्पॉन्सिवनेस कम हो जाती है.

फ़ॉलबैक

जब कोई .SwipeReveal कंटेनर, .SwipeReveal-content से पहले बाईं (inline-start) ओर .SwipeReveal-panel रखता है, तो scroll-initial-target: nearest के साथ काम न करने वाले ब्राउज़र, शुरुआत में स्क्रोल ऑफ़सेट 0 पर रेंडर करेंगे. इसमें लीडिंग पैनल दिखेगा.

अगर आपका बेसलाइन टारगेट scroll-initial-target के साथ काम नहीं करता है, तो CSS.supports('scroll-initial-target', 'nearest') की मदद से पता लगाएं कि यह सुविधा काम करती है या नहीं. इसके बाद, load पर behavior: 'instant' के साथ scrollTo() को कॉल करें, ताकि लीडिंग पैनल वाले कंटेनर, पेज को स्क्रोल किए बिना सीधे .SwipeReveal-content पर पहुंच जाएं:

परतदार वृद्धि

overscroll-behavior: chain और scrollbar-width: none को JavaScript फ़ॉलबैक के बिना, परतदार वृद्धि के तौर पर इस्तेमाल करें:

  • सीएसएस कैस्केड फ़ॉलबैक अपने-आप लागू होना: overscroll-behavior की शुरुआती वैल्यू auto है. जो ब्राउज़र अब तक chain कीवर्ड को नहीं पहचानते वे पार्स करते समय overscroll-behavior: chain को अनदेखा कर देते हैं और auto को बनाए रखते हैं. auto पहले से ही स्क्रोल कंटेनर के लिए स्क्रोल चेनिंग की अनुमति देता है. इसलिए, स्वाइप करके दिखाने का जेस्चर और पैरंट के लिए स्क्रोल चेनिंग, दोनों ही सभी ब्राउज़र पर काम करते हैं. इसके लिए, आपको कुछ भी करने की ज़रूरत नहीं होती. जिन ब्राउज़र पर यह सुविधा काम करती है वे बाहरी स्वाइप रैपर पर, रबर-बैंड बाउंस को रोक देते हैं.
  • contain या none को बदलना: अगर कोई बेस स्टाइलशीट या यूटिलिटी क्लास overscroll-behavior: contain या none सेट करती है, तो overscroll-behavior: chain से ठीक पहले overscroll-behavior: auto का एलान करें. इससे, chain के साथ काम न करने वाले ब्राउज़र, स्क्रोलिंग को ट्रैप करने के बजाय पैरंट एलिमेंट पर चेन स्क्रोलिंग जारी रखेंगे.
  • स्क्रोलबार छिपाना (scrollbar-width: none): हॉरिज़ॉन्टल स्क्रोलबार ट्रैक को छिपाने से, सिर्फ़ विज़ुअल पर असर पड़ता है. अगर कोई पुराना इंजन scrollbar-width: none को अनदेखा करता है, तो स्वाइप करके दिखने वाला कंटेनर, स्टैंडर्ड स्क्रोलबार के साथ पूरी तरह से काम करता रहता है.