Все верстальщики рано или поздно сталкивались с болью, которая заключается в адаптиве сайта под различные устройства. Существуют разные технологии, упрощающие подгонку размеров под определённые устройства, например, clamp(). Эта функция удобна, так как позволяет минимизировать использование брейкпоинтов, но у неё есть свои недостатки:

  • Код сложнее читается и редактируется.

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

  • Требуется продумывать, где использовать, а где нет, что создаёт отсутствие чёткой системности.

  • Сложности с чётким заданием размеров для промежуточных брейкпоинтов, например, для планшетов.

Делаем разработку проще

На помощь приходят старые добрые rem’ы. Этот подход не новый, но он простой в разработке и, самое главное, удобный для разработчика. Перейдём к сути.

Для удобства будем использовать функцию rem(), которая переводит пиксели в rem:

@function rem($pixels) {
	@return calc($pixels / 10) + rem;
}

Та самая формула, которая высчитывает значение 1rem. Для удобства мы будем отталкиваться от значения 10px, модифицируя его с помощью формулы:

html {
  --refRes: 1920;
  font-size: calc(100vw / var(--refRes) * 10);
  
  @media (max-width: 1024px) {
    --refRes: 768  
  }
  @media (max-width: 530px) {
    --refRes: 320
  }
}

Мы берём текущую ширину экрана, делим на базовое разрешение экрана, от которого отталкиваемся (1920px для десктопа), и умножаем на стандартное значение шрифта (10px)

На выходе получаем линейную зависимость значения шрифта от ширины экрана. Используя rem()везде, все элементы также начинают зависеть от ширины экрана:

.foo {
  width: rem(100);
  height: rem(50);
  font-size: rem(24);
}

Что примет вид:

.foo {
  width: 10rem;
  height: 5rem;
  font-size: 2.4rem;
}
Базовое разрешение (синий), брейкпоинты (красный)
Базовое разрешение (синий), брейкпоинты (красный)
  • От 1920 до 1025 сайт выглядит как при 1920.

  • От 1024 до 531 сайт выглядит как при 768.

  • от 530 до 320 сайт выглядит как при 320.

Пример работы формулы
Пример работы формулы

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

Забота о братьях наших больших

Что же с разрешениями больше 1920?

Разрешение больше 1920
Разрешение больше 1920

В этом примере я взял разрешение в 2 раза больше, чем 1920, и тут видно, что все элементы тоже увеличились в 2 раза, что привело к тому, что всё выглядит, как будто у нас разрешение 1920, а не 3840.

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

Для этого есть решение:

html {
  --refRes: 1920;
  $ratio: 0.5;
  font-size: calc(100vw / var(--refRes) * 10);

  @media (min-width: 1921px) {
    font-size: calc(
    	10px + ($ratio * 10) * ((100vw - var(--refRes) * 1px) / var(--refRes))
    );
}

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

Разрешение больше 1920 при коэффициенте 0.5
Разрешение больше 1920 при коэффициенте 0.5

С коэффициентом 0.5, при увеличении размера экрана в два раза элементы увеличиваются всего в 1.5 раза. Таким образом, ничего не ломается, и на экране помещается больше элементов.

Что мы в итоге имеем

Из плюсов:

  • Код легко читается.

  • Все значения указываются в понятном виде — так, как в макете.

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

  • При разработке не нужно учитывать промежуточные размеры viewport.

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

  • Есть чёткая системность: использовать rem() всегда и везде, за исключением, где нужны em, %, ch и другие единицы.

Из очевидных минусов:

  • Невозможность поменять размер шрифта в настройках браузера.

  • Зум через клавиши «+», «-» не меняет ничего в пределах между брейкпоинтами (пользователь не может немного увеличить размер страницы, может только использовать заранее подготовленные версии сайта).

  • При разработке необходимо вручную записывать все меняющиеся значения по брейкпоинтам.

Заключение

Таким образом, мы сделали все размеры элементов зависимыми от font-size у html-элемента, что придало им резиновость, а нам — удобство в разработке.

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

Материалы к статье

Комментарии (5)


  1. savostin
    05.06.2024 07:05

    Здорово конечно. Разработчику. Но сайт с такими минусами вызывает у меня глубокое отторжение.


  1. kellas
    05.06.2024 07:05
    +1

    Интересный подход, для новостных сайтов может не лучший выбор, а вот для приложений самое то! Спасибо!


  1. ooko
    05.06.2024 07:05
    +1

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

    Много лет использую этот прием с rem. Даже делал доклад на MoscowJS. Это по сути получается векторная графика - и соответственно получаем проблему дробных пикселей у маленьких элементов. Это линии в один пиксель или когда нужно выравнивать что-то по вертикали .

    Из минусов - нужно постоянно помнить что верстаешь векторную графику. В коде js тоже нужно это помнить. Всем картинкам не забывать указывать размер.

    Кому интересно как работает могут посмотреть тут https://ooko.pro . Только нужно через телефон или в инспекторе включить мобильный и перезагрузить. Так как учитываю агент браузера.


  1. RomkaLis
    05.06.2024 07:05

    Прочитал с интересом, но, на мой взгляд, минусы для пользователя полностю перекрывают плюсы для разработчика. Мы все же сайты делаем, для того, чтобы люди их смотрели, по возможности, с комфортом. Говорю как человек постоянно пользующийся + / -.


    1. ooko
      05.06.2024 07:05

      Не используйте для десктопа. А у тач-устройств другой принцип зума.