کنترل پیمایش را به‌دست بگیرید - سفارشی‌سازی جلوه‌های «کشیدن برای بازآوری» و «سرریز»

خیلی طولانی است؛ خوانده نشد

ویژگی CSS overscroll-behavior به توسعه‌دهندگان اجازه می‌دهد رفتار پیش‌فرض پیمایش سرریز مرورگر را هنگام رسیدن به بالا/پایین محتوا لغو کنند. موارد استفاده شامل غیرفعال کردن ویژگی «کشیدن برای بازآوری» در تلفن همراه، برداشتن جلوه‌های درخشش فراتومار و کشسانی، و جلوگیری از پیمایش محتوای صفحه وقتی زیر یک مدال/پوشش قرار دارد می‌شود.

پس‌زمینه

مرزهای پیمایش و زنجیره‌سازی پیمایش

زنجیر کردن پیمایش در Chrome Android.

پیمایش یکی از اساسی‌ترین روش‌های تعامل با صفحه است، اما برخی‌از الگوهای UX به‌دلیل رفتارهای پیش‌فرض عجیب مرورگر می‌توانند مشکل‌ساز باشند. به‌عنوان مثال، کشوی برنامه‌ای را درنظر بگیرید که تعداد زیادی مورد دارد و کاربر باید برای دیدن آن‌ها پیمایش کند. وقتی به پایین می‌رسند، پیمایش محفظه سرریز متوقف می‌شود چون محتوای دیگری برای مصرف وجود ندارد. به عبارت دیگر، کاربر به «مرز پیمایش» می‌رسد. اما ببینید اگر کاربر به پیمایش ادامه دهد چه اتفاقی می‌افتد. محتوای پشت کشو شروع به پیمایش می‌کند! پیمایش توسط محفظه اصلی انجام می‌شود؛ در این مثال، خود صفحه اصلی.

Turns out this behavior is called scroll chaining; the browser's default behavior when scrolling content. اغلب اوقات، پیش‌فرض بسیار خوب است، اما گاهی‌اوقات مطلوب نیست یا حتی غیرمنتظره است. برخی‌از برنامه‌ها ممکن است بخواهند وقتی کاربر به مرز پیمایش می‌رسد، تجربه کاربری متفاوتی ارائه دهند.

جلوه کشیدن برای بازآوری

«کشیدن برای بازآوری» اشاره‌ای شهودی است که توسط برنامه‌های تلفن همراه مانند Facebook و Twitter محبوب شده است. کشیدن فید رسانه‌های اجتماعی به پایین و رها کردن آن، فضای جدیدی برای بار کردن پست‌های جدیدتر ایجاد می‌کند. درواقع، این تجربه کاربری خاص آن‌قدر محبوب شده است که مرورگرهای تلفن همراه مانند Chrome در Android نیز همین جلوه را اتخاذ کرده‌اند. با تند کشیدن به پایین در بالای صفحه، کل صفحه بازآوری می‌شود:

کشیدن برای بازآوری سفارشی توییتر
هنگام بازآوری فید در برنامه وب پیشروی آن‌ها.
کنش بومی کشیدن برای بازآوری Chrome Android
کل صفحه را بازآوری می‌کند.

برای موقعیت‌هایی مانند PWA توییتر، ممکن است منطقی باشد که کنش کشیدن برای بازآوری بومی را غیرفعال کنید. چرا؟ در این برنامه، احتمالاً نمی‌خواهید کاربر به‌طور تصادفی صفحه را بازآوری کند. همچنین احتمال دیدن پویانمایی بازآوری دوگانه وجود دارد! یا شاید بهتر باشد کنش مرورگر را سفارشی‌سازی کنید تا با نمانام‌سازی سایت هم‌راستاتر شود. بخش ناخوشایند این است که این نوع سفارشی‌سازی دشوار بوده است. توسعه‌دهندگان درنهایت جاوا اسکریپت غیرضروری می‌نویسند، شنوندگان لمسی غیرفعال (که پیمایش را مسدود می‌کنند) اضافه می‌کنند، یا کل صفحه را در یک 100vw/vh <div> (برای جلوگیری از سرریز شدن صفحه) قرار می‌دهند. این راه‌حل‌ها تأثیرات منفی مستندشده‌ای بر عملکرد پیمایش دارند.

می‌توانیم بهتر عمل کنیم!

معرفی overscroll-behavior

ویژگی overscroll-behavior یک ویژگی جدید CSS است که رفتار آنچه را که هنگام پیمایش بیش‌ازحد یک ظرف (ازجمله خود صفحه) اتفاق می‌افتد، کنترل می‌کند. می‌توانید از آن برای لغو زنجیره پیمایش، غیرفعال کردن/سفارشی‌سازی کنش کشیدن برای بازآوری، غیرفعال کردن جلوه‌های rubberbanding در iOS (وقتی Safari overscroll-behavior را پیاده‌سازی می‌کند)، و موارد دیگر استفاده کنید. بهترین بخش این است که استفاده از overscroll-behavior تأثیر منفی بر عملکرد صفحه ندارد، برخلاف ترفندهایی که در مقدمه ذکر شد!

این خصوصیت سه مقدار ممکن دارد:

  1. auto - پیش‌فرض. پیمایش‌هایی که از عنصر شروع می‌شوند ممکن است به عناصر اجدادی منتشر شوند.
  2. contain - از زنجیره‌ای شدن پیمایش جلوگیری می‌کند. پیمایش‌ها به گره‌های والد منتقل نمی‌شوند اما جلوه‌های محلی درون گره نشان داده می‌شوند. برای مثال، جلوه درخشش فراتر از پیمایش در Android یا جلوه rubberbanding در iOS که وقتی کاربر به مرز پیمایش می‌رسد به او اطلاع می‌دهد. توجه: استفاده از overscroll-behavior: contain در عنصر html مانع از کنش‌های پیمایش فراتر از صفحه می‌شود.
  3. none - همانند contain اما از جلوه‌های پیمایش بیش‌ازحد در خود گره نیز جلوگیری می‌کند (برای مثال، درخشش پیمایش بیش‌ازحد Android یا rubberbanding در iOS).

بیایید چند مثال را بررسی کنیم تا ببینیم چگونه از overscroll-behavior استفاده کنیم.

جلوگیری از فرار پیمایش‌ها از عنصر بی‌حرکت

سناریو چارگوش گپ

محتوای زیر پنجره گپ هم پیمایش می‌شود :(

یک جعبه گپ با موقعیت ثابت را درنظر بگیرید که در پایین صفحه قرار دارد. هدف این است که جعبه گپ یک مؤلفه مستقل باشد و به‌طور جداگانه از محتوای پشت آن پیمایش شود. اما به‌دلیل زنجیره‌سازی پیمایش، به‌محض اینکه کاربر به آخرین پیام در سابقه گپ می‌رسد، سند شروع به پیمایش می‌کند.

برای این برنامه، مناسب‌تر است که پیمایش‌هایی که از داخل چارگوش گپ شروع می‌شوند در داخل گپ باقی بمانند. می‌توانیم این کار را با افزودن overscroll-behavior: contain به عنصری که پیام‌های گپ را نگه می‌دارد انجام دهیم:

#chat .msgs {
  overflow: auto;
  overscroll-behavior: contain;
  height: 300px;
}

در اصل، ما درحال ایجاد یک جدایی منطقی بین زمینه پیمایش جعبه گپ و صفحه اصلی هستیم. نتیجه نهایی این است که وقتی کاربر به بالا/پایین سابقه گپ می‌رسد، صفحه اصلی ثابت می‌ماند. پیمایش‌هایی که در چارگوش گپ شروع می‌شوند به بیرون گسترش نمی‌یابند.

سناریوی رونهاد صفحه

نوع دیگری از سناریو «پیمایش زیرین» زمانی است که می‌بینید محتوا پشت پوشش موقعیت ثابت پیمایش می‌شود. یک هدیه عالی overscroll-behavior در راه است! مرورگر سعی می‌کند مفید باشد اما درنهایت باعث می‌شود سایت دارای اشکال به‌نظر برسد.

مثال - مدال با و بدون overscroll-behavior: contain:

قبل: محتوای صفحه زیر رونهاد پیمایش می‌شود.
بعد: محتوای صفحه زیر هم‌پوشانی پیمایش نمی‌شود.

غیرفعال کردن «کشیدن برای بازآوری»

غیرفعال کردن کنش کشیدن برای بازآوری یک خط CSS است. کافی است از زنجیره‌سازی پیمایش در کل عنصر تعریف‌کننده نمای هدف جلوگیری کنید. در اکثر موارد، این آدرس <html> یا <body> است:

body {
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;
}

با این افزودن ساده، پویانمایی‌های دوگانه کشیدن برای بازآوری را در نمونه آزمایشی chatbox اصلاح می‌کنیم و می‌توانیم به‌جای آن، جلوه سفارشی‌ای را پیاده‌سازی کنیم که از پویانمایی بارگیری مرتب‌تری استفاده می‌کند. با بازآوری صندوق ورودی، کل صندوق ورودی نیز محو می‌شود:

قبل
بعداز

این تکه‌ای از کد کامل است:

<style>
  body.refreshing #inbox {
    filter: blur(1px);
    touch-action: none; /* prevent scrolling */
  }
  body.refreshing .refresher {
    transform: translate3d(0,150%,0) scale(1);
    z-index: 1;
  }
  .refresher {
    --refresh-width: 55px;
    pointer-events: none;
    width: var(--refresh-width);
    height: var(--refresh-width);
    border-radius: 50%;
    position: absolute;
    transition: all 300ms cubic-bezier(0,0,0.2,1);
    will-change: transform, opacity;
    ...
  }
</style>

<div class="refresher">
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
</div>

<section id="inbox"><!-- msgs --></section>

<script>
  let _startY;
  const inbox = document.querySelector('#inbox');

  inbox.addEventListener('touchstart', e => {
    _startY = e.touches[0].pageY;
  }, {passive: true});

  inbox.addEventListener('touchmove', e => {
    const y = e.touches[0].pageY;
    // Activate custom pull-to-refresh effects when at the top of the container
    // and user is scrolling up.
    if (document.scrollingElement.scrollTop === 0 && y > _startY &&
        !document.body.classList.contains('refreshing')) {
      // refresh inbox.
    }
  }, {passive: true});
</script>

غیرفعال کردن جلوه‌های درخشش فراتر از پیمایش و بازگشت کشسانی

برای غیرفعال کردن جلوه پرش هنگام رسیدن به مرز پیمایش، از overscroll-behavior-y: none استفاده کنید:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
قبل: رسیدن به مرز پیمایش، درخششی را نشان می‌دهد.
بعد: درخشش غیرفعال است.

نسخه نمایشی کامل

با کنار هم قرار دادن همه این‌ها، نمونه نمایشی کامل جعبه گپ از overscroll-behavior برای ایجاد پویانمایی سفارشی کشیدن برای بازآوری و غیرفعال کردن پیمایش‌ها برای جلوگیری از خروج از ابزاره جعبه گپ استفاده می‌کند. این کار تجربه کاربری بهینه‌ای را ارائه می‌دهد که دستیابی به آن بدون CSS دشوار بود overscroll-behavior.

مشاهده نسخه نمایشی | منبع