Статьи

Масштабирование значений через контрольные точки с использованием Sass

Остановите меня, если вы были здесь раньше: вам дали настольный комп для сайта, затем после его создания вы получите устную обратную связь (или, может быть, другой комп, если вам повезет) для «мобильного просмотра». Затем вам нужно сделать сайт отзывчивым (включая пару промежуточных точек останова), но вы боитесь вручную вычислить все значения свойств CSS, которые заметно изменяются от маленьких до больших экранов (размеры шрифта, поля, ширина). , и т.д). Что если бы был способ автоматически масштабировать эти значения по всем вашим точкам останова и генерировать необходимые медиа-запросы?

Это инструмент, который мы собираемся создать сегодня.

Управление точками останова

Мы начнем с карты Sass для хранения наших точек останова. Примечание: это предназначено для медиа-запросов, ориентированных на мобильные устройства (минимальной ширины), поэтому пары ключ-значение должны быть упорядочены от малого к большому.

$breakpoints: ( small: 320px, medium: 480px, large: 960px, xlarge: 1200px ); 

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

 @mixin bp($name) { @if not map-has-key($breakpoints, $name) { @warn "Invalid breakpoint `#{$name}`."; } @else { @if map-get($breakpoints, $name) { @media (min-width: map-get($breakpoints, $name)) { @content; } } @else { @content; } } } 

Вспомогательные функции

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

Получение значений точек останова

Первая функция — это просто сокращение для map-get() . Он берет ключ $breakpoints и возвращает его значение измерения.

 @function get_bp($label) { @return map-get($breakpoints, $label); } 

Округление чисел

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

 @function round-num($num) { @return round($num*100)/100; } 

Масштабирование значений

Теперь нам нужен миксин, который выполняет тяжелую работу по распределению ценностей между нашими назначенными точками останова. Этот миксин принимает пять параметров (два из которых являются необязательными). $property — имя изменяемого свойства CSS. $value-start и $value-end являются начальными и конечными значениями для свойства. $bp-start и $bp-end по умолчанию установлены на точки останова small и xlarge, но вы можете использовать переопределение этих значений по умолчанию с именами любого другого ключа в $breakpoints .

 @mixin spread-value($property, $value-start, $value-end, $bp-start: small, $bp-end: xlarge) { @if type-of($value-start) != number or type-of($value-end) != number { @warn "Either $value-start or $value-end is not a number: `#{$value-start}` | `#{$value-end}`" } @else { #{$property}: #{$value-start}; $value-distance: $value-end - $value-start; $bp-distance: get_bp($bp-end) - get_bp($bp-start); $bp-keys: map-keys($breakpoints); $bp-list: (); $i: index($bp-keys, $bp-start); @while $i <= length($bp-keys) and nth($bp-keys, $i) != $bp-end { $i: $i + 1; $bp-list: join($bp-list, nth($bp-keys, $i)); } @each $key in $bp-list { $percentage: ( get-bp($key) - get_bp($bp-start) ) / $bp-distance; @include bp($key) { #{$property}: round-num( ( $value-distance * $percentage ) + $value-start ); } } } } 

Проверка значений

Первое, что мы сделаем, — это убедитесь, что $value-start и $value-end являются числами. Числовые измерения — единственное, что мы можем масштабировать (без растягивания шрифтов или фоновых изображений!). Мы проверяем два параметра-значения, убедившись, что их тип является числом. Эта функция Sass будет оценивать любую единицу измерения как число, поэтому значения с px, em,% и т. Д. Все правильно проверяются как числа. Если $value-start или $value-end не является числом, мы выдадим предупреждение компилятору.

 @if type-of($value-start) != number or type-of($value-end) != number { @warn "Either $value-start or $value-end is not a number: `#{$value-start}` | `#{$value-end}`" } @else { // … } 

Установка по умолчанию

Следующее, что нужно сделать, это установить значение по умолчанию. Для медиазапросов, ориентированных на мобильные устройства, это $value-start . Независимо от того, что еще произойдет, мы распечатаем эту пару свойство-значение в таблице стилей:

 #{$property}: #{$value-start}; 

Начните использовать математику

Теперь мы готовы начать вычислять расстояния, которые нам понадобятся для точного распределения наших значений. Мы установим $value-distance на расстояние между $value-start и $value-end и $bp-distance на расстояние между значениями $bp-start и $bp-end .

 $value-distance: $value-end - $value-start; $bp-distance: get_bp($bp-end) - get_bp($bp-start); 

Далее мы будем использовать map-keys() для создания списка всех имен точек останова. Это облегчит определение количества точек останова, для которых нам нужно рассчитать значения. Мы также инициализируем пустой список $bp-list который мы будем использовать для хранения ключей необходимых точек останова.

 $bp-keys: map-keys($breakpoints); $bp-list: (); 

Следующий цикл @while while запускает $i с позиции $bp-start в списке точек останова. Мы остановим цикл при любом из двух условий: если $i превышает длину карты $breakpoints , или если $i — это индекс, точка останова, указанная как $bp-end . Когда этот цикл завершится, $bp-list будет списком всех точек останова, для которых нам нужно вычислить значения.

 $i: index($bp-keys, $bp-start); @while $i <= length($bp-keys) and nth($bp-keys, $i) != $bp-end { $i: $i + 1; $bp-list: join($bp-list, nth($bp-keys, $i)); } 

Теперь нам нужен миксин, чтобы пройти через этот список, генерируя необходимые медиа-запросы и значения. Переменная $percentage вычисляет процент, обозначающий расстояние между $bp-start и $bp-end нашей текущей точкой останова. Затем @include bp($key) {} создает медиа-запрос для текущей точки останова.

Внутри точки останова мы объявляем свойство с масштабированным значением. Чтобы получить масштабированное значение, мы умножаем расстояние в $value-distance на $percentage в $percentage от расстояния нашей точки останова, а затем добавляем начальное значение. Это дает нам изменения значений, которые пропорциональны ширине текущей точки останова. Вы заметите, что мы оборачиваем вывод в нашу функцию round-num() чтобы все было хорошо округлено.

 @each $key in $bp-list { $percentage: ( get-bp($key) - get_bp($bp-start) ) / $bp-distance; @include bp($key) { #{$property}: round-num( ( $value-distance * $percentage ) + $value-start ); } } 

использование

Чтобы использовать этот миксин, включите его в любой селектор:

 p { @include spread-value(margin-bottom, .6em, 1.6em); } 

С точками останова по умолчанию, которые есть у нас на карте, будет сгенерирован следующий CSS:

 p { margin-bottom: 0.6em; } @media (min-width: 480px) { p { margin-bottom: 0.78em; } } @media (min-width: 960px) { p { margin-bottom: 1.33em; } } @media (min-width: 1200px) { p { margin-bottom: 1.6em; } } 

Вы также можете указать, в какой точке останова начинать или заканчивать масштабирование:

 h1 { @include spread-value(font-size, 1.6em, 2.6em, medium, xlarge); } 

Это сгенерирует следующий CSS:

 h1 { font-size: 1.6em; } @media (min-width: 960px) { h1 { font-size: 2.27em; } } @media (min-width: 1200px) { h1 { font-size: 2.6em; } } 

Вывод

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

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