Safari и тестирование

CSS overscroll-behavior в 2026 году: вложенные области прокрутки, модальные окна, утечка pull-to-refresh, статический маркетинговый HTML и QA WebKit Safari на облачном Mac mini

MacHTML Lab2026.04.27около 31 мин

Длинные статические страницы наслаивают документный скроллер, липкое оглавление с собственным островом 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. Записи экрана для дизайна, если полноэкранное видео остаётся за модалками.

  1. Открыть модалку, прокрутить с рывком до конца—фон не двигается.
  2. Повторить с VoiceOver/TalkBack, фокус внутри модалки.
  3. Ресайз 1280px320px; проверить переключения media query.
  4. Замерить CLS; связать с scrollbar-gutter против скачков ширины.
  5. Прыжок к якорю футера с 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, чтобы валидировать цепочку, слои диалогов и навигацию по якорям вместе.

Устранить утечку скролла Safari
от 16,9 $/сутки