Scroll Snap State Sync

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

پیاده‌سازی

۱. پیکربندی کردن «میزان کردن پیمایش» در CSS

محتوی باید scroll-snap-type تعریف‌شده داشته باشد و فرزندانی با scroll-snap-align داشته باشد تا مرورگر بتواند هدف‌های چسباندن را ردیابی کند. در مقاله‌ای طولانی با فهرست مطالب، می‌توانید از این ویژگی برای چسباندن سرصفحه‌های بخش به بالای نمای دید استفاده کنید.

main {
    /* Enable scroll snapping on the container */  
  scroll-snap-type: y proximity;
  overflow-y: auto;
}

h2 {
  /* Define how headers align when snapped */
  scroll-snap-align: start;
}

۲. گوش دادن به تغییرات Snap

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

<!-- MANDATORY: Wrap table of contents links inside a proper navigation landmark -->
<nav aria-label="Table of contents">
  <ul>
    <li><a href="#section-1" aria-current="location">Section 1</a></li>
    <li><a href="#section-2">Section 2</a></li>
  </ul>
</nav>
const main = document.getElementById('main');
const links = document.querySelectorAll('nav a');

// The event fires when the scroller settles on a new snap target
main.addEventListener('scrollsnapchange', (event) => {
  // Use snapTargetBlock for vertical or snapTargetInline for horizontal
  const snappedHeader = event.snapTargetBlock;
  
  if (snappedHeader) {
    setSelectedParagraph(snappedHeader.id);
  }
});

دسترس‌پذیری

برای فهرست مطالب، مطمئن شوید پیوندهای نوار کناری هنگام فعال بودن از aria-current="true" یا aria-current="location" استفاده می‌کنند.

علاوه‌براین، هنگام استفاده از مقدار mandatory برای scroll-snap-type مراقب باشید، زیرا می‌تواند باعث شود محتوای بین نقاط پرش زمانی‌که طولانی‌تر از صفحه است غیرقابل‌دسترس شود.

راهبردهای جایگزین

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

// Feature detect support for scroll snap events
if (!('onscrollsnapchange' in HTMLElement.prototype)) {
  const observer = new IntersectionObserver(
    () => {
      // Each time the set of intersecting headers changes, find the top
      // header that is visible.
      const topEntry = [...headers].reduce((currentTop, header) => {
        // Use the bottom to handle scrolling up, when the top is still offscreen
        const {bottom} = header.getBoundingClientRect();
        // Don't match if the header's bottom is above the scrollport
        if (bottom < 0) return;
        if (!currentTop) return header;
        return bottom <
          currentTop.getBoundingClientRect().bottom
          ? header
          : currentTop;
      }, undefined);
      if (topEntry) setSelectedParagraph(topEntry.id);
    },
    { root: main, threshold: 0.9 // Adjust based on your use case },
  );

  // Observe all snap targets (e.g., section headers)
  document.querySelectorAll('h2').forEach(header => observer.observe(header));
}