Руководство по цветам в вебе для «ботаников»

Перевод статьи A Nerd’s Guide to Color on the Web с сайта CSS-Tricks.com для CSS-live.ru, автор — Сара Дрэснер

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

Цветосмешение

При работе с цветом очень важно понимать, что привычные еще с детства подходы к цветам не работают в компьютере из-за смешения цветов. В детстве мы работали с краской. В красках и чернилах из принтера есть маленькие частички — пигменты, которые смешиваются между собой и отражают свет, чтобы представить цвет глазу. Это субтрактивное (от англ. subtract — вычитание) цветосмешение. Чем больше цветов вы добавляете, тем темнее становится результат, пока не получится коричневый цвет. Основные цвета близки к тому, к чему вы привыкли: красный, желтый, синий. Но если смешать их при субтрактивном цветосмешении, вы придете к коричневому.

Субтрактивное цветосмешение пигментов

На компьютере (или любом мониторе) мы работаем со светом. Что значит, что если перемешать все цвета, они дадут белый. До знаменитого эксперимента Исаака Ньютона с призмой считалось, что цвет заключен в объектах, а не отражается и поглощается объектами. Исаак Ньютон с помощью призмы доказал свою теорию, что солнечный или любой яркий белый свет — на самом деле несколько цветов, благодаря призме разделив цвета и получив радугу, а затем попытавшись еще раз разделить с помощью призмы синий цвет. Синий цвет не разделился, показав, что цвет не содержался в призме, а призма разделила свет. Это значит, что при аддитивном (от англ. add — сложение) цветосмешении — том типе цветосмешения, что получается у вас на мониторе — из красного, зеленого и синего можно получить все цвета, или rgb. При таком цветосмешении красный и зеленый дают желтый.

color-mixing

Аддитивное и субтрактивное цветосмешение

Мониторы — это множество комбинаций из маленьких частичек света,собранных вместе и работающих синхронно, чтобы получить огромную массу цветов. Разрешением называют количество отдельных цветовых точек — пикселей — содержащихся в экране. Задолго до мониторов частоту света так использовали художники. Сёра́ и пуантилисты создавали желтый с помощью красного и зеленого в картинах наподобие «Гранд-Жатт» (хотя сам Сёра предпочитал термин «хромолюминаризм», а другие называли это дивизионизмом). Этот стиль живописи вырос из убеждения, что оптическое смешение порождает в глазах более чистый резонанс, чем традиционное субтрактивное цветосмешение пигментов.

seurat-detail

Мониторы выпускаются с несколькими разными режимами отображения, из-за которых мы по-разному воспринимаем цвета на них. Мы называем это термином «глубина цвета в битах». Количество цветов, которое можно отобразить одновременно, определяется этой глубиной цвета. При глубине цвета 1 бит мы можем получить два цвета, или монохромное изображение. Глубина цвета 2 бита дает 4 цвета, и так далее вплоть до 32-битной глубины, хотя обычно у мониторов, используемых для веба, бывает 24-битная глубина цвета и 16 777 216 цветов (True Color) с альфа-каналом.

Мы называем это «True Color», потому что человеческий глаз различает до 10 миллионов отдельных цветов, так что 24-битной глубины для этого заведомо достаточно. Из этих 24 бит 8 выделены для красного, зеленого и синего. Остальное используется для прозрачности или альфа-каналов (прим. перев.: похоже, у автора неточность — в 24-битном True Color по 8 бит на каждый цветовой канал, без прозрачности, об этом сказано в первом комментарии к оригиналу статьи).

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

Значения цвета

Значения RGB

Последний раздел поясняет, о чем говорит запись rgba(x, x, x, y);, но давайте разберем это еще поподробнее и покажем еще несколько свойств с их применениями. В терминах значений веб-цветов в RGB-канале мы указываем цвет в диапазоне 0-255.

x обозначает число в диапазоне 0-255
y — число от 0.0 до 1.0
rgb(x, x, x); или rgba(x, x, x, y);

