Сайт вебмастера

Принципы Material Design

30-08-2020Время чтения ~ 9 мин.Berry CSS 3550

Думаю, что каждый вебмастер слышал о концепции Material Design от Google. В целом она рассчитана на разработчиков мобильных приложений, но может частично применяться и для обычных сайтов. В первую очередь речь идёт о подборе цветовой палитры.

Влияние Material Design нашло своё отражение в css-фреймворках, правда в ограниченном объёме.

Я хочу рассказать о Material Design с этой точки зрения, поскольку будущая Berry 3 будет поддерживать его цветовую схему полностью. Начнём с описания того, как обычно создаётся сайт.

Итак, первоначально сайт рисует дизайнер, где отдельно выделяет используемые цвета. Это не только типографика, но и различные блоки. Как правило значения приводятся в RGB в виде #RRGGBB. После этого верстальщик (предполагаем, что мы используем css-препроцессор, хотя это не столь принципиально) создаёт переменные для этих цветов. Что-то вроде:

$color-header-bg: #...
$color-footer-bg: #...
$color-block1-bg: #...
$color-block26-bg: #...
и т.д.

В css/sass-коде используются эти переменные в виде css-классов. Такие цвета называются фиксированными, поскольку имеют точные значения. Если стоит задача сменить дизайн, то достаточно поменять соответствующую переменную.

Теперь перейдем от css-верстки к созданию самого дизайна макета. Не каждый дизайнер имеет врождённое чувство цвета, поэтому были придуманы различные цветовые теории, предлагающие подбор «правильных» цветов. Самый простой пример — монохромная палитра, когда из базового цвета получают его темные и светлые оттенки.

Опытный дизайнер как правило работает в цветовой модели HSB/HSL, которая описывает цвет в трех числах: hue (оттенок), satutation (насыщенность) и lightness (яркость/светлость). Оттенок определяется по цветовому кругу в градусах от 0 до 360, а насыщенность и яркость в процентах от 0 до 100.

Если вы никогда не сталкивались с этой моделью, то загляните в википедию, где это всё подробно описано.

Так вот, монохромная палитра подразумевает, что цвета будут иметь примерно один и тот же оттенок и насыщенность, но будет меняться только яркость.

Дизайнер, использующий данный подход, опишет цвета уже в модели HSL (которая используется в CSS), например так:

$color-header-bg: hsl(210, 83, 52);
$color-footer-bg: hsl(210, 83, 75);
$color-block1-bg: hsl(210, 83, 34);
$color-block26-bg: hsl(210, 83, 59);
и т.д.

Здесь также используются фиксированные цвета, но у верстальщика уже есть понимание того, как именно они строятся. Такие цвета задаются в виде переменных. В Berry CSS (и UniCSS) также можно использовать фиксированные цвета в виде color1, color2 и т.д. (имя произвольно), в других фреймворках используются другое именование: error, info, warning и прочие.

Некоторые фреймворки, подражая Material Design, ввели переменные для primary (первичный цвет) и secondary (вторичный), что ещё не означает следование этой концепции. Например — Bootstrap 4, UiKit и т.д. В них используются только фиксированные цвета, а для Material Design нужны ещё яркостные градации.


Возвращаясь к монохромной палитре, нетрудно заметить, что цвет меняется только в виде яркости. Поэтому логичным будет вместо функционального назначения, указывать непосредственное название тона. То есть вместо $color-header-bg будем использовать $blue600, а вместо $color-footer-bg — $blue700.

Меняется сам подход к построению дизайна. Если раньше дизайнер предлагал точечные цвета, то теперь он вначале создаёт монохромную палитру какого-то оттенка (в нашем примере — blue). Такая палитра, естественно, легко формируется верстальщиком и меняется в любой момент. Например, если клиент решил менять цвет с blue на teal, то по факту это лишь меняется значение hue в палитре цветов.

CSS-фреймворки подхватили эту идею и стали предлагать уже готовые палитры для некоторых цветов. Степень градации у всех разная, например в Tailwind CSS раньше использовались такие варианты:

.bg-red-darkest	
.bg-red-darker	
.bg-red-dark	
.bg-red
.bg-red-light	
.bg-red-lighter
.bg-red-lightest

Понятно, что это не так информативно, поэтому такие фреймворки быстро перешли на Material Design, где используются числовые ступени:

.bg-red100
.bg-red200
.bg-red300
.bg-red400
.bg-red500	
.bg-red600
.bg-red700
.bg-red800
.bg-red900

Такой вариант означает частичную поддержку Material Design. Она также есть в Berry CSS и UniCSS.


Здесь возникает один немаловажный вопрос: как именно будет создаваться монохромная палитра? Очевидно, что можно как-то автоматизировать этот процесс. То есть указывается только один базовый цвет, который автоматически разбивается на оттенки.

