Что такое safe area — и почему одно слово в meta-теге прячет кнопку под вырез

Вот неожиданная вещь. Safari на iPhone по умолчанию сам отодвигает твой сайт от выреза с камерой и скруглённых углов. Поля по краям он заливает цветом фона страницы. Ты даже не знаешь, что тебя страхуют.
А потом в <meta name="viewport"> появляется одно слово — viewport-fit=cover. Ради картинки во весь экран или ради того, чтобы Chrome на Android не показывал лишнюю полоску снизу. И страховка выключается. Нижняя панель уходит под полоску «домой», в горизонтальной ориентации текст залезает под вырез.
Чтобы этого не было, есть safe area — безопасная зона экрана.
Что это такое простыми словами
Safe area — прямоугольник внутри экрана, где контент гарантированно виден. Его не закрывают скругления углов, вырез с камерой, полоска жестов и системные панели.
Браузер сообщает размеры этой зоны четырьмя отступами — сверху, справа, снизу и слева. MDN объясняет: если экран прямоугольный и ничего не мешает, все четыре равны нулю. Если мешает — это число пикселей, на которое нужно отступить.
Представь фото в рамке с паспарту. Картинка может занимать весь лист, но важное должно оставаться внутри окошка.
Как это работает
За поведение отвечают две вещи.
Первая — ключ viewport-fit в meta-теге. Значение по умолчанию auto: браузер сам ужимает страницу в безопасную зону. Значение cover растягивает страницу на весь экран, до самых краёв.
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
Вторая — функция env() в CSS. Она достаёт готовые отступы: safe-area-inset-top, safe-area-inset-right, safe-area-inset-bottom и safe-area-inset-left. Появилась она в iOS 11 в 2017 году, вместе с первым iPhone с вырезом. Сейчас её понимают все современные браузеры — по данным MDN, с января 2020 года.
Типичная нижняя панель выглядит так:
.bottom-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 12px 16px;
padding-bottom: max(12px, env(safe-area-inset-bottom));
}
Обрати внимание на max(). Команда WebKit объясняла: безопасный отступ — это не замена обычному. В портретной ориентации отступ слева равен нулю, и текст прилипнет к краю. max() берёт большее из двух: твои 12 пикселей или отступ от выреза.
Та же логика для шапки и для боков. Закреплённая сверху панель в приложении с главного экрана получает padding-top: env(safe-area-inset-top). А в горизонтальной ориентации вырез оказывается слева или справа — пример из статьи WebKit:
.content {
padding-left: max(12px, env(safe-area-inset-left));
padding-right: max(12px, env(safe-area-inset-right));
}
Отступы меняются сами, когда человек поворачивает телефон. Пересчитывать ничего не нужно.
Это не только про iPhone
Скругления, вырезы и полоска жестов есть и на Android. С версии 135 Chrome на Android умеет рисовать страницу под навигационной полосой внизу. По умолчанию он показывает над ней свою полоску — Google называет её «подбородком». Она уезжает при прокрутке. А с viewport-fit=cover подбородка нет вовсе, и страница сразу доходит до нижнего края.
Документация Chrome прямо предупреждает: элемент с position: fixed; bottom: 0 в таком режиме может оказаться под навигационной полосой. Лечится тем же env(safe-area-inset-bottom).
Когда ты с этим встретишься
- Нижняя панель навигации или кнопка «Купить», прилипшая к низу экрана.
- Строка ввода в чате, закреплённая снизу.
- Картинка или видео во весь экран на первом экране.
- Горизонтальная ориентация iPhone — вырез оказывается сбоку и режет текст слева или справа.
- Сайт, открытый с главного экрана как приложение: панели браузера нет, и низ экрана ничем не прикрыт.
Если просишь ИИ сверстать мобильный экран с закреплённой панелью, добавь в запрос: «учти safe area через env(safe-area-inset-bottom) и max()». Иначе панель легко окажется под полоской жестов.
Проверять надёжнее на настоящем телефоне, в обеих ориентациях: поверни его боком и посмотри, не залез ли текст под вырез. Если у тебя есть Mac, WebKit советовал ещё один путь — симулятор iPhone из Xcode: вырез и полоска жестов там настоящие. Базовую настройку viewport мы разбирали в статье как сделать сайт адаптивным. А если у тебя экран на 100vh и низ всё равно обрезан — это отдельная история: почему 100vh выше экрана на телефоне.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.
Нужна ли safe area, если я не ставил viewport-fit=cover?
Чаще всего нет: Safari сам отодвинет страницу. Но проверь цвет полей по бокам. Их заливает фон <body> или <html>, и если он не совпадает с шапкой, появятся заметные полосы.
Что будет в браузере, который не знает env()?
Он проигнорирует всё правило целиком. Поэтому строкой выше пиши обычный отступ — как в примере с padding и padding-bottom. Ещё у env() есть второй аргумент для запасного значения: env(safe-area-inset-bottom, 0px).
Почему env() возвращает ноль?
Чаще всего так и должно быть. MDN объясняет: на прямоугольном экране, где ничего не мешает, все отступы равны нулю — например, на компьютере. А в портретной ориентации iPhone нулевые боковые отступы: вырез сверху. Проверяй на телефоне и поворачивай его боком.
Это нужно и для нативного приложения?
В нативных приложениях у каждой платформы свои инструменты для безопасной зоны. env() нужен, когда интерфейс — это веб-страница: сайт, PWA или веб-приложение внутри обёртки.