Пример: rbga(150, 150, 150, 0.5);

Hex-значения

Шестнадцатиричные цвета (Hex-цвета) — чуть другой формат для представления значений тем же образом. Hex-значения, пожалуй, самый общеупотребительный способ, которым веб-разработчики задают цвета в вебе.

Если вспомнить, что байт — это 8 бит, каждый шестнадцатиричный цвет представляет байт. Цвет указывается в соответствии с интенсивностью своих красного, зеленого и синего компонентов, так что это называется триплетом, причем каждый компонент выражается двумя знаками. Один байт представляет собой число в диапазоне от 00 до FF (в шестнадцатиричной записи) или от 0 до 255 в десятичной. Первый байт — это красный, второй — зеленый, третий — синий. Название Hex происходит от 16-ричной системы (англ. hexadecimal). Значения берутся из диапазона 0-9 и A-F, где 0 — наименьшее, а F — наибольшее, или #000000 — черный, а #FFFFFF — белый.

Для триплетов с повторяющимися значениями можно избавиться от повторения, записав их сокращенно, например, #0FF вместо #00FFFF. Эта система легко понятна компьютерам и очень кратка в записи, что делает ее полезной для быстрого копирования и задания цветов в программировании. Но если вы собираетесь делать с цветами что-то более сложное, для человека всё-таки чуть понятнее HSL.

HSL-значения

Логика и диапазоны, с которыми работают HSL-значения, похожи на таковые в RGB, но HSL-значения работают не со значениями, которыми представляет цвета монитор, а со значениями тона, насыщенности и яркости. Синтаксически это выглядит похоже на RGB-значения, но диапазоны другие. Эта система основана на цветовой системе Манселла (он был первым, кто разделил цвет на эти три канала или создал трехмерную систему на базе математических принципов, привязанных к реальному человеческому зрению).

munsell_1929_color_solid

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

Тон вращается на 360 градусов, по полному кругу, а насыщенность и яркость — это проценты от 0 до 100.

x — число от 0 до 360
y — проценты от 0% до 100%
z — число от 0.0 до 1.0
hsl(x, y, y); или hsla(x, y, y, z);

Пример: hsla(150, 50%, 50%, 0.5);

Для браузеров переход от RGB-значений к HSL и обратно — достаточно простое изменение (около 11 строк кода, если точнее), но нам, людям, разобрать HSL намного проще. Представьте себе колесо, с плотным и насыщенным содержимым в центре. Этот пример весьма неплохо показывает, как это выражается.

Крис несколько лет назад тоже сделал удобный инструмент под названием «hsla explorer», который можно попробовать здесь.

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

Именованные цвета

Именованные цвета нам, разработчикам, тоже доступны. Но работать с именованными цветами считается сложным из-за их неточности. Самые заметные и «знаменитые» примеры — то, что dark grey (тёмно-серый) на самом деле светлее, чем grey (просто серый), а lime (цвет лайма) и limegreen (зеленый оттенка лайма) — совершенно разные цвета. Есть даже игра, в которой надо угадывать именованные цвета в вебе, ее сделал Крис Хайльман. Когда-то давно chucknorris был кроваво-красным цветом (сейчас он поддерживается только в HTML, насколько я могу судить), но это был мой любимый цвет (прим. перев.: в HTML есть специальный алгоритм, преобразующий практически любые слова в Hex-значения, в комментариях к оригиналу статьи об этом рассказано подробнее). Именованные цвета бывают полезны, когда нужно быстро показать применение цвета, но чаще разработчики пользуются Sass и другими препроцессорами, чтобы хранить значения цветов в Hex, rgba или hsla, привязывая их к названиям цветов, принятым в компании.

Цветовые переменные

Считается правильным хранить цвета в переменных и никогда не использовать их напрямую, а вместо этого привязывать их другим переменным с более осмысленной системой именования. В CSS есть «родные» переменные, наподобие:

:root {
  --brandColor: red;
}

body {
  background: var(--brandColor);
}

