Олег Марков
Атрибут viewport в HTML - полный разбор для разработчиков
Введение
Атрибут viewport в HTML играет ключевую роль в адаптивной верстке. Без него сайт на мобильном устройстве почти всегда будет выглядеть неправильно: слишком мелкий текст, неудобный зум, смещенные элементы.
Вам как разработчику важно понимать, что meta-тег viewport не просто "магическая" строка для копирования из чужих проектов. Он задает правила того, как браузер должен:
- интерпретировать ширину страницы;
- рассчитывать масштаб при первой загрузке;
- разрешать или запрещать пользователю менять масштаб;
- реагировать на поворот экрана и изменения размеров окна.
Давайте пошагово разберем, как работает атрибут viewport, какие параметры он поддерживает, какие комбинации значений использовать безопасно, а каких лучше избегать.
Что такое viewport в контексте браузера
Понятие viewport
Viewport — это область окна браузера, в которой отображается веб-страница. Проще говоря, это видимая пользователю часть документа без прокрутки.
Важно отличать три величины:
- Ширина экрана устройства — физическое количество пикселей дисплея (например, 1080 px).
- CSS-пиксели — логические пиксели, которыми вы оперируете в стилях.
- Viewport — "логическое окно", через которое страница видна пользователю.
На десктопе все относительно просто: ширина viewport обычно совпадает с шириной окна браузера в CSS-пикселях. На мобильных устройствах все сложнее: исторически браузеры рендерили страницы так, как будто ширина экрана около 980 пикселей, чтобы старые неадаптивные сайты помещались "как на десктопе", но в уменьшенном виде.
Вот здесь и вступает в работу meta-тег viewport.
Meta-тег viewport: базовая форма
Определение viewport происходит через тег в секции <head>:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Другие meta-теги и стили -->
</head>Комментарии к этому коду:
<meta
name="viewport" <!-- Говорим браузеру, что это настройки viewport -->
content="width=device-width, <!-- Ширина viewport = ширине устройства -->
initial-scale=1.0"> <!-- Начальный масштаб = 1 -->Смотрите, этот тег сообщает браузеру, что:
- нужно подстроить "логическую" ширину страницы под ширину устройства;
- отображать страницу без изначального уменьшения или увеличения.
Без этого тега мобильный браузер часто решает, что страница шириной около 980 CSS-пикселей, и масштабирует ее, чтобы она уместилась, делая текст мелким.
Синтаксис и параметры атрибута viewport
Общий синтаксис content
Атрибут content принимает список пар "ключ=значение", разделенных запятыми:
<meta name="viewport" content="key1=value1, key2=value2, key3=value3">Пробелы после запятых не обязательны, но делают код читаемее.
Наиболее часто используются:
widthheightinitial-scaleminimum-scalemaximum-scaleuser-scalableviewport-fit(актуально для "вырезов" на экране, например, iPhone с выемкой)
Давайте разберем каждый параметр по отдельности.
Параметр width
width определяет логическую ширину viewport в CSS-пикселях.
Поддерживаемые значения:
device-width— ширина экрана устройства в CSS-пикселях;- конкретное число, например
320,768,1024.
Примеры:
<!-- Адаптивный вариант. Используется чаще всего -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Жестко зафиксированная ширина -->
<meta name="viewport" content="width=1024">Комментарии:
<!-- width=device-width
Ширина viewport = текущей ширине устройства (с учетом ориентации) -->
<!-- width=1024
Браузер будет считать, что страница шириной 1024 CSS-пикселя,
и масштабировать ее под экран. Это плохо для адаптивной верстки. -->Использование фиксированной ширины (например, width=1024) может пригодиться только в очень специфичных админках или внутренних системах, где вы точно знаете, на каких экранах все открывается. В современной адаптивной верстке почти всегда используется width=device-width.
Параметр height
height работает по аналогии с width, но применяется гораздо реже:
<meta name="viewport" content="height=device-height, width=device-width">Комментарии:
<!-- height=device-height
Указывает, что высота viewport равна высоте экрана устройства -->На практике этот параметр почти не нужен: браузеры сами корректно рассчитывают высоту с учетом статус-бара, панели навигации и других элементов.
Чаще всего height либо вообще не указывают, либо игнорируется браузером. Об этом стоит помнить: вы можете его прописать, но особых гарантий поведения нет.
Параметр initial-scale
initial-scale задает начальный масштаб страницы при первой загрузке. Это отношение CSS-пикселей к реальным пикселям экрана.
На практике:
initial-scale=1.0— базовый рекомендуемый вариант;- значения выше 1.0 увеличивают содержимое;
- значения ниже 1.0 уменьшают содержимое.
Пример:
<meta name="viewport" content="width=device-width, initial-scale=1.0">Комментарии:
<!-- initial-scale=1.0
1 CSS-пиксель примерно равен 1 "виртуальному" пикселю экрана
(с учетом плотности пикселей и масштабирования браузера) -->Вы можете встретить:
<meta name="viewport" content="width=device-width, initial-scale=0.5">Но такой код делает страницу визуально уменьшенной, что делает чтение неудобным. В адаптивной верстке стремятся не уменьшать масштаб, а перестраивать layout через CSS (flex, grid, media queries).
Параметры minimum-scale и maximum-scale
Эти параметры задают допустимый диапазон масштабирования:
minimum-scale— минимальный масштаб;maximum-scale— максимальный масштаб.
Пример:
<meta name="viewport" content="width=device-width, initial-scale=1.0,
minimum-scale=1.0, maximum-scale=3.0">Комментарии:
<!-- minimum-scale=1.0
Пользователь не сможет уменьшить масштаб меньше 1.0 -->
<!-- maximum-scale=3.0
Пользователь сможет увеличить масштаб максимум до 3.0 раз -->Смотрите, эти параметры напрямую влияют на доступность. Ограничивая масштабирование слишком жестко, вы мешаете пользователям с нарушениями зрения увеличивать контент.
С точки зрения UX и требований доступности рекомендуется:
- не ограничивать масштаб вообще;
- либо не ставить слишком жесткие рамки (например, минимум 0.5, максимум 5).
Параметр user-scalable
user-scalable управляет тем, может ли пользователь вообще менять масштаб (жесты pinch-to-zoom на мобильных устройствах).
Возможные значения:
user-scalable=yes— масштабирование разрешено (значение по умолчанию);user-scalable=no— масштабирование запрещено.
Пример:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">Комментарии:
<!-- user-scalable=no
Пользователь не сможет уменьшать или увеличивать страницу жестами зума.
Это ухудшает доступность и обычно не рекомендуется. -->Даже если иногда хочется "запретить" зум для отдельных интерфейсов (например, мобильных игр или сложных интерактивных панелей), лучше хорошенько взвесить последствия. Для обычных сайтов, блогов, интернет-магазинов зум всегда лучше оставить включенным.
Параметр viewport-fit (для устройств с "вырезами")
viewport-fit используется в основном на устройствах с вырезами и закругленными углами экрана (например, iPhone с notch). Этот параметр управляет тем, как страница занимает пространство экрана.
Основные значения:
auto— поведение по умолчанию;contain— контент вписывается в "безопасную область";cover— контент растягивается на всю область экрана, включая "опасные зоны".
Пример:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">Комментарии:
<!-- viewport-fit=cover
Разрешает странице растягиваться под весь экран, включая области
под вырезами и закруглениями. Дальше вы уже через CSS учитываете safe-area. -->Обычно viewport-fit=cover комбинируется с использованием CSS-переменных типа env(safe-area-inset-top) для отступов, чтобы элементы не "уползали" под вырез.
Типичные конфигурации meta viewport
Базовая и рекомендованная конфигурация
Наиболее распространенный и рекомендуемый вариант для адаптивной верстки:
<meta name="viewport" content="width=device-width, initial-scale=1.0">Почему именно так:
- страница адаптируется под ширину устройства;
- нет принудительного зума или уменьшения;
- пользователь может масштабировать страницу при необходимости.
Если вам не нужны специфические эффекты вроде запрета увеличения или сложного управления масштабами, этого тега достаточно в 90 процентах случаев.
Конфигурация с ограничениями масштаба
Иногда хотят ограничить масштаб, но не отключать его полностью:
<meta name="viewport" content="width=device-width, initial-scale=1.0,
minimum-scale=1.0, maximum-scale=2.0">Комментарии:
<!-- Пользователь сможет увеличить масштаб только до 2 раз.
Это спорное решение с точки зрения доступности. -->Используйте такую конфигурацию осознанно, проверяя, что текст остается читаемым для большинства пользователей.
Конфигурация с запретом зума (не рекомендуется)
Иногда встречается:
<meta name="viewport" content="width=device-width, initial-scale=1.0,
user-scalable=no">Проблема в том, что пользователю с плохим зрением вы тем самым лишаете возможность нормально читать текст. Сейчас многие гайды по доступности прямо рекомендуют не использовать user-scalable=no вообще.
Если вы видите такой код в проекте, стоит обсудить с командой, действительно ли это необходимо.
Конфигурация для устройств с вырезами
Для современных смартфонов с вырезами (notch) и закругленными углами часто используют:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">А затем подключают CSS:
/* Здесь мы добавляем отступы с учетом безопасной зоны */
.page {
padding-top: env(safe-area-inset-top); /* Отступ сверху */
padding-right: env(safe-area-inset-right); /* Отступ справа */
padding-bottom: env(safe-area-inset-bottom);/* Отступ снизу */
padding-left: env(safe-area-inset-left); /* Отступ слева */
}Комментарии:
/* env(safe-area-inset-*)
Переменные, которые браузер подставляет в зависимости от устройства
и положения выреза, чтобы контент не попадал "под" него. */Такой подход особенно важен для сайтов, оформленных как PWA или добавляемых "на главный экран" в iOS.
Как viewport влияет на адаптивную верстку
Связь с медиазапросами (media queries)
Медиазапросы в CSS (@media) используют значения ширины viewport. Если вы не настроите meta viewport, медиазапросы на мобильных устройствах будут работать не так, как вы ожидаете.
Например, смотрите такой код:
/* Стили по умолчанию для десктопа */
body {
font-size: 18px;
padding: 20px;
}
/* Стили для узких экранов */
@media (max-width: 600px) {
body {
font-size: 16px; /* Чуть уменьшаем текст */
padding: 10px; /* Уменьшаем отступы */
}
}Если на мобильном устройстве не задать:
<meta name="viewport" content="width=device-width, initial-scale=1.0">то:
- браузер будет считать, что ширина страницы условно 980 px;
- условие
(max-width: 600px)никогда не сработает; - "мобильные" стили не применятся.
Поэтому meta viewport — фактически обязательное условие для корректной работы responsive layout.
Пример: одна и та же страница с viewport и без него
Давайте посмотрим, как одна и та же простая страница выглядит с разными настройками.
HTML:
<head>
<title>Демо viewport</title>
<!-- Попробуйте включать и отключать эту строку по очереди -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>Тестовая страница</h1>
<p>Некоторый текст для проверки поведения viewport.</p>
</body>Если вы откроете эту страницу на смартфоне:
- Без meta viewport — страница будет "уменьшена", текст мелкий, все выглядит как уменьшенный десктоп;
- С meta viewport — текст станет нормального размера, страница займет всю ширину экрана, зум будет работать адекватно.
Этот пример хорошо показывает, зачем вообще нужен viewport.
Поддержка в браузерах и особенности поведения
Поддержка на мобильных устройствах
Meta-тег viewport поддерживается всеми современными мобильными браузерами:
- Safari (iOS);
- Chrome (Android, iOS);
- Firefox;
- Edge на мобильных;
- встроенные браузеры на Android.
Исторически именно мобильные браузеры ввели этот механизм, чтобы решить проблему отображения "десктопных" сайтов на маленьких экранах.
На десктопах meta viewport тоже распознается, но особого влияния не оказывает, так как масштаб и ширина по умолчанию уже достаточно "прямолинейны".
Особенности на iOS и Android
На iOS Safari есть нюансы с:
- поведением адресной строки и ее скрытием при прокрутке;
- расчетом высоты viewport (при обращении к
100vhв CSS); - использованием
viewport-fit=coverиsafe-area.
На Android Chrome аналогичные нюансы с высотой, но в общем поведение meta viewport довольно стабильное при корректном использовании width=device-width и initial-scale=1.0.
Если вы сталкиваетесь с "прыгающей" высотой блока с высотой 100vh при прокрутке, это связано не столько с meta viewport, сколько с особенностями UI браузера (скрытие/показ панелей). Но важно понимать, что viewport тоже участвует в этих расчетах.
Практические примеры и рекомендации по использованию
Пример 1: Стандартный адаптивный лендинг
Представим, вы делаете простой лендинг, который должен адекватно работать на мобильных и десктопах. В head вы пишете:
<head>
<meta charset="utf-8">
<title>Мой адаптивный лендинг</title>
<!-- Ключевая строка для мобильных -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
</head>Комментарии:
<!-- meta viewport гарантирует, что все дальнейшие медиазапросы
и процентные/относительные размеры будут работать ожидаемо
на мобильных устройствах. -->А далее в CSS:
/* Базовые стили для всех экранов */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 16px;
}
/* Мобильные устройства */
@media (max-width: 600px) {
.container {
padding: 8px; /* Меньше отступы на узких экранах */
}
}Без meta viewport этот @media будет почти бесполезен на смартфоне.
Пример 2: Приложение с PWA и учет вырезов
Если вы делаете PWA и ожидаете, что пользователь добавит приложение на домашний экран iOS, разумно добавить:
<head>
<meta charset="utf-8">
<title>Мое PWA-приложение</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<link rel="stylesheet" href="app.css">
</head>И в CSS:
.app-root {
/* Здесь мы учитываем "safe area" для устройств с вырезами */
padding-top: env(safe-area-inset-top); /* Не даем контенту уползти под статус-бар */
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
}Так вы гарантируете, что на iPhone с вырезом ваш верхний бар или кнопки не окажутся частично закрытыми.
Пример 3: Когда не нужно усложнять конфигурацию
Иногда можно встретить такие строки:
<meta name="viewport" content="width=device-width, height=device-height,
initial-scale=1.0, minimum-scale=1.0,
maximum-scale=1.0, user-scalable=no">Комментарии:
<!-- Это попытка "заставить" страницу быть фиксированной и не масштабируемой.
На практике:
- height часто игнорируется
- запрет user-scalable ухудшает доступность
- строгие minimum/maximum-scale могут мешать пользователям
-->Чаще всего, если у вас нет очень специфической задачи, стоит ограничиться простой и понятной конфигурацией:
<meta name="viewport" content="width=device-width, initial-scale=1.0">Так вы избежите лишних проблем и конфликтов с ожиданиями пользователей.
Частые ошибки при работе с viewport и как их избежать
Ошибка 1: Отсутствие meta viewport
Симптомы:
- сайт на смартфоне выглядит как уменьшенная десктопная версия;
- текст мелкий, приходится зумить;
- медиазапросы по ширине не срабатывают, хотя должны.
Решение:
Добавить в <head>:
<meta name="viewport" content="width=device-width, initial-scale=1.0">Ошибка 2: Слишком сложный или "агрессивный" viewport
Симптомы:
- пользователи жалуются, что не могут приблизить страницу;
- тесты на доступность ругаются;
- на разных устройствах или в разных браузерах масштаб ведет себя по-разному.
Пример проблемной конфигурации:
<meta name="viewport" content="width=device-width, initial-scale=1.0,
minimum-scale=1.0, maximum-scale=1.0,
user-scalable=no">Решение:
- убрать
user-scalable=no; - убрать или ослабить
minimum-scaleиmaximum-scale; - по возможности оставить только
width=device-width, initial-scale=1.0.
Ошибка 3: Противоречивые значения
Иногда пишут что-то вроде:
<meta name="viewport" content="width=1024, initial-scale=1.0, width=device-width">При этом:
- значение
widthуказано дважды; - поведение разных браузеров может отличаться (кто-то возьмет первое значение, кто-то второе).
Решение:
- не дублировать один и тот же ключ;
- оставить только одно однозначное значение.
Ошибка 4: Ожидание, что viewport "починит" верстку
Иногда есть ожидание: "Сейчас добавим meta viewport — и верстка станет адаптивной". Но meta viewport только задает правила масштабирования и считает ширину. Сам layout вы все равно должны адаптировать через:
- flex и grid;
- медиазапросы;
- относительные единицы (
%,vw,vh,rem).
Если сайт изначально сделан "жесткой" фиксированной ширины, один только meta viewport не решит все проблемы.
Ошибка 5: Непонимание роли device-width
Иногда разработчики думают, что device-width — это физическое количество пикселей матрицы устройства (например, 1080). На самом деле это логическая ширина в CSS-пикселях.
Например:
- у смартфона с физической шириной 1080 px и плотностью 3x логическая ширина может быть 360 CSS-пикселей;
width=device-widthв таком случае даст 360, а не 1080.
Браузер сам учитывает плотность пикселей (device pixel ratio). Вам для верстки достаточно именно логических CSS-пикселей.
Заключение
Атрибут viewport в HTML — это фундаментальный инструмент для любой современной адаптивной верстки. Он управляет тем, как браузер интерпретирует ширину страницы, рассчитывает масштаб и позволяет (или запрещает) пользователю изменять зум.
Основные моменты, которые стоит запомнить:
- почти во всех реальных проектах достаточно использовать конфигурацию
width=device-width, initial-scale=1.0; - запрещать масштаб (
user-scalable=no) и слишком жестко ограничивать его обычно не стоит из-за доступности; - фиксированную ширину (
width=1024и подобные значения) лучше не использовать для публичных сайтов; viewport-fit=coverнужен, если вы нацелены на полноэкранный опыт на устройствах с вырезами и закругленными краями;- meta viewport не делает верстку адаптивной сам по себе, а лишь создает корректные условия, в которых медиазапросы и относительные единицы работают ожидаемо.
Понимая, как устроен viewport и как его настраивать, вы можете делать сайты, которые корректно и предсказуемо отображаются на самых разных устройствах.
Частозадаваемые технические вопросы по теме
Как сделать так, чтобы сайт вел себя по-разному в портретной и ландшафтной ориентации через viewport
Через сам meta viewport напрямую это не делается. Ориентацию обычно учитывают в CSS через медиазапросы:
/* Портретная ориентация */
@media (orientation: portrait) {
/* Стили для вертикальной ориентации */
}
/* Ландшафтная ориентация */
@media (orientation: landscape) {
/* Стили для горизонтальной ориентации */
}Viewport в этом случае просто обеспечивает корректную ширину и масштаб.
Можно ли динамически менять meta viewport через JavaScript
Да, можно. Например:
// Находим существующий тег viewport
const meta = document.querySelector('meta[name="viewport"]');
// Меняем его содержимое
meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=2.0');Но злоупотреблять этим не стоит. Динамическая смена viewport может вызывать "прыжки" интерфейса и раздражать пользователя. Обычно это оправдано только в особых сценариях (например, включение режима "просмотра изображения" с отличным масштабом).
Почему height=device-height часто не дает эффекта
Многие браузеры либо игнорируют height в meta viewport, либо интерпретируют его по-своему. Высота viewport сильно зависит от интерфейса браузера (адресная строка, нижняя панель). Для контроля высоты чаще используют CSS (vh, calc, учет safe-area) вместо попыток управлять этим через meta viewport.
Как проверить, какое значение width реально установлено для viewport
Самый простой способ — использовать JavaScript в консоли браузера:
// Показываем текущую ширину viewport в CSS-пикселях
console.log(window.innerWidth); // Ширина внутренней области окна
console.log(document.documentElement.clientWidth); // Ширина области документаЕсли meta viewport настроен как width=device-width, то это значение и будет вашей логической шириной для медиазапросов и верстки.
Что делать, если 100vh ведет себя странно на мобильных, хотя viewport задан корректно
Поведение 100vh на мобильных браузерах связано с панелями интерфейса (адресная строка, нижние панели), которые могут появляться и исчезать при прокрутке. Meta viewport тут не все контролирует.
Практическое решение:
- использовать
min-height: 100vhосторожно; - при необходимости вычислять высоту через JavaScript:
// Определяем высоту окна и сохраняем в кастомную переменную
const setAppHeight = () => {
const doc = document.documentElement;
doc.style.setProperty('--app-height', `${window.innerHeight}px`);
};
window.addEventListener('resize', setAppHeight);
setAppHeight();И в CSS:
/* Используем переменную вместо 100vh */
.app {
min-height: var(--app-height);
}Так вы подстраиваете высоту под фактическую видимую область, не полагаясь только на vh.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

HTML и CSS
Антон Ларичев
TypeScript с нуля
Антон Ларичев