Я с этим вопросом столкнулся более 5 лет назад, когда делал UniCSS. Разные палитры мне были нужны для создания шаблонов MaxSite CMS, поскольку все сайты были в разных оттенках, то логично было автоматизировать этот процесс. Мне пришлось перепробовать очень много алгоритмов и через какое-то время я пришёл к sass-функциям lighten() и darken(). Вот кусок кода, чтобы было понятно:

@if $step == 50  { @include colors_state(#{$name}50,  lighten($color, 45%)); }
@if $step == 100 { @include colors_state(#{$name}100, lighten($color, 40%)); }
@if $step == 200 { @include colors_state(#{$name}200, lighten($color, 30%)); }
@if $step == 300 { @include colors_state(#{$name}300, lighten($color, 20%)); }
@if $step == 400 { @include colors_state(#{$name}400, lighten($color, 10%)); }
@if $step == 500 { @include colors_state(#{$name}500, $color); }
@if $step == 600 { @include colors_state(#{$name}600, darken($color, 10%)); }
@if $step == 700 { @include colors_state(#{$name}700, darken($color, 20%)); }
@if $step == 800 { @include colors_state(#{$name}800, darken($color, 30%)); }
@if $step == 900 { @include colors_state(#{$name}900, darken($color, 38%)); }

То есть базовый цвет для градаций 50..400 осветляется, а для остальных затемняется. При данной простоте, здесь есть несколько проблем. Первая — нелинейность преобразования цвета. Наш глаз имеет разную спектральную чувствительность, а поскольку алгоритм линейный, то на выходе цвета оказываются немного в «странной» яркостной градации.

Вторая проблема — подбор базового цвета. Если он окажется чуть светлее, чем нужно, то вся палитра сваливается в светлые оттенки. Если темнее, то всё становится темнее, что даже 50-степень оказывается слишком насыщенной.

Третья проблема — о ней позже. :-)

В любом случае многие фреймворки пытаются автоматически создавать градации яркости. Например будущий Bootstrap 5 использует практически тот же подход, что и UniCSS пятилетней давности. При этом разработчики уже столкнулись с проблемой нелинейности цветов, и чтобы это исправить используют сложные алгоритмы, где цвет задаётся в совершенно непотребном виде:

$blue-100: tint-color($blue, 8);
$blue-200: tint-color($blue, 6);
$blue-300: tint-color($blue, 4);
$blue-400: tint-color($blue, 2);
$blue-500: $blue;
$blue-600: shade-color($blue, 2);
$blue-700: shade-color($blue, 4);
$blue-800: shade-color($blue, 6);
$blue-900: shade-color($blue, 8);

То есть используется корректирующий коэффициент. Но это не исправляет проблему подбора базового цвета, поскольку он всё также задаётся в произвольном RGB-варианте.

В Berry 2 я полностью отказался от автоматического расчёта, поскольку он постоянно даёт сбой и перешёл на систему, где каждый цвет задаётся отдельно в виде обычного css-цвета hsl().

В данном примереhsl() — это Sass-функция, которая на выходе отдаёт обычный #RGB-цвет. Для того, чтобы в scss-файлах использовать нативный hsl-цвет, следует его указывать в верхнем регистре: HSL(). Это позволяет избежать конфликта синтаксиса Sass с CSS.
$red50:  hsl(12, 100%, 96%);
$red100: hsl(11, 100%, 92%);
$red200: hsl(11, 100%, 85%);
$red300: hsl(10, 100%, 75%);
$red400: hsl(9, 100%, 65%);
$red500: hsl(8, 94%, 50%);
$red600: hsl(7, 94%, 42%);
$red700: hsl(6, 86%, 33%);
$red800: hsl(5, 74%, 24%);
$red900: hsl(4, 65%, 19%);

За основу были взяты профессиональные готовые палитры, с которых я просто снял цвет и конвертировал его в hsl-формат (поэтому там смещается оттенок от яркости). То есть в Berry 2 предполагалось, что дизайнер предоставляет уже готовую палитру без автоматического расчёта, чтобы точно попасть в цвет.

Это трудозатратно — такое количество цветов не так просто изменить, поэтому в Berry 3 подход к цветам был изменён. Здесь используется автоматический расчёт монохромных палитр, но цвет задаётся в виде двух значений: hue и saturation.

$colorHS-red:      4, 95%; // hue, saturation
$colorHS-brown:   15, 47%;
$colorHS-orange:  35, 99%;
$colorHS-yellow:  53, 99%;
$colorHS-lime:    64, 85%;
$colorHS-green:  122, 68%;
$colorHS-teal:   175, 58%;
$colorHS-cyan:   186, 82%;
$colorHS-blue:   206, 86%;
$colorHS-indigo: 231, 70%;
$colorHS-violet: 270, 91%;
$colorHS-purple: 290, 68%;
$colorHS-pink:   335, 82%;

Для расчёта яркости используется равномерная градация между 100 и 900. Таким образом мы получаем идеально-линейную шкалу яркости HSL, которая охватывает все оттенки цвета. Для оттенков 50 и 950 указываются отдельные значения яркости, поскольку они могут немного выбиваться из общей шкалы.

В Berry 3 предусмотрены 13 шкал + серый, да ещё и с шагом 50, то это покрывает практически любую потребность. При необходимости всё это легко настраивается и можно скорректировать любой цвет.

Таким образом переход от RGB в модель HSL позволило избавиться от ошибок неверной яркости. Дизайнер и верстальщик теперь работают с единой палитрой.

Но поскольку мы используем sass-функцию hsl(), то на выходе всё равно будет #RGB.

Теперь самое время затронуть третью проблему. Автоматическая градация не позволяет создавать sass-переменные промежуточных цветов. Например в Berry мы можем использовать $red600 в любом классе, а в UniCSS эта переменная недоступна, поскольку не определена. Это создаёт существенные проблемы верстки, когда нужно использовать уже готовый цвет, а не снимать его пипеткой и потом подбирать нужный оттенок.

.my-header1 {
    background: $red650;
}

Таким образом Material Design предполагает, что в дизайне будут доступны цвета всей палитры. Ими оперирует и дизайнер, и верстальщик. В Berry это реализовано.


На практике это привело к тому, что верстать теперь стали в какой-то выбранной палитре. Скажем в дизайне выбрали red, где автоматом можно использовать все его оттенки от 50 до 950. Именно так работает Berry 2 и будет работать Bootstrap 5. Это также лишь частичная поддержка Material Design, где доступны готовые монохромные палитры, но ещё нет поддержки первичного и вторичных цветов.

Когда мы используем классы цветов, то мы жестко фиксируем и сам дизайн. Если стоит задача сменить blue на red, придётся менять html-верстку каждого блока. Material Design для решения этой задачи предлагает использовать оттенки primary, secondary и другие (например акцент).

Здесь важно понять, что это не просто конкретный цвет, а именно hue-оттенок, поэтому когда создаётся дизайн в концепции Material Design, то используются именно эти условные обозначения.

$primary: $red;
$primary100: $red100;
$primary200: $red200;
и т.д.

Таким образом, если стоит задача сменить цветовой тон, то делается это только в sass-файле, сам html-код не меняется, поскольку используются классы вида: .bg-primary, .t-primary100, .bg-primary650 и т.д.


Теперь разберёмся почему используется несколько цветов. Если бы все сайты были в монохромной палитре, то Интернет стал бы скучным и безрадостным. Поэтому дизайнеры добавляют как минимум ещё один цвет, который отличается от основного.

Второй цвет можно назначить и наугад, но грамотные дизайнеры всё-таки изучают схемы комбинации цветов, чтобы они гармонично смотрелись и выполняли определённую роль. Например если нужно выделить какой-то блок или кнопку, то используется контрастная схема, где цвета располагаются на противоположных секторах цветового круга.

Поэтому для любой другой схемы, отличной от монохромной, потребуются другие оттенки. При этом с практической точки зрения мы можем говорить о трёх. В Material Design это primary, secondary, а третий цвет отдан на откуп дизайнера (в Berry 3 — это tertiary).

Подбор такой палитры дело творческое. Например Adobe Color предлагает сразу 5 цветов (работать нужно в HSB). Но это, конечно, уже перебор, поскольку с таким обилием оттенков нужно ещё уметь справляться. Поэтому общепринято (и используется в Material Design) два оттенка + дополнительный.

И здесь опять важный момент: primary, secondary и tertiary это не какие-то фиксированные цвета — это названия оттенков, которые доступны в их палитрах: .bg-primary600, .bg-secondary600, .bg-tertiary600 и т.п. То есть это три монохромные палитры, которые могут одновременно использоваться в дизайне.

Если сайт использует Material Design, то дизайнер вначале определяет эти палитры и указывает их оттенки на макете: здесь secondary450, а здесь цвет primary600, а для кнопки используется tertiary700. Соответственно, верстальщик работает ровно с этими же палитрами, а значит указывает одноимённые классы.

Посмотреть всё это в действии можно в документации Berry 3 в разделе Material Design. Посмотрите на пример в конце, где вёрстка выполнена на классах Material Design.

При использовании Berry 3 достаточно лишь указать три sass-переменные, чтобы получить все необходимые классы. Оттенки можно создавать и на основе других готовых палитр.

$colorHS-primary: $colorHS-blue;
$colorHS-secondary: $colorHS-indigo;
$colorHS-tertiary: $colorHS-cyan;
 
Либо:

$colorHS-primary: 206, 86%;
$colorHS-secondary: 231, 70%;
$colorHS-tertiary: 186, 82%;

Думаю, что использование Berry CSS с поддержкой Material Design, будет полезным как для дизайнеров, так и для верстальщиков.

UPDATE: см. цвета в Berry CSS 5.0

Похожие записи