Но они еще слишком новые и на момент выхода статьи еще не добрались до браузеров Microsoft.

CSS-препроцессоры тоже поддерживают переменные, так что можете заводить переменные вроде $brandPrimary и использовать их сплошь у себя в коде. Либо ассоциативный массив:

$colors: (
  mainBrand: #FA6ACC,
  secondaryBrand: #F02A52,
  highlight: #09A6E4
);

@function color($key) {
  @if map-has-key($colors, $key) {
    @return map-get($colors, $key);
  }

  @warn "Неизвестный `#{$key}` в $colors.";
  @return null;
}

// _component.scss
.element {
  background-color: color(highlight); // #09A6E4
}

Помните, что именование здесь важно. Иногда полезны абстрактные имена, так что если вы измените переменную, представляющую синий цвет, на оранжевый, вам не придется перелопачивать весь код и переименовывать все цветовые значения. Или хуже того, вешать объявление «$синий теперь оранжевый». *печальный вздох тромбона*

currentColor

currentColor — невероятно полезное значение. Оно подчиняется каскаду и полезно для распространения значения цвета на штуки вроде теней блока, обводок (outline), рамок и даже фонов.

Пусть у нас есть div, а в нем еще один div. Вот это сделает оранжевую рамку для внутреннего дива:

.div-external { color: orange; }
.div-internal { border: 1px solid currentColor; }

Это невероятно полезно для систем иконок, как SVG-шных, так и иконочных шрифтов. Можно задать currentColor в качестве значения по умолчанию для заливки (fill), обводки (stroke) или цвета текста (color), а затем использовать для оформления семантически подходящие CSS-классы, и иконка сама «подтянет» нужное значение.

Препроцессоры

CSS-препроцессоры замечательно подходят для возни с цветами. Вот несколько ссылок на документацию по цветовым функциям для разных препроцессоров:

Вот несколько крутых штук, которые можно делать именно с Sass:

mix($color1, $color2, [$weight])
adjust-hue($color, $degrees)
lighten($color, $amount)
darken($color, $amount)
saturate($color, $amount)

Наверняка есть десятки способов программно смешивать и менять цвета с помощью препроцессоров, и мы не будем углубляться в них все, но вот великолепный интерактивный ресурс с более подробной информацией.

Цветовые свойства

Color, как CSS-свойство, относится к цвету текста. Чтобы задать цвет большой области, вам пригодится background-color, если только это не SVG-элемент, в случае которого подойдет fill. Border — это рамка вокруг HTML-элемента, тогда как stroke — ее SVG-шный аналог.

Тени блока и текста

Свойства box-shadow и text-shadow принимают значение цвета. Тени текста принимают 2-3 значения: г-тень (сдвиг тени по горизонтали), в-тень (сдвиг тени по вертикали) и необязательный радиус размытия. Тени блоков принимают 2-4 значения, г-тень, в-тень, необязательный радиус размытия и необязательная дистанция распространения. Еще можно указать в начале inset, чтобы получить внутреннюю тень. На этом сайте есть замечательные примеры с простым кодом, который легко скопировать.

Градиенты

Для работы линейных градиентов надо задать направление. От/к (в зависимости от браузерного префикса) верха, низа, левого или правого края, в градусах или вообще радиальные градиенты. Затем указываем контрольные точки и цвета, которые должны быть в этих точках. Они также принимают прозрачность.

Вот пример:

В основном записывать синтаксис градиентов не настолько уж трудно, но мне вправду нравится работать с этим онлайновым генератором градиентов, поскольку он заодно создает сложное свойство filter для поддержки IE6-9. А вот еще очень красивый инструмент для создания градиентов uiGradients. Он замечательный и притом опенсорсный, так что можете поучаствовать в нем.

Столь же легко создавать градиенты в SVG. Мы определяем блок <linearGradient> и ссылаемся на него по id. Можно определить еще и поверхность для градиента.

