Понимание вьюпорта WebView в iOS 11

Перевод статьи Understanding the WebView Viewport in iOS 11 с сайта ayogo.com для CSS-live.ru, автор — Дэррил Пог

Понимание вьюпорта WebView в iOS 11

iOS 11 представила новое, — пожалуй, неинтуитивное — поведение, связанное со статус-баром. Оно имеет особое значение для тех, кто разрабатывает приложения при помощи инструментов вроде Apache Cordova и Ionic. В частности, изменение затрагивает веб-приложения под iOS11, использующие фиксированное позиционирование верхней панели навигации. Эта статья поможет понять вьюпорт WebView в iOS 11.

Примечание: уже существующие приложения продолжат работать так, как всегда работали — без изменений в поведении их вьюпорта. Нововведение затрагивает только приложения, скомпилированные при помощи Xcode 9 и предназначенные для iOS 11.

Чтобы понять это изменение, посмотрим на его контекст.

Статус-бары и безопасные зоны

В ранних версиях iOS статус-бар был просто черной полосой через верхнюю часть экрана и обычно не реагировал на касания. Он был частью системного интерфейса, и приложение запускалось в пространстве под ним.

Это изменилось с выходом iOS 7, у которой был прозрачный статус-бар. Он принимал цвет верхней панели навигации приложения. Для приложений, отображающихся в WebView, наподобие Cordova, это часто означало определение версии iOS и добавление 20px верхнего отступа к фиксированной верхней панели навигации. Таким образом, она вставала правильно.

Последующие версии iOS представили небольшие доработки. В их числе была такая особенность: во время звонка в статус-баре мог отображаться дополнительный баннер, а также когда приложение фоново использовало геолокацию.

В нативных приложениях это во многом автоматически управлялось стандартными средствами: UINavigation Bar (управление панелью навигации) и autolayout (авто-выравнивание). Были инструменты выравнивания верхней и нижней части экрана, которые автоматически подстраивали их под высоту статус-бара (-баров). Они проверяли, что контент приложения находится в безопасной зоне, и статус-бар его не перекроет. Если имелась панель навигации UINavigation Bar, выровненная по верхнему краю, то iOS автоматически добавляла ее цвет в качестве фона статус-бара. Для веба, к сожалению, не было такого эквивалента.

Изменения в iOS 11

iPhone 8 c iOS 11

Поведение вьюпорта по умолчанию в iOS 11 на iPhone 8

Отличие iOS 11 от более ранних версий состоит в том, что контент WebView теперь учитывает безопасные зоны. Это значит, что если имеется фиксированная панель навигации со свойством top: 0, то она по умолчанию отрисуется на 20px ниже верхнего края экрана — выровненная по нижнему краю статус-бара. При прокрутке вниз она сдвинется наверх, под статус-бар. При прокрутке вверх она снова выпадет прямо под статус-баром (оставляя нелепый зазор в 20px, через который проглядывает контент).

Вы можете убедиться, насколько это плохо, в этом видео:

Очень странное поведение скролла в iOS 11 для элементов с фиксированным позиционированием

Почему вообще Apple внесли такое изменение?

Если вы видели дизайн iPhone X, то цель изменения понятна. У iPhone X нестандартная форма экрана с выемкой наверху для динамика и камеры. Если фиксированные элементы выровнять по реальному верхнему краю экрана, то они станут недоступными позади этой выемки.

Выравнивание по нижнему краю статус-бара гарантирует, что всё, что находится в панели навигации, будет доступным.

Круто… Не считая того, что теперь приложения выглядят ужасно со странной верхней панелью навигации, двигающейся вверх и вниз, и контентом, который проглядывает через статус-бар во время прокрутки.

Фиксы iOS 11

К счастью, Apple дали нам способ управлять этим поведением при помощи мета-тега viewport. И даже больше — они портировали фикс нового поведения вьюпорта для прежнего, устаревшего UIWebView!

Свойство мета-тега viewport, которое нам нужно, — это viewport-fit. Оно имеет три возможных значения:

  • contain: вьюпорт должен полностью вмещать веб-контент. Тогда фиксированные элементы будут содержаться внутри безопасной зоны на iOS 11.
  • cover: веб-контент должен полностью покрывать вьюпорт. Тогда фиксированные элементы будут зафиксированы во вьюпорте. Даже в тех случаях, когда это означает, что они будут перекрыты. Это восстанавливает поведение, которое было при iOS 10.
  • auto: значение по умолчанию, в этом случае поведение веб-контента такое же, как при contain.

