Сегодня настроим систему интервалов, а заодно используем все преимущества относительных единиц для обеспечения отзывчивости макета.
Настройка системы интервалов с помощью переменных CSS
Первый шаг настройки системы интервалов — создание шкалы значений. Для этого нужно выбрать 1) единицу измерения или базовое значение и 2) множитель. О создании модульной шкалы мы уже говорили первой статье цикла, посвященной типографике.
Базовый подход выглядит так:
:root {
--space-xxs: 4px;
--space-xs: 8px;
--space-sm: 12px;
--space-md: 20px;
--space-lg: 32px;
--space-xl: 52px;
--space-xxl: 84px;
}
Фрагмент выше описывает систему интервалов на основе последовательности Фибоначчи (каждое значение находится путем сложения двух чисел перед ним).
Недостатком базового подхода является то, что…он базовый. Если мы хотим изменить одно значение, то нужно все пересчитать и вручную отредактировать.
Давайте попробуем взять систему под контроль. Мы можем ввести коэффициенты и базовое значение и использовать функцию calc() для получения значений интервалов.
:root {
--space-unit: 16px;
--space-xxs: calc(0.25 * var(--space-unit)); // 4px
--space-xs: calc(0.5 * var(--space-unit)); // 8px
--space-sm: calc(0.75 * var(--space-unit)); // 12px
--space-md: calc(1.25 * var(--space-unit)); // 20px
--space-lg: calc(2 * var(--space-unit)); // 32px
--space-xl: calc(3.25 * var(--space-unit)); // 52px
--space-xxl: calc(5.25 * var(--space-unit)); // 84px
}
Уже теплее! Каждый интервал теперь вычисляется умножением базового значения на коэффициент для каждого размера. Обратите внимание, что теперь коэффициенты следуют последовательности Фибоначчи. Если нужно обновить всю систему, достаточно изменить базовое значение.
Далее, давайте избавимся от абсолютных единиц и заменить их на em.
:root {
--space-unit: 1em;
--space-xxs: calc(0.25 * var(--space-unit));
--space-xs: calc(0.5 * var(--space-unit));
--space-sm: calc(0.75 * var(--space-unit));
--space-md: calc(1.25 * var(--space-unit));
--space-lg: calc(2 * var(--space-unit));
--space-xl: calc(3.25 * var(--space-unit));
--space-xxl: calc(5.25 * var(--space-unit));
}
Это выглядит как маленькая правка, но на самом деле серьезно меняет всю систему. em
— это относительная единица измерения, равная текущему размеру шрифта. В большинстве браузеров размер по умолчанию равен 16 пикселей, поэтому мы можем предположить, что 1em = 16px
. Однако, если вы редактируете размер шрифта элемента, то меняется и базовое значение для отступов. Кажется, что мы теряем контроль над макетом, но на самом деле мы достигаем великолепной отзывчивости.
Если вы следите за этой серией статей, то знаете, что мы создали систему типографики, где все размеры шрифтов связаны и получены путем умножения переменной размера текста (равной 1em
) на коэффициент. Это означает, что переменная text-base-size
является контроллером всей системы типов. Если увеличить базовый размер текста при определенном запросе носителя, все переменные размера текста изменятся соответствующим образом.
@include breakpoint(md) {
:root {
--text-base-size: 1.25em;
}
}
Обновив только одну переменную, вы получите следующее:
И это не все! Поскольку интервалы измеряются в em
, при обновлении переменной text-base-size
мы также влияем на интервал.
Посмотрите, как этот метод влияет на типографику и интервал одновременно:
Мы все еще обновляем одну переменную (text-base-size
). Никаких дополнительных медиа запросов пока не требуется! Вам просто нужно использовать переменные интервалов для установки магринов и паддингов на уровне компонентов:
.header__top {
background: var(--black);
padding: var(--space-sm);
text-align: center;
a {
color: var(--white);
@include fontSmooth;
}
}
.header__main {
border-bottom: 1px solid var(--color-border);
padding-top: var(--space-sm);
padding-bottom: var(--space-sm);
background: var(--white);
}
.header__nav {
ul {
display: flex;
}
li {
margin-right: var(--space-md);
&:last-child {
margin-right: 0;
}
}
}
Что делать, если вы хотите обновить все значения интервалов без изменения переменной text-base-size
? Просто обновите переменную space-unit
:
:root {
--space-unit: 1em;
--space-xxs: calc(0.25 * var(--space-unit));
--space-xs: calc(0.5 * var(--space-unit));
--space-sm: calc(0.75 * var(--space-unit));
--space-md: calc(1.25 * var(--space-unit));
--space-lg: calc(2 * var(--space-unit));
--space-xl: calc(3.25 * var(--space-unit));
--space-xxl: calc(5.25 * var(--space-unit));
}
@include breakpoint(md) {
:root {
--space-unit: 1.25em;
}
}
Действительно, используя подобный метод, вы теряете часть контроля, но код становится проще для чтения и обслуживания.
Действительно, так вы не сможете установить идеальные значения отступов в пикселях, но отзывчивость выходит на совершенно новый уровень.
Самая сложная часть работы: установить надежную шкалу значений для интервалов и типографики. Затем можно изменить пару переменных в медиа-запросах, и это каскадом изменит все остальное. Вам больше не нужно настраивать каждый элемент вручную.
Как установить отступ по умолчанию для всех компонентов
В некоторых случаях требуется, чтобы разные компоненты имели одинаковые паддинги. Для такого дефолтного значения можно установить собственную переменную.
Вот пример:
В файл _spacing.scss добавим переменную component-padding
:
:root {
--space-unit: 1em;
--space-xxs: calc(0.25 * var(--space-unit));
--space-xs: calc(0.5 * var(--space-unit));
--space-sm: calc(0.75 * var(--space-unit));
--space-md: calc(1.25 * var(--space-unit));
--space-lg: calc(2 * var(--space-unit));
--space-xl: calc(3.25 * var(--space-unit));
--space-xxl: calc(5.25 * var(--space-unit));
/* components padding */
--component-padding: var(--space-sm);
}
.component {
padding-top: var(--component-padding);
}
Теперь если нужно установить для компонента отступ, вы можете не искать, какое значение было у него в других элементах, просто используйте переменную.
Вспомогательные margin-классы
Включать в CSS компонента паддинги достаточно безопасно, а вот маргины могут вызвать проблемы с макетом.
Информация о внешних отступах и позиционировании должна храниться не в компоненте, а в элементе абстрактного макета. При этом вы сможете использовать один и тот же компонент в двух совершенно разных ситуациях, с маргинами или без.
По этим причинам удобно иметь служебные классы для внешних отступов:
.margin-top, .margin-top--md {
margin-top: var(--space-md);
}
.margin-top--sm {
margin-top: var(--space-sm);
}
.margin-top--lg {
margin-top: var(--space-lg);
}
.margin-top--xl {
margin-top: var(--space-xl);
}
.margin-top--xxl {
margin-top: var(--space-xxl);
}
.margin-bottom, .margin-bottom--md {
margin-bottom: var(--space-md);
}
.margin-bottom--sm {
margin-bottom: var(--space-sm);
}
.margin-bottom--lg {
margin-bottom: var(--space-lg);
}
.margin-bottom--xl {
margin-bottom: var(--space-xl);
}
.margin-bottom--xxl {
margin-bottom: var(--space-xxl);
}
При необходимости можно обновить эти значения полей в определенном брейкпоинте, чтобы автоматически увеличивать расстояния при увеличении вьюпорта.
@include breakpoint(md) {
.margin-top, .margin-top--md {
margin-top: var(--space-lg);
}
.margin-top--sm {
margin-top: var(--space-md);
}
.margin-top--lg {
margin-top: var(--space-xl);
}
.margin-top--xl {
margin-top: var(--space-xxl);
}
.margin-top--xxl {
margin-top: var(--space-xxxl);
}
.margin-bottom, .margin-bottom--md {
margin-bottom: var(--space-lg);
}
.margin-bottom--sm {
margin-bottom: var(--space-md);
}
.margin-bottom--lg {
margin-bottom: var(--space-xl);
}
.margin-bottom--xl {
margin-bottom: var(--space-xxl);
}
.margin-bottom--xxl {
margin-bottom: var(--space-xxxl);
}
}
Пользовательские значения интервалов
Что делать, если space-sm
выглядит слишком маленьким, а space-md
слишком большим? Когда вы работаете с набором предопределенных переменных, иногда приходится идти на компромисс.
Однако, если вам действительно нужно использовать значение, не входящее в шкалу интервалов, вы можете воспользоваться функцией calc
:
.nav__item {
margin-right: calc(var(--space-sm) * 1.1);
}
Таким образом, вы вводите новое значение, но оно по-прежнему контролируется вашей системой.
Фиксированные значения интервалов
Система интервалов, которую мы ввели, подразумевает, что все поля, отступы (и элементы типографики) обновляются одновременно. Однако в некоторых случаях значение отступа должно быть постоянным, независимо от размера вьюпорта.
Такие интервалы следует задавать в rem
. 1rem
— это размер шрифта корневого элемента html
, он не изменяется при обновлении переменной text-base-size
.
Мы не будем заменять em
на rem
, но попробуем их объединить.
Самый простой способ установить «фиксированное» значение интервала:
.nav__item {
margin-right: 0.5rem;
}
Однако это приведет к использованию множества внесистемных значений интервалов. Чтобы избежать путаницы было бы идеально использовать переменные.
Вот пример того, как вы можете установить шкалу фиксированных значений интервалов в дополнение к отзывчивым:
:root {
/* spacing values */
--space-unit: 1em;
--space-xxs: calc(0.25 * var(--space-unit));
--space-xs: calc(0.5 * var(--space-unit));
--space-sm: calc(0.75 * var(--space-unit));
--space-md: calc(1.25 * var(--space-unit));
--space-lg: calc(2 * var(--space-unit));
--space-xl: calc(3.25 * var(--space-unit));
--space-xxl: calc(5.25 * var(--space-unit));
/* fixed values - not affected by --space-unit or --text-base-size */
--space-unit-fixed: 1rem;
--space-xxs-fixed: calc(0.25 * var(--space-unit-fixed));
--space-xs-fixed: calc(0.5 * var(--space-unit-fixed));
--space-sm-fixed: calc(0.75 * var(--space-unit-fixed));
--space-md-fixed: calc(1.25 * var(--space-unit-fixed));
--space-lg-fixed: calc(2 * var(--space-unit-fixed));
--space-xl-fixed: calc(3.25 * var(--space-unit-fixed));
--space-xxl-fixed: calc(5.25 * var(--space-unit-fixed));
}
_spacing.scss
Собираем все вместе :
/* --------------------------------
Spacing
-------------------------------- */
:root {
/* spacing values */
--space-unit: 1em;
--space-xxxs: calc(0.25 * var(--space-unit));
--space-xxs: calc(0.375 * var(--space-unit));
--space-xs: calc(0.5 * var(--space-unit));
--space-sm: calc(0.75 * var(--space-unit));
--space-md: calc(1.25 * var(--space-unit));
--space-lg: calc(2 * var(--space-unit));
--space-xl: calc(3.25 * var(--space-unit));
--space-xxl: calc(5.25 * var(--space-unit));
--space-xxxl: calc(8.5 * var(--space-unit));
/* components padding */
--component-padding: var(--space-sm);
}
// optional - edit space unit and padding of all components at a specific breakpoint
@include breakpoint(md) {
:root {
--space-unit: 1.25em;
--component-padding: var(--space-md);
}
}
/* vertical margins */
.margin-top, .margin-top--md {
margin-top: var(--space-md);
}
.margin-top--sm {
margin-top: var(--space-sm);
}
.margin-top--lg {
margin-top: var(--space-lg);
}
.margin-top--xl {
margin-top: var(--space-xl);
}
.margin-top--xxl {
margin-top: var(--space-xxl);
}
.margin-bottom, .margin-bottom--md {
margin-bottom: var(--space-md);
}
.margin-bottom--sm {
margin-bottom: var(--space-sm);
}
.margin-bottom--lg {
margin-bottom: var(--space-lg);
}
.margin-bottom--xl {
margin-bottom: var(--space-xl);
}
.margin-bottom--xxl {
margin-bottom: var(--space-xxl);
}
@include breakpoint(md) {
.margin-top, .margin-top--md {
margin-top: var(--space-lg);
}
.margin-top--sm {
margin-top: var(--space-md);
}
.margin-top--lg {
margin-top: var(--space-xl);
}
.margin-top--xl {
margin-top: var(--space-xxl);
}
.margin-top--xxl {
margin-top: var(--space-xxxl);
}
.margin-bottom, .margin-bottom--md {
margin-bottom: var(--space-lg);
}
.margin-bottom--sm {
margin-bottom: var(--space-md);
}
.margin-bottom--lg {
margin-bottom: var(--space-xl);
}
.margin-bottom--xl {
margin-bottom: var(--space-xxl);
}
.margin-bottom--xxl {
margin-bottom: var(--space-xxxl);
}
}
0 комментариев