<linearGradient id="Gradient">
   <stop id="stop1" offset="0" stop-color="white" stop-opacity="0" />
   <stop id="stop2" offset="0.3" stop-color="black" stop-opacity="1" />
</linearGradient>

Эти градиенты тоже поддерживают прозрачность, так что можно добиться интересных эффектов, в т.ч. со слоями, например, анимировать их в качестве масок.

Можно сделать и градиентный текст, только в вебките (уже не только — прим. перев.), есть хорошая заготовка кода здесь на CSS-Tricks (а здесь на css-live есть стандартная кроссбраузерная альтернатива — прим. перев.).

Генерируемые цвета

Есть несколько классных способов получить сразу кучу впечатляющих цветов. Мне всегда в радость играть с ними при программной генерации художественных объектов или элементов интерфейса.

Если не выходить за границы диапазонов, обозначенных в последних разделах, можно воспользоваться циклами for либо в Sass (или любом CSS-препроцессоре), или в JavaScript, либо получить значения цвета с помощью Math.Random() и Math.floor(). Math.floor() или Math.ceil() тут нужны для того, что если на выходе будет не целое число, мы получим ошибку и не сможем получить значение цвета.

Придерживайтесь полезного правила, что не надо изменять все три значения сразу. У меня удачные результаты выходили при сильном изменении в одном диапазоне значений, меньшем изменении второго значения и неизменном третьем значении, не обязательно именно в таком порядке. Например, в hsl очень легко переходить от одного цвета к другому, поскольку известно, что цикл по цветовому тону от 0 до 360 дает весь диапазон. Еще один плюс вращения цветового тона в градусах в том, что это полный круг, можно не ограничиваться диапазоном 0–360, даже -480 или 600 — по-прежнему понятные браузеру значения.

Sass

@mixin colors($max, $color-frequency) {
  $color: 300/$max;
  
  @for $i from 1 through $max {
    .s#{$i} {
      border: 1px solid hsl(($i - 10)*($color*1.25), ($i - 1)*($color / $color-frequency), 40%);
     }
  }
} 
.demo {
  @include colors(20,2);
}

Я использовала это, чтобы фрукт менял цвет по циклу в этом примере:

А также в этом, с другим диапазоном (быстро прокручивайте содержимое списка):

В примере ниже, я использую Math.random() для значений rgb, чтоб наштамповать множество цветов в одном и том же диапазоне. Этот пример создает трехмерную сцену виртуальной реальности с помощью React. Я могла бы перебрать их и циклом for, но мне хотелось, чтобы цвета были случайными и тем самым лучше отражали движение. Простор для творчества тут безграничен.

2932663-react-aframe

Кликните по картинке, чтобы посмотреть пример целиком.

JavaScript

class App extends React.Component {
  render () {
    const items = [],
          amt1 = 5,
          amt2 = 7;
    for (let i = 0; i < 30; i++) {
     let rando = Math.floor(Math.random() * (amt2 - 0 + 1)) + 0,
          addColor1 = parseInt(rando * i),
          addColor2 = 255 - parseInt(7 * i),
          updateColor = `rgb(200, ${addColor1}, ${addColor2})`;
      items.push(<Entity geometry="primitive: box; depth: 1.5; height: 1.5; width: 6" 
                material={{color: updateColor}} ...
                key={i}>
	    ...
        </Entity>);
    }
    return (
      <Scene>
       ...
       {items}
      </Scene>
    );
  }
}

В библиотеку GreenSock входит инструмент, позволяющий анимировать относительные значения цвета, что полезно, так как позволяет взять много элементов сразу и анимировать их относительно их текущих цветовых координат. Вот небольшая демонстрация этого принципа на черепашках:

TweenMax.to(".turtle2 path, .turtle2 circle, .turtle2 ellipse", 1.5, {fill:"hsl(+=0, +=50%, +=0%)"});

Другие интересные цветовые эффекты

Режимы смешивания и наложения фонов

