Приемы использования единиц окна просмотра на мобильных устройствах

Приемы использования единиц окна просмотра на мобильных устройствах

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

Реальный пример: следует ли учитывать полосу прокрутки для единицы vw? Что насчет панели навигации сайта или элементов управления страницы — должны ли они учитываться при расчете? Также есть физические атрибуты самих устройств, которые нельзя игнорировать.

Для начала небольшой контекст

Спецификация довольно расплывчата в отношении того, как нужно вычислять единицы окна просмотра. Для мобильных устройств нам часто приходится иметь дело с вертикальной высотой, поэтому давайте рассмотрим конкретно высоту окна просмотра (vh): Единица vh — Равна 1% от высоты исходного блока контейнера.

Так что да, четких указаний, связанных с работой на различных устройствах и в конкретных браузерах, нет.

Сначала vh рассчитывалась, основываясь на размерах текущего окна просмотра браузера. Если вы открыли браузер и начали загружать веб-сайт, 1vh был равен 1% от высоты экрана, минус интерфейс браузера.

Но! Если вы начинаете прокручивать окно, это совсем другая история. Как только вы пролистаете часть интерфейса браузера, например, адресную строку, значение vh будет обновляться, а в результате — скачок контента.

Safari для iOS был одним из первых мобильных браузеров, в котором реализации была обновлена — выбиралось определение фиксированного значения для vh на основе максимальной высоты экрана. Таким образом, пользователь не сталкивается со скачками контента на странице, когда адресная строка перестает отображаться. Мобильный браузер Chrome последовал этому примеру около года назад.

Использование фиксированного значения — это хорошо. Но это также означает, что вы не можете получить полную высоту элемента, если отображается адресная строка. Нижняя часть элемента будет обрезана.

Элемент обрезается внизу, когда адресная строка находится в поле зрения (слева), но мы хотим, чтобы все было правильно (справа).

Пользовательские свойства CSS: Прием для корректировки размеров

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

В JavaScript вы всегда можете получить значение текущего окна просмотра с помощью глобальной переменной window.innerHeight. Это значение учитывает интерфейс браузера и обновляется при изменении его видимости. Хитрость заключается в том, чтобы сохранить значение размеров окна просмотра в переменной CSS и применить это к элементу вместо блока vh.

Скажем, для этого примера наша пользовательская переменная CSS —vh. Это означает, что мы можем применить ее в CSS следующим образом:

.my-element { height: 100vh; /* Резервный вариант для браузеров, которые не поддерживают пользовательские свойства */ height: calc(var(--vh, 1vh) * 100

Хорошо. Теперь давайте получим внутреннюю высоту окна просмотра в JavaScript:

// Сначала мы получаем высоту окна просмотра и умножаемы ее на 1%, чтобы получить значение для единицы vh
let vh = window.innerHeight * 0.01;
// Затем мы присваиваем это значение пользовательскому свойству --vh для корневого элемента документа
document.documentElement.style.setProperty('--vh', `${vh}px`);

Таким образом, мы указали JS захватить высоту окна просмотра, а затем получили 1/100 этой суммы, поэтому мы получили значение, которое можем присвоить единице высоты. Затем мы вежливо попросили JS создать переменную CSS (—vh) для :root.

В результате теперь мы можем использовать —vh как значение высоты, мы можем умножить его на 100 и получить полную высоту.

Еще одна маленькая деталь

Хотя на этом мы можем и остановиться, те из вас, кто внимателен к деталям, возможно, обратили внимание, что JavaScript срабатывает, но никогда не обновляет размер элемента при изменении высоты окна просмотра. Идем дальше и попробуем изменить размер окна в демо-версии выше.

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

// Мы прослушиваем событие resize
window.addEventListener('resize', () => { // Выполняем тот же скрипт, что и раньше let vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`);
});

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

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

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

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

Тем временем я надеюсь, что эта статья поможет вам!

Автор: Louis Hoebregts

Источник: https://css-tricks.com/

Редакция: Команда webformyself.