Kaydırarak Tutturma Durumu Senkronizasyonu

Kullanıcı arayüzü durumunu kaydırılabilir bir kapsayıcının tutturma konumuyla senkronize etmek için geleneksel olarak karmaşık kaydırma etkinliği işleyiciler, kaydırma ofsetlerinin manuel hesaplamaları ve kesişim gözlemcileri gerekiyordu. scrollsnapchange etkinliği, kaydırıcının yeni bir yakalama hedefine ne zaman yerleştiğini algılamanın yerel ve verimli bir yolunu sunar. Bu sayede, kenar çubuklarını senkronize etmek veya içindekiler tablosundaki etkin bölümü vurgulamak için kullanışlıdır.

Uygulama

1. CSS'de kaydırarak tutturmayı yapılandırma

Tarayıcının kaydırma hedeflerini izleyebilmesi için kapsayıcıda scroll-snap-type tanımlanmış olmalı ve scroll-snap-align içeren alt öğeler bulunmalıdır. İçindekiler tablosu içeren uzun bir makalede, bölüm başlıklarını görüntü alanının üst kısmına sabitlemek için bu özelliği kullanabilirsiniz.

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;
}

2. Snap değişikliklerini dinleme

Kullanıcı kaydırmayı bitirdiğinde ve tarayıcı yeni bir öğeye geçtiğinde tepki vermek için kaydırma kapsayıcısında scrollsnapchange etkinliğini kullanın. İçindekiler tablosu demomuzda, kenar çubuğundaki etkin bağlantıyı vurgulamak için bu özelliği kullanıyoruz.

<!-- 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);
  }
});

Erişilebilirlik

İçindekiler tablosu için kenar çubuğu bağlantılarının etkin olduklarında aria-current="true" veya aria-current="location" kullandığından emin olun.

Ayrıca, scroll-snap-type için mandatory değerini kullanırken dikkatli olun. Bu değer, ekrandan daha uzun olduğunda tutturma noktaları arasındaki içeriğin erişilemez hale gelmesine neden olabilir.

Yedek stratejiler

scrollsnapchange desteklenmiyorsa kaydırıcının en üstünde hangi öğenin bulunduğunu tespit etmek için IntersectionObserver kullanın. Bu, scrollsnapchange'ten farklı bir davranıştır. Çünkü bu, yalnızca kaydırma işlemi tamamlandığında değil, kaydırma işlemi gerçekleşirken tetiklenir.

// 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));
}