Если вы пользовались эффектами слоев в Photoshop, вы, скорее всего, знакомы с режимами смешивания. Они использовались на почти каждом сайте в 90-х (на моем тоже *краснею*). Режимы смешивания и наложения фонов объединяют два изображения в один композитный слой, и для этого есть 16 режимов. Подробности каждого из них — за рамками этой статьи, но вот несколько ключевых примеров.

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

mixblend

Если желаете заморочиться основательно, как я, цветовые формулы для режимов наложения зависят от типа используемого эффекта. Например, режим «умножение» (multiply) — это получатель × источник = подложка. Другие эффекты — это вариации простых формул на основе вычитания, умножения, сложения и деления. Линейный режим — это A+B−1, а режим Color Burn — это 1−(1−B)÷A. Но можно пользоваться ими и не зная всех этих формул.

Вот более развёрнутая документация, а вот очень простой пример, показывающий, как работает цвет с некоторыми из этих эффектов:

Эта замечательная статья Робина тоже показывает несколько по-настоящему сложных и впечатляющих эффектов, которых можно достичь применением нескольких режимов наложения по очереди. Ниже мы рассмотрим совмещение их с фильтрами. В наши дни в браузере можно делать очень многое.

Фильтры

CSS-фильтры предоставляют много отличных цветовых эффектов, а также возможность взять цветную картинку и сделать ее черно-белой. Есть замечательный ресурс здесь на CSS-Tricks, показывающий, как они работают, да и поддержка браузерами сейчас весьма неплоха. У Беннета Фили тоже есть вот такая симпатичная галерея фильтров, если вас тянет на исследования.

Фильтры и режимы размытия могут работать вместе! Юна Кравец сделала этот прекрасный инструмент под названием CSS Gram, объединив некоторые эффекты, чтобы воссоздать типовые фильтры из Instagram, внизу там у нее есть хорошая документация.

feColorMatrix

У Юны есть еще одна статья о том, как создать эти же изображения другим способом — с помощью feColorMatrix, представляющего собой примитив фильтра в SVG, который можно применять и к HTML-элементам. Он очень мощный и позволяет работать с цветом с филигранной точностью. Как видно из названия, базовая разметка feColorMatrix использует матрицу значений, и мы вызываем ее по назначенному ей id.

<filter id="imInTheMatrix">
    <feColorMatrix in="SourceGraphic"
      type="matrix"
      values="0 0 0 0 0
              1 1 1 1 0
              0 0 0 0 0
              0 0 0 1 0" />
</filter>

<path filter="url(#imInTheMatrix)"  … />

Можно также расширить эту матрицу и подстроить тон, насыщенность и т.д. этих значений:

<filter id="imInTheHueMatrix">
  <feColorMatrix in="SourceGraphic"
    type="hueRotate"
    values="150" />
</filter>

Все эти возможности подробно рассматриваются в статье Юны, но вы можете найти еще больше информации об этом и многих других умопомрачительных инструментах SVG для цветов и градиентов в книге Амелии Беллами-Ройдз «Цвета, паттерны и градиенты в SVG», выпущенной издательством O’Reilly, или в поясняющем примере Майка Маллани.

Доступность и еще кое-что на заметку о цветах

Цвет существует не сам по себе, а в связи с другим цветом. Вот в чем сложность цветов. Вы наверняка знакомы с этим с точки зрения доступности. Бледно-зеленый на черном может быть доступным, но если поменять фон на белый — уже нет.

context-color

Цветовую доступность можно измерить многими инструментами. Вот некоторых из моих любимых:

Неплохо также с самого начала настроить палитру для доступности. Color Safe — замечательный инструмент, способный помочь в этом. А когда всё уже настроено, оценить страницу поможет WAVE (инструмент веб-доступности):

Цвет и атмосфера

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

landscape

Пейзаж, показывающий разницу в цветах между близкими и далекими предметами

Тени

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

shadow-color

Поля ввода для цвета

