Что такое Viewport, как он работает и для чего вообще нужен

Создадим простую страничку с минимальной разметкой:

<!doctype html> 
<html> 
<head> 
    <title>Hello world!</title> 
</head> 
<body> 
    <p>Hello world!</p> 
</body> 
</html> 

Теперь откроем эту страничку на мобильном устройстве. Открыв, увидим, что наша страница отобразится примерно таким образом:

Как видно, текст слишком мелкий для чтения, есть куча пустого пространства, и для того, чтобы прочесть этот текст, нам нужно его увеличивать приближением.

Почему же так происходит?

Проблема мобильных браузеров

При сравнении мобильных и десктопных браузеров наиболее очевидное различие — размер экрана. Мобильные браузеры по-умолчанию отображают сайты, созданные для обычных десктопных браузеров, гораздо хуже, чем могли бы: либо путем уменьшения масштаба, делая текст и другой контент слишком мелким и нечитаемым (как в нашем варианте), либо отображая лишь небольшую часть сайта, которая умещается на экране.

Если подумать логически, то в этом есть смысл: мобильный браузер видит страницу и предполагает, что она создана для десктопной версии браузера, что верно для подавляющего числа сайтов. Исходя из этого, этот браузер задает странице ширину 980px (Safari iPhone) и пытается оптимально уместить ее на экране смартфона, отобразив в максимально уменьшенном масштабе. Обычно ширина сайтов примерно такой и является, поэтому открыв среднестатистическую веб-страницу на мобильном устройстве, она растянется на всю свою ширину, но меньше в 2-3 раза своего оригинального размера.

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

И вот как раз для этого мы и будем использовать мета-тег viewport, который был введен компанией Apple и как обычно скопирован остальными.

Добавим в блок <head></head> следующую строку:

<meta name="viewport" content="width=device-width">

И вот что получится в результате:

Совсем другое дело. Задав мета-тегу viewport значение “device-width”, мы говорим браузеру, что ширина области просмотра равняется ширине этого устройства, а не стандартной ширине в 980px, как он может предполагать по-умолчанию. На большом количестве смартфонов ширина экрана равняется 320px (в портретном режиме). Можно задать самостоятельно ширину в 320px, что даст тот же результат, но на некоторых смартфонах ширина экрана может быть другой, поэтому самый оптимальный вариант — использовать device-width.

Одним из самых распространенных вариантов определения области просмотра является следующий вариант:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

который определяет ширину страницы и задает начальный масштаб.

Также, часто можно встретить такой вариант:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

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

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

<meta name="MobileOptimized" content="320"/>
<meta name="HandheldFriendly" content="true"/>

Подробнее об этих и других специфических мобильных тегах можно почитать здесь.

Возможные параметры для мета-тега viewport

Атрибут Возможное значение Описание
width Целое неотрицательное значение
(от 200px — 10,000px)
или константа device-width.
Определяет ширину viewport.
Если ширине не указана, в мобильном Safari устанавливается значение 980px, в Opera — 850px, в Android WebKit — 800px, а в IE — 974px.
height Целое неотрицательное значение
(от 223px до 10,000px)
или константа deviceheight
Определяет высоту viewport. В большинстве случаев на этот атрибут можно не обращать внимание
initial-scale Число с точкой (от 0.1 до 10).
Значение 1.0 — не масштабировать
Определяет начальный масштаб страницы. Чем больше число, тем выше масштаб.
user-scalable no или yes Определяет, может ли пользователь изменять масштаб в окне.
По-умолчанию “yes” в мобильном Safari.
minimum-scale Число с точкой (от 0.1 до 10).
1.0 — не масштабировать
Определяет минимальный масштаб viewport. По-умолчанию “0.25” в мобильном Safari.
maximum-scale Число с точкой (от 0.1 до 10).
1.0 — не масштабировать
Определяет максимальный масштаб viewport. По-умолчанию “1.6” в мобильном Safari.

Таблица совместимости с viewport.

Браузер/ Платформа Использование
браузер Android Да, но до версии 2.2 начальное масштабирование равно 1,0.
Symbian/S60, Nokia Series 40, Motorola Internet Browser, NetFront, Openwave (Myriad), Opera Mobile, Opera Mini Нет
BlackBerry Нет до версии 4.2.1.
Да с версии 4.2.1
Internet Explorer Нет до IE6

Собственно, если у вас нет планов углубляться в нюансы и специфику тега viewport, то на этом можно и закончить. Однако, если кто хочет понять принцип работы вьюпорта, и чем отличаются визуальный вьюпорт и вьюпорт страницы, можно почитать дальше.
А поможет нам в этом дополненный мною перевод замечательной статьи Питера-Пауля Коха (Peter-Paul Koch) A tale of two viewports — part two :)

