Зачастую, когда говорят об адаптиве, подразумевают сужение большого экрана до мобильного размера без потери функциональности. Однако, на самом деле, адаптив также существует между разными десктопными версиями. Обычно разработчики не очень стараются применять адаптивные подходы для больших экранов, ведь если интерфейс поместился на HD разрешении, то он точно поместится на 2K разрешении и больше. Однако контент никак не масштабируется, поэтому имеем на больших разрешениях маленькие элементы, которые трудно уловить взглядом. В этой статье я покажу, как сделать интерфейсы пропорционально одинаковыми на разных десктопных разрешениях.
Проблема
Давайте сделаем совсем примерную верстку онлайн-кинотеатра Кекфликс. Не буду вдаваться в подробности, как именно это сверстано, тут нет особых сложностей, я детально буду рассматривать лишь стили. Сначала необходимо договориться о некоторых нерушимых постулатах:
Базовый размер шрифта равен
16px
.Эталонный размер десктопного экрана
1600х900
. Это означает, что мы будем стараться делать другие десктопные экраны максимально пропорционально похожими на экран1600х900
.
Вот что у нас получилось:
Полный скриншот страницы выглядит так:
В данной верстке у нас все задано в пикселях: размер шрифта, размер скруглений, ширины, высоты и другое. Именно поэтому данный интерфейс будет выглядеть следующим образом на разрешении iMac 2560х1664
:
Интерфейс никак не заскейлился: например, как был размер шрифта у названия фильма 16px
на экране 1600х900
, так и остался. Стало вмещаться больше контента, вследствие чего глазу очень тяжело остановиться на чем-то одном, а мышкой тяжело дотянуться до маленьких элементов. Как выглядит данный интерфейс на 4K разрешении можете предугадать: все заметно уменьшилось.
Как вариант решения этой проблемы на некоторых сайтах добавляют пустые боковые распорки, чтобы сузить контент. В нашем варианте это могло бы выглядеть примерно так:
Ничего не имею против такого подхода, он имеет право на существование. Я лишь хочу предложить альтернативную стратегию адаптива десктопных разрешений, чтобы даже когда вы вывели свой сайт на плазменный телевизор, вам бы не приходилось увеличивать браузерный масштаб, чтобы лучше было видно контент.
Наивное решение
Самый простой способ заскейлить интерфейс — это прописать размеры относительно базовой величины 1rem
, которую впоследствии заадаптивить. Можно также использовать величину em
, но будьте аккуратны, ведь это значение высчитывается от размера шрифта родителя, поэтому могут быть проблемы при наследовании стилей у вложенных элементов. Величина rem
фиксирована размером шрифта, указанном на теге html
. По умолчанию во всех современных браузерах 1rem=16px
, что нам подходит согласно нашим постулатам.
html
// ... some styles ...
font-size: 16px
// ... some styles ...
Чтобы нам проще было переписать стили относительно базовой величины, создадим вспомогательную SASS функцию, которая будет переводить количество пикселей в rem
-ы:
@use 'sass:math'
@function rem(value, $delimeter) * 1rem
Таким образом, например, стили красного квадрата размером 200х200 (width: 200px; height: 200px
) перепишутся следующим образом:
.box
width: rem(200)
height: rem(200)
background-color: red
Что после компиляции примет вид:
.box {
width: 12.5rem;
height: 12.5rem;
background-color: red;
}
После того как мы перевели все пиксели на rem
, необходимо приступать к адаптиву этой величины. Мы бы могли наивно написать следующее медиа-выражение, которое пропорционально экрану 1600x900
увеличит базовую величину 1rem=16px
до значения 1rem=19.2px
для разрешения 1920х1080
.
@media (min-width: 1920px)
html
font-size: 19.2px
Тогда получим, что на экране шириной 1920 действительно все пропорционально увеличилось, но на всех разрешениях до величины 1920 не было никаких изменений. Это видно, если ресайзить окно:
Это уже вариант, который можно развивать. Мы бы могли наплодить брейкпоинтов, на каждый из которых повесить свои медиа-выражения. Но такой подход далек от идеала, ведь хочется получить сразу готовый результат одной строчкой. Перед тем как показать такой вариант решения, необходимо немного раскрыть тему CSS шлюзов.
Миксин адаптивности через CSS шлюзы
CSS шлюзом (CSS lock) называется механизм, позволяющий плавно переходить от одного значения к другому в зависимости от текущей области просмотра. Подробнее об этой механике можно почитать в этой статье.
Давайте попробуем создать СSS шлюз для изменения базовой величины rem
. То есть создадим шлюз для управления размером шрифта для тега html
. Согласно нашим постулатам мы договорились, что у нас базовый шрифт равен 16px
, а базовый экран имеет разрешение 1600х900
. Стоит отметить, что мы будем добавлять резиновости нашему интерфейсу лишь по ширине экрана, но при необходимости такие же манипуляции можно сделать и с высотой.
Если для ширины 1600
мы имеем размер шрифта 16px
, то прибегнув к несложным математическим операциям можно выяснить, что для ширины экрана 1920
размер шрифта должен составлять 19.2px
. Это можно увидеть на графике для прямой y=0.01x
, где по оси X у нас находятся ширины экранов, а по оси Y размер шрифта:
Давайте абстрагируемся от конкретных значений и построим общую прямую по двум точкам (x1, y1)
и (x2, y2)
согласно линейной функции y=kx+b
, где k
— это наклон функции, а b
— смещение по оси ординат. Коэффициент k
вычисляется как первая производная функции (или как тангенс угла наклона, если так удобнее):
Коэффициент b
можно вычислить, если подставить любую точку, например, (x1, y1)
и найденный коэффициент k
. Не буду тратить ваше время на математические манипуляции и покажу сразу исходный вид нашей функции, построенной для любых двух точек:
Давайте преобразуем это в SASS функцию: y
— это то, что мы ищем, поэтому воспользуемся функцией calc()
, а x
заменим на ширину всего вьюпорта 100vw
:
@function calc-between-width($width-start, $value-start, $width-end, $value-end)
@return calc(#{$value-start} * 1px + (#{$value-end} - #{$value-start}) * (100vw - #{$width-start} * 1px) / (#{$width-end} - #{$width-start}))
Получили SASS функцию calc-between-width
, которая выставит пропорциональное значение в пикселях любому CSS свойству в зависимости от переданных величин в промежутке указанных ширин.
Время магии
Необходимо применить SASS функцию на нашей базовой верстке, чтобы заадаптивить базовую величину rem
. Для этого добавим следующий стиль
html
font-size: calc-between-width(1600, 16, 1920, 19.2)
Тогда получим желанный результат: все десктопные экраны стали выглядеть одинаково согласно нашему базовому разрешению 1600х900
:
А вот как это выглядит в динамике:
Заключение
Если не забывать думать о больших экранах пользователей, то можно сделать интерфейс одинаковым для любого десктопного разрешения через CSS шлюзы. Это позволит правильно масштабировать сайт, что сделает его похожим на полноценное веб-приложение.
В наивном решении необходимо было писать медиа-выражения, которые никак не гарантировали масштабируемость страницы для неучтенных размерностей. Условно, сколько мы зафиксировали брейкпоинтов, столько разрешений мы поддержали. Для остальных десктопных экранов — нам бы пришлось сделать боковые распорки, чтобы лучше было видно контент. Если сравнивать, то решение со шлюзами сразу делает интерфейс по-настоящему резиновым для любого экрана пользователя в одно движение, а также значительно сокращает написание кода.
В данной статье мы адаптивили CSS свойство font-size
, что позволило добавить нам резиновость для всех разрешений. Но мы сделали это самым простым способом через линейную функцию. Однако нам никто не запрещает использовать другие виды функций. Например, при необходимости можно построить кусочно-линейную функцию, которая будет увеличивать размер шрифта от ширины экрана 1600
до 1800
, далее уменьшать размер шрифта до ширины 2000
и после снова увеличивать. Или можно написать новую SASS функцию, которая будет вычислять значение согласно квадратичной функции. К тому же, функция calc-between-width
применятся к любому CSS свойству, которое может содержать пиксели. Поэтому вы можете, таким же образом через CSS шлюзы добавлять резиновости любым таким свойствам. К примеру, вы можете резиново манипулировать скруглениями через border-radius
. Вы ограничены лишь своей фантазией и возможностями браузера!
Ссылка на github: https://github.com/progikusok/desktop-adaptive-example