Подсказки о возможности прокрутки

Обзор

Визуальные подсказки, такие как тени или градиенты, помогают пользователям понять, что они могут прокрутить страницу, чтобы увидеть больше контента. В этом руководстве показано, как создать такие подсказки с помощью CSS container-scroll-state-queries, который позволяет стилизовать элементы на основе прокручиваемого состояния их контейнера, не полагаясь на прослушиватели прокрутки JavaScript или наблюдатели.

Реализация

1. Создайте контейнер прокрутки

Контейнер прокрутки должен быть объявлен как контейнер запросов состояния прокрутки.

.scroller {
  overflow-y: auto;
  /* Establish this element as a scroll-state query container */
  container-type: scroll-state;
  position: relative;
}

2. Как настроить стиль индикаторов

Поместите элементы индикатора (например, тени, градиенты или стрелки) в контейнер и настройте их стиль. По умолчанию они не должны быть видны. Если они показываются, то не должны быть интерактивными. Для этого нужно задать значение pointer-events: none.

.indicator-top, .indicator-bottom {
  position: sticky;
  left: 0;
  right: 0;
  height: 20px;
  opacity: 0;
  transition: opacity 0.2s;
  pointer-events: none; /* Let clicks pass through */
}

.indicator-top {
  top: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.2), transparent); /* Example: Shadow */
}

.indicator-bottom {
  bottom: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.2), transparent); /* Example: Shadow */
}

3. Как запросить состояние прокрутки

Используйте правило @container с функцией scroll-state. Проверьте, можно ли прокручивать контейнер вверх или вниз, чтобы показать соответствующий индикатор.

/* Show top indicator when the user can scroll up */
@container scroll-state(scrollable: top) {
  .indicator-top {
    opacity: 1;
  }
}

/* Show bottom indicator when the user can scroll down */
@container scroll-state(scrollable: bottom) {
  .indicator-bottom {
    opacity: 1;
  }
}

Резервные стратегии

Базовое резервное объявление

Если функция не поддерживается, индикаторы не будут видны. Поскольку это подсказки, а не критически важные функции, их можно опустить в неподдерживаемых браузерах.

Расширенное резервное решение (Intersection Observer)

Если подсказки необходимы, используйте IntersectionObserver для переключения классов, когда контрольные элементы вверху и внизу прокручиваемой области перемещаются в область прокрутки и из нее.

<!-- Sentinel elements placed at the ends of the scroller -->
<div class="sentinel-top"></div>
<!-- Content goes here -->
<div class="sentinel-bottom"></div>
/* Marker styling to ensure it does not affect layout */
.sentinel-top, .sentinel-bottom {
  height: 0;
  width: 0;
  visibility: hidden;
}

.scroller.scrolled-down .indicator-top {
  opacity: 1;
}

.scroller.can-scroll-down .indicator-bottom {
  opacity: 1;
}
if (!CSS.supports('container-type', 'scroll-state')) {
  const topSentinel = document.querySelector('.sentinel-top');
  const bottomSentinel = document.querySelector('.sentinel-bottom');
  const scroller = document.querySelector('.scroller');

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.target === topSentinel) {
        // If top sentinel is not intersecting, we have scrolled down
        scroller.classList.toggle('scrolled-down', !entry.isIntersecting);
      }
      if (entry.target === bottomSentinel) {
        // If bottom sentinel is intersecting, we reached the bottom
        scroller.classList.toggle('can-scroll-down', !entry.isIntersecting);
      }
    });
  }, { root: scroller });

  observer.observe(topSentinel);
  observer.observe(bottomSentinel);
}