Таким образом, чтобы вернуть панель навигации к самому верху экрана, за статус-бар, как это было на iOS 10, следует добавить в мета-тег viewport свойство viewport-fit=cover.

iPhone 8 с iOS 11

Всё в порядке в iOS 11 на iPhone 8, когда свойство viewport-fit имеет значение cover

iPhone X

Но что насчет iPhone X с его нестандартной формой? Статус-бар больше не имеет высоту 20px. Из-за выемки для камеры и динамика содержимое верхней панели навигации будет полностью недоступным для пользователей. Важно отметить, что это также относится и к нижней панели навигации, прикрепленной к низу экрана, которая будет перекрыта микрофоном.

Примечание: приложение использует все пространство экрана на iPhone X только в том случае, если у вас есть сториборд для экрана загрузки. Уже существующие приложения будут показаны в контейнере просмотра с черным пространством сверху и снизу.

iPhone X с iOS 11

На iPhone X уже появляется проблема, даже при том же значении cover у свойства viewport-fit

К счастью, Apple добавили способ управлять выравниванием безопасной зоны через CSS. Они ввели новое понятие, похожее на CSS-переменные, изначально названное CSS-константами. Вы можете представить их как системно заданные CSS-переменные, которые нельзя переопределить. Они были предложены Рабочей группе CSS для стандартизации. Она приняла предложение, но с условием: для доступа к этим константам нужно будет использовать функцию с названием env() вместо constant(). (Изначально Apple предложили название constant() — прим. переводчика.)

Примечание: iOS 11 использует синтаксис с constant(), но последующие версии операционной системы будут поддерживать только env()!

Четыре константы для управления раскладкой безопасных зон — это:

  • env(safe-area-inset-top): значение отступа безопасной зоны (в CSS-пикселах), считая от верхнего края вьюпорта.
  • env(safe-area-inset-bottom): значение отступа безопасной зоны (в CSS-пикселах), считая от нижнего края вьюпорта.
  • env(safe-area-inset-left): значение отступа безопасной зоны (в CSS-пикселах), считая от левого края вьюпорта.
  • env(safe-area-inset-right): значение отступа безопасной зоны (в CSS-пикселах), считая от правого края вьюпорта.

И, в качестве последнего подарка для нас, Apple портировало эти переменные для UIWebView.

Пример с CSS-константами

Скажем, есть фиксированная верхняя панель навигации, и CSS для iOS 10 сейчас выглядит так:

header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 44px;

    padding-top: 20px; /* Высота статус-бара */
}

Чтобы она автоматически подстраивалась под iPhone X и другие устройства на iOS 11, надо добавить свойство viewport-fit=cover в мета-тег viewport и изменить CSS с обращением к константе:

header {
    /* ... */
    
    /* Высота статус-бара в iOS 10 */
    padding-top: 20px;

    /* Высота статус-бара в iOS 11.0 */
    padding-top: constant(safe-area-inset-top);

    /* Высота статус-бара в iOS 11+ */
    padding-top: env(safe-area-inset-top);
}

Важно, чтобы для старых устройств, не понимающих синтаксис constant() или env(), осталось страховочное значение. Можно также использовать константы в CSS-функции calc().

Проблема iPhone X с iOS 11 решена

Проблема на iPhone X решена через добавление отступа в зависимости от устройства

Также не стоит забывать делать то же самое для нижней панели навигации.

Особое спасибо Тимоти Хортону из команды WebKit в Apple за внедрение функций constant()/env(), которые мы обсуждали в этой статье. Спасибо Шазрон, Хулио, Керри, Грегу и Майку за помощь в тестировании и проверке некоторых из описанных в статье поведений.

P.S. Это тоже может быть интересно:

1 Комментарий
  1. Александр

    Вначале придумать, проблему, а затем ее решить. (И получить как с градиентом двойной синтаксис)
    Тогда нужно и под выпуклость экрана тоже ключевые слова предусмотреть, чтобы потом не было новой sypercontant(safe-area-outside-top).

Добавить комментарий для Александр Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.