В браузерах есть встроенный инструмент для выбора цвета, с помощью которого ваши пользователи могут выбирать цвета динамически. Можно написать <input type="color"> или <input type="color" value="#ff0000">, если предпочитаете, чтобы с самого начала была подсказка цвета. Вот так просто. Молодцы, браузеры. Единственное, что нужно иметь в виду — они могут чуть по-разному выглядеть от браузера к браузеру, как, впрочем, и любые другие встроенные элементы управления. Этот пример Ноа Блона показывает, как использовать это в тандеме с цветовым CSS-фильтром «тон», чтобы динамически выделять элементы картинки, цвет которых нужно изменить. Оставшаяся часть картинки черно-белая, поэтому не затрагивается. Ловко придумано.

Занятности для разработчиков и другие ресурсы

  • Плагин Color Highlighter для редактора Sublime Text — то, с помощью чего я легко определяю, какой цвет браузер сможет распознать. Мне нравится использовать {"ha_style": "outlined"}, но из этой статьи я узнала, что Уэс Бос предпочитает «filled».
  • Есть несколько разных традиционных комбинаций для палитры и онлайновых ресурсов, с помощью которых можно их генерировать. Для любителей чего-то более научного — Paletton или Adobe Color. Бенджамин Найт воссоздал инструмент Adobe Color на библиотеке d3 (на CodePen), это весьма мастерская работа, на которую стоит взглянуть. Если хотите, чтобы веб сделал за вас всю тяжелую работу (а кто не хочет?), нет ничего проще Coolors.
  • Если вам нужна помощь в понимании цветов, или вы ищете простой быстрый инструмент, который менял бы вам цветовые свойства с одного типа на другой,  Colorhexa обеспечит вас всеми мыслимыми типами замены цвета.
  • Для самых дотошных «ботаников» по части цвета, можно даже настроить цветной вывод в консоли. Вот замечательный пример, показывающий, как это работает (и есть подробная статья Юли Бухваловой на эту тему — прим. перев.).

Заключение

Тема этой статьи довольно обширна, а в вебе масса цвета, в котором стоит покопаться, но, надеюсь, эта краткая статья станет вам отправной точкой для экспериментов и понимания.

P.S. Это тоже может быть интересно:

5 Комментарии

  1. Otshelnik-Fm

    rgba цвет не от 0-255. Можно поставить 666 — браузер приведет его к 255. Полезно чтобы не делать проверку на выход за пределы 255 (если это скрипт)

  2. SelenIT (Автор записи)

    Рабочий диапазон до 255 всё же. То, что значения автоматом ужимаются до него — удобно, конечно. Но не всегда (как и любая «молчаливая» коррекция ошибок).

  3. newJS

    Я бы не стал утверждать что HSL понятней чем RGB, и там и там числа которые наш глаз не может по простому перевести в цвет.

    silver
    hsl(0, 0%, 75%) — HSL
    RGB(192,192,192) — RGB
    #C0C0C0 — HEX
    12632256 — WIN(браузеры это не понимают, кроме осла)

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

    у меня на сайте есть программа, может именно она кому то будет более удобна
    Подбор и Конвертация HTML цветов

    P.S.
    WIN это формат в котором винда возвращает цвет в стандартном окне выбора цвета. Все не единожды юзали это окно.

    1. SelenIT (Автор записи)

      Думаю, имелось в виду, что логика HSL ближе к «бытовой» логике сравнения цветов, в которой мы чаще оперируем понятиями «светлее/темнее», «ярче/тусклее» и «ближе к одному оттенку, чем к другому», а не раскладываем в уме цвет на компоненты и сравниваем их по отдельности. Хотя с тем, что удобнее то, что привычно, не спорю)

  4. newJS

    Да, тут согласен, наверно действительно ближе, не зря же именно в HSL рекомендуют сортировать цвета, хотя на практике это оказалось не так, но сортировка действительно лучше, чем всё остальное, что мне пришлось пробовать для своей программы.
    P.S.
    В мою программу HSL будет добавлен в последующих версиях, уже есть всё что нужно, делать надо….

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

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