От автора: теперь, когда вы знаете принцип работы пользовательских свойств в CSS, можно перейти к их применению для повышения читаемости кода и упрощения будущей эксплуатации. Замечание: в целях краткости я опущу в статье запись var(), но вы всегда должны ее использовать, как в шаблоне ниже.
1 2 3 4 5 6 |
.foo { /* Для браузеров, не понимающих пользовательские свойства */ color: black; /* `black` используется как фолбек, если `--color` не задана */ color: var(--color, black); } |
Убираем повторяющийся код
DRY расшифровывается как «Don’t Repeat Yourself» или «не повторяйся». Хорошая цель, так как это сэкономит не только набранный текст, но и время на поиск, замену и отладку, если вы вдруг захотите что-то поменять. Проще говоря, такой подход сокращает затраты на обслуживание кода.
Разберем пример. Ниже представлен плохой CSS код с множеством повторений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.button { background-color: gray; } .title { color: gray; } .image-grid > .image { border-color: gray; } .caption { color: gray; /* Всегда должен быть gray, независимо от темы. */ } |
Если нужно сменить цвет темы, необходимо изменить значение первых трех селекторов. Цвет подписи трогать нельзя.
Так как же могут помочь пользовательские свойства CSS? Вы устанавливаете значение один раз и потом используете его много раз! Давайте создадим пользовательское свойство —theme-color:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
:root { --theme-color: gray; } .button { background-color: var(--theme-color); } .title { color: var(--theme-color); } .image-grid > .image { border-color: var(--theme-color); } .caption { color: gray; } |
Сохранив цвет темы в пользовательскую переменную, изменения можно вносить в одном месте, и все значения будут обновляться. Мало того, так вы еще добавили семантику в CSS: если раньше этот цвет сложно было связать с темой, то теперь это явно прописано.
Цвет текста подписи также можно занести в пользовательскую переменную:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
:root { --theme-color: gray; --caption-text-color: gray; } .button { background-color: var(--theme-color); } .title { color: var(--theme-color); } .image-grid > .image { border-color: var(--theme-color); } .caption { color: var(--caption-text-color); } |
Мы только начали!
Отложите калькулятор
Если вы читали введение в пользовательские CSS свойства, вы должны знать, что их можно использовать с функцией calc() для выполнения вычислений в браузере.
Разберем пример сетки:
1 2 3 4 5 6 7 |
.image-grid { padding: 8px; } .image-grid > .image { margin: 8px; } |
Если вы уже видели этот шаблон или хорошо знаете боксовую модель CSS, скорее всего, вы поймете, что этот код создает макет с ячейками, чьи стороны равны 16px, и разделителями шириной в 16px между ячейками. Чисто по CSS коду это понять сложно, и мы не указываем на то, что действительно важно.
С точки зрения дизайна важным аспектом здесь является пространство вокруг ячеек в 16px. Мы хотим все настроить с учетом конечного результата, а не промежуточных вычислений. Сами по себе эти вычисления неважны, а задавать их отдельно слишком долго.
Пользовательские свойства и calc() помогут нам:
1 2 3 4 5 6 7 8 9 10 11 |
:root { --image-grid-spacing: 16px; } .image-grid { padding: calc(var(--image-grid-spacing) / 2); } .image-grid > .image { margin: calc(var(--image-grid-spacing) / 2); } |
Так мы работает с осмысленными концепциями вычислений, а не результатами этих вычислений. Так намного легче будет понять код в будущем.
На деле, эту идею можно расширить на весь макет вашего сайта, выравнивая элементы по сетке:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
:root { --page-grid: 4px; --image-grid-spacing: calc(4 * var(--page-grid)); } .title { text-size: calc(5 * var(--page-grid)); } .paragraph { margin: calc(4 * var(--page-grid)); } .image-grid { padding: calc(var(--image-grid-spacing) / 2); } .image-grid > .image { margin: calc(var(--image-grid-spacing) / 2); } |
В примере выше мы с помощью промежуточных вычислений делаем код еще более понятным.
Замечание: в Safari / WebKit на данный момент наблюдаются проблемы с промежуточными вычислениями такого типа. Проблема была решена в Safari Technology Preview, есть вероятность, что ее пофиксят и в следующем релизе Safari 10.1.
Читаемые изменения
До сих пор мы говорили про значения, которые задаем в документе один раз и потом повторно везде используем без масштабных изменений. Однако пользовательские свойства становятся еще полезнее, когда есть значения, которые необходимо менять в определенных обстоятельствах.
Разберем пример. Простой сетчатый макет на flexbox:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
.image-grid { display: flex; flex-wrap: wrap; padding: 8px; } .image-grid > .image { margin: 8px; width: calc(100% - 16px); } @media (min-size: 600px) { /* 3 изображения на строку */ .image-grid > .image { width: calc(100% / 3 - 16px); } } @media (min-size: 1024px) { /* 6 изображений на строку */ .image-grid > .image { width: calc(100% / 6 - 16px); } } |
Сразу не поймешь, что здесь происходит. Давайте разберем код. По умолчанию для маленьких экранов строится сетка с одной колонкой. По мере увеличения экрана сетка расширяется до 3 и 6 колонок. Как и в примере из предыдущего раздела, у нас тут ячейки со стороной 16px и разделители в 16px.
Из-за сложности вычислений, нам нужно было добавить пару комментариев, чтобы улучшить читаемость. Но если использовать пользовательские свойства:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
:root { --grid-spacing: 16px; --grid-columns: 1; } .image-grid { display: flex; flex-wrap: wrap; padding: calc(var(--grid-spacing) / 2); } .image-grid > .image { margin: calc(var(--grid-spacing) / 2); width: calc(100% / var(--grid-columns) - var(--grid-spacing)); } @media (min-size: 600px) { :root { --grid-columns: 3; } } @media (min-size: 1024px) { :root { --grid-columns: 6; } } |
Теперь все вычисления выполняются в одном месте. Осталось лишь изменить значения пользовательских свойств во всех медиа запросах. Неважно, знаете вы код или нет, так он стал намного понятнее и более читаемым. И как бонус, так вы не ошибетесь при наборе в вычислениях в новых медиа запросах, и это не приведет к неожиданным результатам!
Замечание: код выше может быть слишком сложным для CSS препроцессоров. Имейте это в виду, если используете что-то подобное и получаете неожиданный результат!
Теперь, когда вы знаете, как сделать свой CSS более читаемым и простым в обслуживании, мы узнаем, как JavaScript может выиграть от пользовательских свойств.
Источник: //sgom.es/
Редакция: Команда webformyself.