"Потяните, чтобы увидеть" – это шаблон пользовательского интерфейса, в котором контент (например, строка поиска или элемент управления обновлением) скрыт над верхней частью прокручиваемой области при начальной загрузке, и пользователь может потянуть вниз (прокрутить вверх), чтобы увидеть его. Этот шаблон обычно используется в мобильных и веб-приложениях для строк поиска, фильтров и других дополнительных элементов управления, которые должны быть доступны, но не сразу видны.
Свойство CSS scroll-initial-target предлагает декларативный способ реализации этого шаблона только на CSS. Если задать scroll-initial-target: nearest для элемента основного контента, контейнер прокрутки будет отображаться со скрытым контентом, прокрученным за пределы видимости. Раньше для этого разработчики использовали JavaScript (Element.scrollIntoView()) или идентификаторы фрагментов URL (#content-id). Однако оба этих способа имеют ограничения и сложны в реализации.
Как реализовать
Чтобы реализовать шаблон "Потяните, чтобы увидеть":
- Убедитесь, что контейнер прокрутки существует. Целевой элемент должен находиться внутри контейнера прокрутки (элемента с переполнением, который позволяет прокручивать, например
overflow: auto). Это может быть любой элемент-предок, включая корневой элемент<html>. - Определите скрытый элемент. Поместите контент, который хотите скрыть (например, строку поиска), в качестве первого дочернего элемента внутри контейнера прокрутки. При первоначальной загрузке этот элемент будет прокручен за пределы видимой области.
- Определите основной контент. Разместите элемент основного контента сразу после скрытого элемента. Это элемент, который пользователь должен увидеть в первую очередь.
- Таргетинг на основной контент. Примените
scroll-initial-target: nearestк основному элементу контента, чтобы контейнер прокрутки отображался вместе с ним, скрывая элемент над ним. - Добавьте привязку прокрутки. Чтобы скрытый элемент всегда был либо полностью виден, либо полностью скрыт (и не оставался в частично прокрученном состоянии), добавьте
scroll-snap-type: y mandatoryв контейнер прокрутки иscroll-snap-align: startкак в скрытый элемент, так и в элемент основного контента.
Пример кода: потяните, чтобы открыть поиск
/**
* ANCESTOR: Define the scroll container.
* Scroll snapping ensures the search bar is always
* either fully visible or fully hidden.
*/
.scroll-container {
height: 100vh;
overflow-y: auto;
scroll-snap-type: y mandatory;
}
/**
* HIDDEN ELEMENT: The search bar hidden above the fold on load.
* It has scroll-snap-align so it snaps into place when pulled down.
*/
.search-bar {
height: 60px;
scroll-snap-align: start;
}
/**
* MAIN CONTENT + TARGET: The element the user sees first.
* scroll-snap-align makes it a valid snap point.
* scroll-initial-target tells the browser to scroll here on
* initial render, hiding the search bar above it.
*/
.main-content {
scroll-snap-align: start;
scroll-initial-target: nearest;
}
Стратегическое внедрение и рекомендации
- РЕКОМЕНДУЕТСЯ использовать
scroll-initial-target: nearest, если вы хотите привлечь внимание пользователя к определенной части прокручиваемой области при загрузке и намеренно скрыть периферийные элементы интерфейса, например строку поиска в самом верху. - НЕ путайте его с фокусом специальных возможностей. Это свойство перемещает только визуальную область просмотра, но не фокус клавиатуры. Если целевой элемент должен быть начальной точкой для пользователей клавиатуры, вам нужно вручную управлять
element.focus(). - НЕ используйте это свойство, если вам нужна плавная анимация прокрутки при загрузке. Оно является дискретным и мгновенно задает позицию на этапе макета.
- НЕ устанавливайте
scroll-initial-targetдля нескольких элементов в одном прокручиваемом контейнере. Если атрибутscroll-initial-target: nearestуказан для нескольких элементов, браузер выберет тот, который находится выше в дереве DOM. - УЧИТЫВАЙТЕ иерархию приоритетов. Фрагмент URL (например,
example.com/#top) и свойствоscroll-startна уровне контейнера имеют приоритет надscroll-initial-target.
Резервная стратегия
Для браузеров, которые пока не поддерживают API, используйте резервный вариант JavaScript. Обратите внимание, что для раскрытия контента при перетаскивании основной контент должен быть привязан к start (верхней части) контейнера.
/**
* Progressive Enhancement Fallback
*/
document.addEventListener("DOMContentLoaded", () => {
// Check for native CSS support
if (!CSS.supports("scroll-initial-target", "nearest")) {
const targetContent = document.querySelector('.main-content.target');
if (targetContent) {
// Use behavior: "instant" to mimic the native CSS behavior
// 'block: start' should match your CSS 'scroll-snap-align' (or expected top position)
targetContent.scrollIntoView({ behavior: 'instant', block: 'start' });
}
}
});