Два вьюпорта

Итак, допустим, что вьюпорт слишком узок для нашего CSS-шаблона. Очевидное решение — сделать вьюпорт шире. Однако, для начала разделим понятие вьюпорта на две части: визуальный вьюпорт и вьюпорт страницы.

Очень неплохо концепцию вьюпортов объясняет Джордж Камминс (George Cummins) на Stack Overflow:

Представьте вьюпорт страницы как большое изображение с неизменными размерами и формой. Теперь представьте меньшую по размеру рамку, через которую вы смотрите на это большое изображение. Эта рамка окружена непроницаемым материалом, который не дает вам увидеть большое изображение полностью, за исключением отдельных его частей. Часть большого изображения, которая видна через рамку, и будет визуальным вьюпортом. Если отойти с рамкой от большого изображения (zoom out, т.е. уменьшить масштаб), то можно увидеть сразу все изображение, или же подойти поближе (zoom in, увеличить масштаб), тогда можно будет рассмотреть только часть изображения. Также, можно поворачивая рамку менять ее ориентацию (на портретную или ландшафтную), при этом размер и форма большого изображения (вьюпорта страницы) всегда остается неизменной.

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

Разметка страницы, особенно если ее ширина задана в процентах, рассчитывается относительно вьюпорта страницы, который значительно шире визуального вьюпорта.

Таким образом, -элемент изначально принимает ширину вьюпорта страницы и дальше CSS ведет себя так, если бы экран был намного шире экрана телефона. Это обеспечивает сайту такое же поведение, как и в десктопном браузере.

Какой же ширины сам визуальный вьюпорт? Это зависит от браузера. Safari iPhone использует 980px, Opera — 850px, Android WebKit — 800px, а IE — 974px.

Некоторые браузеры ведут себя по-своему:

Symbian WebKit пытается приравнять вьюпорт страницы к визуальному вьюпорту, и это означает, что элементы с процентной шириной могут вести себя непредсказуемо. Однако, если страница не умещается в визуальном вьюпорте из-за абсолютных величин браузер растягивает вьюпорт страницы максимум до 850-ти пикселей.

Samsung WebKit делает вьюпорт страницы равным по ширине самого широкого элемента.

На BlackBerry при масштабе в 100% вьюпорт страницы равен будет визуальному вьюпорту при любых раскладах.

Масштабирование (Zooming)

Оба вьюпорта измеряются в CSS-пикселях. Однако, во время масштабирования размеры визуального вьюпорта меняются (при увеличении масштаба на экране умещается меньшее количество CSS-пикселей), в то время как размеры вьюпорта страницы остаются неизменными. (Если бы это было не так, браузер постоянно совершал бы reflow страницы из-за пересчета процентной ширины.)

Понимание вьюпорта страницы

Для лучшего понимания размеров вьюпорта страницы следует взглянуть на то, что происходит при наименьшем возможном масштабе страницы. Большинство мобильных браузеров по-умолчанию отображают любую страницу в наименьшем масштабе.

Дело в том, что размеры вьюпорта страницы браузеров полностью совпадают с экраном при максимально уменьшенном масштабе и поэтому равны визуальному вьюпрту.

Таким образом, ширина и высота вьюпорта страницы равна всему тому, что отображено на экране при наименьшем масштабе. При увеличении масштаба пользователем эти размеры остаются неизменными.

Ширина вьюпорта страницы всегда неизменна. Если изменить ориентацию экрана смартфона, визуальный вьюпорт изменится, но в то же время мобильный браузер приспособится к новой ориентации, немного увеличив масштаб таким образом, что вьюпорт страницы снова станет таким же по ширине, как и визуальный вьюпорт.

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

Android и target-densitydpi

У устройств на платформе андроид есть свой атрибут для viewport, который выключает масштабирование для дисплеев с различным разрешением.

<meta name="viewport" content="target-densitydpi=high-dpi" />

На устройствах с HDPI (240dpi) не будет масштабирования.

<meta name="viewport" content="target-densitydpi=medium-dpi: />

На устройствах с MDPI (160dpi) не будет масштабирования. Такое значение dpi установлено по-умолчанию.

<meta name="viewport" content="target-densitydpi=low-dpi: />

На устройствах с LDPI (120dpi) не будет масштабирования

<meta name="viewport" content="target-densitydpi=device-dpi" />

Такая запись означает, что не будет масштабирования ни на каком из устройств на Андроиде.

Официальный гайд на developer.android.com

