Хабрахабр

[Из песочницы] Максимальная адаптивность с минимальным количеством медиа запросов, или метод обратной адаптивности

— Генри Луис Менкен. "У всякой проблемы всегда есть решение — простое, удобное, и конечно ошибочное".

Суть проблемы

На первый взгляд реализация адаптивной верстки может показаться «линейным квестом » с довольно небольшим полем для маневров.

Назначаем нужные классы, меняем по мере надобности размеры, положение или порядок элементов и дело вроде бы сделано.

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

При столкновении с необычными дизайнерскими решениями медиа запросы становятся «толще», появляются нестандартные брейкпоинты, а при смене деталей дизайна, внесение правок в вёрстку становится довольно тяжелой работой.

Любая поправка от клиента или дизайнера, и css код нужно редактировать во всех медиа запросах (особенно если это чужой css и они разбросаны по всему коду в разных местах с нелогичной последовательностью).

Код становится ещё менее настраиваемым и где-то там среди тысяч строк появляются строки которые уже не нужны и только (пусть и незначительно ) замедляют работу браузера.
Что часто приводит к ситуации когда вы уже не совсем контролируете ситуацию и появляется соблазн прибегнуть к «жёстким» методам, таким как директива !important, или вложенность.

Решение

Часть 1. Абсолютная относительность

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

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

Итак главный шаг к этому — это использование абсолютных единиц измерения: px, em, rem только внутри медиа запросов (за редкими исключениями).

Вне медиа запросов нам лучше пользоваться только относительными viewport единицами измерения: vw, vh, vmax и процентами %.

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

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

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

image

в нашем случае
(1400 / 1920) * 100 = 72. 1920 — это главная ширина нашего макета, от нее будут зависеть все остальные размеры по горизонтали.
930 — это главная высота нашего макета (предполагаемая высота одновременно видимой на экране области страницы), от нее будут зависеть все размеры по вертикали.
1400 — это ширина контейнера, в который будет упаковываться всё содержимое страницы.
Далее создадим основные классы для контейнера и текста, следующим образом:
(Вычисляемая ширина / ширина макета) * 100, т.е. 9
Результат как и планировалось выше запишем во viewport единицах а именно view width:

.container { width: 72.91vw;
}

Тоже самое проделаем для текста за тем исключением, что вместо vw используем vmax — что бы использовать максимальный размер экрана а не ширину.
(55 / 1920) * 100 = 2.86

.page__title { font-size: 2.86vmax;
}

Так же для элементов у которых совпадает значение высоты и ширины (квадратные и круглые элементы) тоже нужно использовать vmax единицы что бы сохранять пропорции. Далее можно приступить к верстке и набросать сетку.

Так же к верхним и нижним отступам мы будем применять vh.
(300 / 1920) * 100 = 15. Для блоков которым нужно задать высоту используем ту же формулу пересчёта во viewport, но теперь вместо ширины мы будем будем отталкиваться от высоты экрана и к результату дописывать vh(view height). 12; 62;
(60 / 1920) * 100 = 3.

.main__block { width: 15.62vmax; height: 15.62vmax; margin-top: 3.12vh; margin-right: 3.12vw;
}

А ширину вложенных блоков как я говорил ранее мы посчитаем в процентах используя flex-basis.

image

52;
(16 / 1920) * 100 = 0. (970 / 1920) * 100 = 50. 83;

.main-menu { width: 50.52vw;
}
.main-menu__item { flex-basis: calc(100% / 4 - 0.83vw);
}

Часть 2. Обратная адаптивность

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

Теперь настало время для обратной адаптивности.

Используя медиа запросы мы заменяем относительные единицы на абсолютные.
Em для Размера шрифта;
Px для высоты блоков;

Для ширины контейнера и некоторых блоков мы продолжим использовать относительные единицы но сменим их на %:

@media (max-width: 767px) .main__block { width: 300px; height: 300px; } .some__block { width: 100%; height: 300px; } ....
}

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

Часть 3. Удобство и щепотка программирования

При всей универсальности данного метода мы продолжаем делать много работы «за кадром», а именно бесконечно пользоваться калькулятором для перевода пикселей во viewport единицы «вручную». Что бы автоматизировать этот процесс нам понадобиться выполнить несколько простых шагов с помощью Scss:

Записать главные размеры в переменные 1.

$full-width: 1920;
$work-width: 80;
$screen-height: 720;

2. Написать функцию для автоматичемкого пересчёта пикселей во viewport

@function vmax($pixels, $context: $full-width) { @return #{($pixels/$context)* 100}vmax
}

и две аналогичные для vw и vh.

Теперь мы можем смело писать все размеры в том виде в котором они указаны в макете примера и не считать это «вручную»:

.main__block { width: vmax(300); height: vmax(300); margin-top: vh(60); margin-right: vw(60);
}

Тем самым мы экономим время и силы.

Выше в медиа запросах мы использовали единицы em для указания размеров шрифта,
поэтому неплохо было бы написать функцию и для них, что соблюдать четкость и порядок:

$browser-context: 16; @function em($pixels, $context: $browser-context) { @return #{$pixels/$context}em
}

Думаю вполне очевидно что эти функции будут написаны один раз и далее могут «переезжать» из одного проекта в другой, вместе с созданными переменными, а так же некоторыми классами зависящими от них.

Единственное что придется делать начиная работу над новым проектом это снова «снять мерку» с макета и подмена значений в этих переменных.

Заключение

  • Мы получаем минимум лишнего кода разбросанного в разных концах и файлах.
  • Увеличиваем свой контроль над ним.
  • Ускоряем процесс написания и редактирования кода.
  • Банально упрощаем себе жизнь, ведь как показывает практика — меньше кода = меньше проблемм.
Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть