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

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

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

Важно отметить, что изменение всех размеров нас интересует только в пределах минимальной и максимальной ширины макета.

Проблема

Например мы хотим задать размер для заголовка первого уровня. При минимальной ширине макета (320px), размер шрифта должен быть 28px.  При максимальной ширине (1440px), размер шрифта должен быть 40px. 

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

Min-Max-Value Interpolation

Для наших значений мы получим такой код: clamp(1.75rem, 1.536rem + 1.07vw, 2.5rem)

h1 {

    font-size: clamp(1.75rem, 1.536rem + 1.07vw, 2.5rem);

}

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

Можно использовать препроцессор Sass, и написать функцию для расчета значений.

Пример описан в этой статье: “Easy Fluid Typography With clamp() Using Sass Functions

Но это все еще не выглядит, как хорошее решение.

Решение

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

Рассмотрим пример реализации на CodePen

Магический коэффициент

Чтобы задать гибкость какому либо размеру нужно связать его с шириной макета. Чем больше ширина, тем больше размер. Для этого нам нужен некий коэффициент, который вычисляет, где текущий экран между минимальной (minWidth) и максимальной (maxWidth) шириной макета. Результатом такого вычисления будет дробное число от 0 до 1.  Коэффициент рассчитывается по следующей формуле:

calc( ( clamp( [minWidth] , 100vw, [maxWidth] ) - [minWidth] ) / ( [maxWidth] - [minWidth] ) )

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

Формула гибкости

calc( ( [maxValue] - [minValue] ) * var(--kw) + [minValue] )

Например, если мы хотим, чтобы при минимальном размере макета отступ был 15px (minValue), и при максимальном 60px (maxValue). То код стилей будет следующим:

padding: calc((60 - 15) * var(--kw) + 15px);

Благодаря коэффициенту --kw размер отступа теперь напрямую связан с изменением ширины макета, в заданных пределах.

Как быть rem

Как упоминалось выше, значения для типографики лучше указывать в единицах rem. 1rem соответствует размеру шрифта корневого элемента. Чтобы применить формулу гибкости для калькуляции rem нужно указать минимальное и максимальное значение для одного rem. Считать rem удобнее всего, если он будет равен 10px. Например 14px это 1.4rem. Поэтому возьмем 10px как минимальное значение. Чтобы определить максимальное, можно обратиться к дизайну макета. Например, на мобильной версии заголовок первого уровня равен 30px, а на десктопной 48px. Узнаем во сколько раз 48 больше 30: 48  / 30 = 1,6. Получается максимальное значение rem будет 1,6 * 10px  = 16px.

html { 

    font-size: calc((16 - 10) * var(--kw) + 62.5%); 

}

Откуда взялось число 62.5%? Размер шрифта браузера по умолчанию равен 16 пикселей. Чтобы получить процентное значение 10px от пользовательского размера шрифта, нужно: 10 / 16 = 0.625 = 62.5% . Теперь, если пользователь в настройках браузера изменит размер шрифта, то это изменит и размер rem.

Заключение

Теперь всё хорошо. Везде, где возможно, используем rem; там, где значение должно быть в строгом диапазоне, используем формулу гибкости.

Больше полезного материала на моей странице (Boosty)

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


  1. MoniKossa
    19.01.2025 16:33

    Так какую проблему мы "победили"? Перечитал несколько раз. Кстати, что по этому поводу думает дизайнер?


    1. kossyak Автор
      19.01.2025 16:33

      Лучше всего на этот вопрос может ответь демонстрация на CodePen, можно увидеть, как с помощью несложного кода реализуется резиновая верстка. Дизайнеры хорошо к этому относятся, потому как для мобильной и десктопной версии возможен PerfectPixel. А то, что при этом подходе, PerfectPixel не возможен для планшетной версии - небольшая цена.


      1. MoniKossa
        19.01.2025 16:33

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

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


        1. kossyak Автор
          19.01.2025 16:33

          Похоже, вы просто еще не сталкивались с подобной проблемой.


          1. MoniKossa
            19.01.2025 16:33

            "Бизнесу" это не надо. Проблемы нет.


            1. kossyak Автор
              19.01.2025 16:33

              Проблема в том, что нет единого способа сделать резиновую верстку, все придумывают свой велосипед. Этот же способ претендует на единый подход. Чтобы вы не думаю, что только я пытался решить эту проблему, вот еще ссылка https://www.youtube.com/watch?v=6l6IJLlSoLo


  1. dom1n1k
    19.01.2025 16:33

    Последняя формула некорректная из-за смешения пикселей и процентов.

    От себя скажу, что подход сомнительный. Я в своё время всё это изобретал и проходил. На практике это работает далеко не так удобно, как кажется поначалу. Очень легко запутаться и накосячить, особенно если код потом правят разные люди. Дебажится трудно, порой даже трудно понять, а правильно ли оно сейчас работает? Короче, быстро выходит из под контроля, а плюсы при этом неочевидны.
    Знаю, приятно почувствовать себя умным, но обычно эти формулы не строят свеч.


    1. kossyak Автор
      19.01.2025 16:33

      Соглашусь, что с rem могут быть сайд эффекты, ну формула гибкости работает безупречно. В примере: padding: calc((60 - 15) * var(--kw) + 15px); На мобильных версиях (320px) гарантированно будет 15px, на десктопе (1440px) будет 60px. Строго между этими значениями резина. Хотя бы такое использование, я смело могу рекомендовать для продакшена.


      1. dom1n1k
        19.01.2025 16:33

        Да, математически формула работает. Но я немного о другом.
        Если брать более-менее сложные проекты, то там неизбежно растёт клубок зависимостей. Например, сделали размер основного текста переменным. А потом паддинги привязали к размеру этого текста - ну потому что так логически по дизайну вытекает. А потом какие-нибудь беджики, там размер текста зависит от размера текста материнского блока. А паддинги в беджиках от размера их собственного текста.
        Со временем в этом начинает путаеться даже автор. А если на проекте что-то делают много разных людей, то там вообще всё плохо. По опыту, не спасает даже подробная дока - каждый новый человек либо ничего не понимает, либо понимает как-то по своему и плодит баги.
        Конечно, если это несложный лендинг, который делает один и тот же человек, тогда проблем нет.


  1. Mausglov
    19.01.2025 16:33

    К сожалению, тот же размер заголовка первого уровня меняется нелинейно. А как только появляются медиа-запросы, смысл в формулах пропадает, можно сразу указать конечное значение.


    1. kossyak Автор
      19.01.2025 16:33

      Зачем нужна линейность? Главное, что размер меняется в заданном промежутке 28-40, где 28 для ширины макета 320, 40 при 1440.