Длинные статические страницы наслаивают документный скроллер, липкое оглавление с собственным островом overflow:auto и модалки, которые не должны передавать импульс странице позади или красть резиновую обратную связь. Без явного контроля WebKit цепляет перерасход прокрутки от самого внутреннего контейнера к предкам: фоновый скролл, промахи по CTA и шум метрик Lighthouse. В 2026 году ставьте overscroll-behavior: contain на нужные контейнеры вместе с правилами из scrollbar-gutter: stable и scroll-padding для фиксированных шапок, чтобы цепочка, резерв полосы и якоря вели себя согласованно в Safari и на iOS.
Прогон этих сценариев на арендованном Mac mini у MacHTML примерно за 16,9 $/сутки ловит iOS-особенности импульса, которые десктопная автоматизация Chromium в CI воспроизводит ненадёжно.
Цепочка прокрутки и поведение по умолчанию
Цепочка означает: вложенный скроллер уперся в край, дельты колеса или касания идут к предкам. Маркетинговые сайты это ненавидят—пользователь крутит прайс, а уезжает герой с видео. Desktop Safari и iOS WebKit цепляют по умолчанию; Chromium тоже—одно исправление помогает везде.
Не вешайте overflow: hidden на body при открытой модалке: ломаете паттерны блокировки фона на iOS и доступность. Лучше overscroll-behavior-y: contain на панели модалки и overscroll-behavior-x: none, если горизонтальные карусели не должны вызывать жесты истории.
Дизайн-система должна явно назначать «владельца прокрутки», иначе обёртки и дети получат противоречивые утилиты при каждом редизайне.
overscroll-behavior: contain на теле модалки
Применяйте к элементу, которому реально принадлежат полосы прокрутки:
.modal__body {
max-height: min(70vh, 640px);
overflow: auto;
overscroll-behavior: contain;
}
Contain останавливает цепочку, но позволяет менять позицию внутри модалки. На iOS с горизонтальными слайдерами добавьте touch-action: pan-y.
У нативного <dialog> фон не наследует ваши классы—дублируйте правила на диалог и внутренний скроллер, если оба могут быть в фокусе.
Аудиты WCAG проверяют, должен ли фокусироваться сам body модалки или обёртка с role="dialog"—это меняет клавиатурное поведение.
Когда none безопаснее contain
none, если нужно отключить pull-to-refresh в Android WebView-гибридах или если горизонтальные графики аналитики не должны вызывать жесты «назад». Тяжелее: пропадают полезные эффекты перерасхода—сначала пробуйте contain.
Карты и дашборды на canvas часто требуют none на обеих осях, чтобы перетаскивание оставалось локальным.
Команды безопасности следят, чтобы none не блокировал ожидаемую навигацию пользователя.
auto и явные сбросы на брейкпоинтах
На широком экране оглавление не крутится; на узком становится overflow:auto. Включайте overscroll только когда появляется вложенный скроллер:
@media (max-width: 900px) {
.toc { overflow: auto; overscroll-behavior: contain; max-height: 40vh; }
}
Забытый сброс contain после смены вёрстки—классическая регрессия: десктоп QA зелёный, мобильный теряет нужную цепочку к документу.
Изолированные сторибуки без родительского документа врут; добавьте интеграционные тесты на полный вьюпорт.
iOS Safari, touch-action и пассивные слушатели
iOS жёстко связывает инерционный скролл с распознавателями жестов. Если аналитика ставит пассивные слушатели колеса, но ждёт preventDefault, CSS не спасёт. Аудит третьих сторон; пусть браузер владеет скроллом.
Тестируйте на дисплеях 120 Гц ProMotion: меньшие контейнеры тормозят быстрее, цепочка ощущется резче.
Удалённая отладка через Safari Web Inspector на арендованном Mac mini ближе к реальным iPhone, чем только симуляторы.
Доступность: ловушки фокуса и прокрутка
Модалки с ловушкой фокуса должны делать прокручиваемую область доступной с клавиатуры и стрелок. Пользователи скринридеров страдают, когда цепочка двигает фон и смещает доступные имена.
prefers-reduced-motion не отключает overscroll-behavior; снижайте max-height, чтобы не заставлять гигантскую глубину прокрутки.
Документируйте, кто несёт role="dialog", а какой потомок получает tabindex="0" при программном открытии.
QA: фокус внутри тела, колесо не крутит фон, даже если кольцо фокуса на body не видно.
Производительность, композитинг и ловушки will-change
Сам overscroll-behavior дёшев, но его смешивают с backdrop-filter и will-change: transform, что на Mobile Safari добавляет слои GPU. Смотрите вкладку слоёв WebKit; если старые iPad превышают ~512 МБ, упрощайте тени.
Не ставьте глобально will-change: scroll-position на каждую карточку—только пока модалка открыта.
Анимации, управляемые скроллом документа, могут конфликтовать с внутренними скроллерами без цепочки; перенесите цель анимации внутрь при необходимости.
Маркетинг любит параллакс—проверяйте края overscroll до продакшена.
Печатные стили и экспорт PDF
Комплаенс-PDF всё ещё печатают со статических страниц. В @media print верните overscroll к auto, чтобы движки PDF не обрезали контент по max-height модалки. Прячьте подложки диалогов, восстанавливайте overflow документа.
Headless Chromium PDF ведёт себя иначе, чем интерактивный Safari; держите print-CSS вроде .modal { position: static; max-height: none; overflow: visible; overscroll-behavior: auto; }.
Сравнивайте число страниц PDF до/после вложенного contain—рост часто значит, что карусель не схлопывается в печати.
Юристы иногда требуют полноты текста; print-CSS—часть цепочки доказательств.
Матрица: contain, none, auto
| Паттерн UI | Рекомендация | Заметки |
|---|---|---|
| Юридический текст в модалке | contain | Герой не уезжает |
| Вложенная таблица данных | contain на сетке, документ auto | Скролл страницы, если сетка не в фокусе |
| Карусель с риском истории | none на оси | Android WebView отдельно |
| Полноэкранная карта | none | Проверить pinch-zoom |
Чеклист перед релизом
Гоняйте на минимально поддерживаемом iOS и свежем Safari Technology Preview, чтобы поймать ужесточения семантики WebKit. Записи экрана для дизайна, если полноэкранное видео остаётся за модалками.
- Открыть модалку, прокрутить с рывком до конца—фон не двигается.
- Повторить с VoiceOver/TalkBack, фокус внутри модалки.
- Ресайз 1280px → 320px; проверить переключения media query.
- Замерить CLS; связать с scrollbar-gutter против скачков ширины.
- Прыжок к якорю футера с scroll-padding; overscroll в TOC не должен красть финиш прыжка.
Корпоративные команды, выкатывающие статические лендинги в десятки локалей, должны поднять правила overscroll в центральный пакет токенов, чтобы переводчики не изобретали расходящиеся утилиты. Зеркальные RTL-раскладки (арабский, иврит) иногда меняют модель прокрутки браузера—добавьте явную строку QA для RTL в матрицу overscroll.
Если сторонние iframe встраивают модальный контент, помните: многие инструменты автоматизации не достают внутрь iframe; только реальный Safari на Mac mini позволяет увидеть bleed между родителем и iframe. Документируйте атрибуты sandbox партнёра, косвенно влияющие на touch-action.
Для внутренних админок с тысячами строк таблиц внутри модалок задайте бюджет производительности: считайте, как часто композитор создаёт слои при длинной модальной прокрутке и стабилизирует ли contain кадровую частоту; если нет—виртуализируйте или пагинируйте на сервере вместо одного лишь CSS.
Телеметрия: после открытия модалки логируйте, всплывают ли события колеса до document; Playwright может требовать ноль за 200 бросков.
Если продукт одновременно поддерживает пользовательские темы оформления и кастомные плотности пикселей, проверьте, не переопределяют ли сгенерированные CSS-переменные ваши overscroll-правила на вложенных контейнерах: тёмная тема иногда подмешивает дополнительные обёртки с собственным overflow, которые QA в светлой теме никогда не увидит.
Для редких кейсов с нативными жестами «назад» в PWA на iOS убедитесь, что none на оси X не ломает ожидаемый свайп из края экрана там, где Apple всё ещё резервирует системный жест; иногда достаточно сузить область жеста CSS-маской вместо глобального none на всём модальном слое.
Команды e-commerce, которые вставляют виджеты оплаты третьих сторон в модальные фреймы, должны отдельно прогонять overscroll-сценарии после каждого обновления скрипта виджета: поставщики часто меняют внутренние overflow и ломают ваш contain, даже если внешний маркетинговый слой не менялся месяцами.
Наконец, если вы комбинируете нативный скролл с виртуализированными списками внутри модалки, убедитесь, что библиотека виртуализации не переустанавливает overscroll на корневом контейнере при каждом батче элементов; иначе регрессии появятся только на длинных каталогах, а не на коротких демо-данных.
При смешении статического лендинга с небольшими островками реактивности проверьте, не сбрасывает ли гидратация React/Vue ваши overscroll-классы на клиенте после первого рендера: SSR-HTML может выглядеть идеально, а гидратированный DOM — уже без contain и с неожиданным bleed.
Mac mini у MacHTML (~16,9 $/сутки) даёт нативный Safari и Apple Silicon, чтобы воспроизводить вложенные скроллеры, ловушки фокуса и тайминг ProMotion в среде, близкой к дизайнерам.
Тестируйте overscroll и модалки на облачном Mac mini
SSH/VNC на выделенный macOS, чтобы валидировать цепочку, слои диалогов и навигацию по якорям вместе.