44 мнений о Что такое Viewport, как он работает и для чего вообще нужен

  1. Pingback: Полезные элементы в контейнере <HEAD>для мобильных сайтов | frontender.com.ua

  2. Спасибо, всё понятно.
    Но, как сделать, чтобы при переворачивании сайта из портрета в ландшафт, страница не увеличивалась, а растягивалась? Это делает, к примеру, мобильный Яндекс.

  3. Добрый день!
    Спасибо за статью!
    Подскажите пожалуйста, проблема в следующем:
    Заходим на сайт с iPad’a, страница загружается корректно при любой ориентации экрана,
    затем, при смене ориентации на альбомную, ширина страницы увеличивается и
    выходит за пределы зоны видимости. Для того, чтобы данную страницу
    привести к нормальному состоянию, необходимо уменьшить зум, после этого
    страница отображается корректно.

    С портретной ориентацией таких проблем не возникает. В чем может быть
    причина данного поведения страницы при альбомной ориентации и как это
    исправить?

    Если прописать , то все корректно, но не работает зум. Возможно ли сделать чтобы и отображалось корректно и чтобы зум работал?

    Спасибо

    • Добрый день. Скорее всего, вы имеете в виду так называемый «ios scale bug». Есть несколько фиксов, можно посмотреть, например, тут.

    • Вы прописали «maximum-scale=1, user-scalable=no» и жалуетесь, что не работает зум?
      Странная логика…

  4. «И вот как раз для этого мы и будем использовать мета-тег viewport, который был введен компанией Apple и как обычно скопирован остальными.» , а у вас хорошее чувство юмора)))

  5. Огромное человеческое СПАСИБО!!!!!!!!!!!!!!!!!!!!!! 2 недели ломал как сделать чтобы на андроидофоне не съезжал шаблон, не правя при этом ксс. теперь все отлично отобржается НО, но при переходе из горизонтального положения в вертикальное сайт отображается целеком но только на пол экрана)))) как исправить? использовал этот код

  6. Статья очень классная, расписано так что даже для меня понято все стало, спасибо автору!!!

  7. Какой вариант нужно использовать для не мобильных сайтов? То есть чтобы масштабировать пальцами с мобильного, а не подстраиваться под экраны.

    • В таком случае можно вообще ничего не использовать. Мобильные браузеры
      сейчас достаточно умные, чтобы самостоятельно отображать сайты
      оптимальным для них образом

  8. спасибо большое за статью, во многом разобрался но я что то ни как не могу понять вот что, есть у меня сайт http://www.plesenistop.ru/ делан на джумле 2.5 в мета у меня прописано вот такая штука подскажите пожалуйста что нужно поменять чтобы на айфоне при начальной загрузке маштабировалось по ширине экрана(((

  9. Вы случайно не можете дать платную консультацию по верстке под мобильные устройства. Есть несколько вопросов. Вроде ничего сложного для человека, который в этом разбирается.

    Вот один из вопросов. Я делаю резиновую верстку с такими параметрами
    Мой айфон4 отображает по горизонтали судя по всему около 360 пикселей. Почему так? Откуда он берет это значение? Ведь в верстке ширина 100%. По идеи он должен ставить разрешение самого девайса, то есть афйона — 940.

    • Извиняюсь. По горизонтали айфон отображает, примерно, 640. Если повернуть вертикально телефон, то в районе 340.

        • А все просто. Есть пресловутый devicePixelRatio, который для iPhone4+ равен 2. И при вьюпорте равным ширине устройства как раз и получаем 640/2=320 пикселей. Они и только они влезут в экране без зума.

  10. Это же должно работать с десктопным хромом? Хочу чтобы по высоте масштабировалось так, чтобы влазило все до 1000 пикселов.
    почему-то не помогает.
    Реквестирую помощь.

  11. >» мобильный браузер видит страницу и предполагает, что она создана для
    десктопной версии браузера, что верно для подавляющего числа сайтов.
    Исходя из этого, этот браузер задает странице ширину 980px (Safari
    iPhone) и пытается оптимально уместить ее на экране смартфона, отобразив
    в максимально уменьшенном масштабе»

    Не совсем понятно, что значит «браузер задает странице ширину 980px»? Как это браузер может задать ширину странице? Как это происходит, можно поподробней?

  12. Спасибо!! Как раз с андроидом и были проблемы, теперь все работает :)) Хорошая статья!

  13. Народ, кто знает как отключать отображение тех или иных блоков информации на сайте? Делаю на ворд пресс, адаптивная верстка, и некоторые меню, или просто куски текстов лишние для мобильных устройств. вот сайт rns.com.ua

    • Самый простой вариант — скрывать ненужные мобильные блоки с помощью media queries

  14. Бедолага , долго же ты это в себе держал, но мог подержать ещё и вылить кому то лично,
    что бы сразу адекватный ответ выхватить. 😉

    ———
    Статья познавательная, почерпнул для себя много полезного.
    Автору спасибо за труд , и поменьше обращать внимания на неблагодарное «дерево».

Добавить комментарий

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