web design uiNovember 5, 20267 min read

Цвета CSS-градиента: почему градиент сереет посередине и 3 способа это исправить

Смешайте синий с жёлтым, и середина станет серой, потому что hex-цвета смешиваются в RGB. Добавьте среднюю точку, смешивайте в OKLCH или берите соседей по цветовому кругу. Внутри пять готовых градиентов.

By Boone
XLinkedIn
CSS Gradient Colors: Why Gradients Turn Gray in the Middle and 3 Ways to Fix It

Градиент серит посередине, потому что браузер смешивает hex-цвета в RGB, а два цвета, стоящие напротив друг друга, на полпути взаимно гасятся. Решение: дать середине цвет осознанно или изменить способ расчёта смешивания. Вот три способа и пять градиентов, которые можно просто вставить.

Почему середина становится серой

Посмотрите на градиент, который выглядит грязным, и забудьте про края. С краями всё в порядке. Их вы выбирали сами. Середину не выбирал никто.

Градиент это смешивание, а смешивание требует математики. Hex-цвета это значения RGB, поэтому по умолчанию браузер смешивает их канал за каналом.

На полпути между синим и жёлтым красный находится посередине между 0 и 255, зелёный посередине между 0 и 255, а синий посередине между 255 и 0. Каждый канал оказывается около 128. Равные красный, зелёный и синий это определение серого.

#0000FF в #FFFF00

Градиент от синего к жёлтому, который посередине становится плоским серым

Со средней точкой #0EBAAE

Тот же градиент от синего к жёлтому с бирюзовой серединой, который остаётся цветным на всём протяжении
Те же два края. Слева смешивание идёт напрямую через #808080. Справа середина бирюзовая, и градиент остаётся живым от начала до конца.

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

Способ 1: добавить среднюю точку

Самый прямой способ: перестать оставлять середину на волю случая. Добавьте третью цветовую точку на 50%, выбранную вами.

css
background: linear-gradient(90deg, #0000FF, #0EBAAE, #FFFF00);

#0EBAAE это бирюзовый, который по восприятию лежит между синим и жёлтым. Теперь смешивание идёт от синего к бирюзовому, затем от бирюзового к жёлтому, и ни одна половина не пересекает серый.

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

Способ 2: смешивать в OKLCH

Другой способ меняет математику, а не добавляет цвет. CSS позволяет выбрать цветовое пространство, в котором происходит смешивание, а OKLCH описывает цвет через светлоту, насыщенность (chroma) и оттенок. Chroma показывает, насколько цвет яркий, поэтому смешивание, которое сохраняет chroma, остаётся цветным.

css
background: linear-gradient(in oklch, #0000FF, #FFFF00);

С in oklch браузер идёт вокруг цветового круга, через зелёные и бирюзовые, а не напрямую через серый центр. Цветов по-прежнему два, а код короткий. MDN описывает это как метод интерполяции цвета внутри функции градиента, а старые hex-цвета используют RGB, только если вы ничего не выбрали, ради совместимости со старыми страницами.

Две вещи, которые стоит знать. Часть цветов на этом пути может оказаться за пределами того, что способен показать экран, поэтому браузеры обрезают их до ближайшего отображаемого значения. И маршрут идёт по короткой дуге круга, так что проверьте, нравится ли вам выбранный путь. Наш гид по цвету OKLCH в современном CSS разбирает это пространство подробнее.

Способ 3: брать соседей

Третий способ не трогает код. Он выбирает цвета, которые не могут погасить друг друга.

#0066FF в #FF8800

Градиент от синего к оранжевому, который посередине становится тусклым коричневато-серым

#6440E0 в #E040A0

Градиент от фиолетового к розовому, который остаётся ярким на всём протяжении
Синий и оранжевый противоположны, поэтому встречаются в тусклом #807780. Фиолетовый и розовый соседи, поэтому встречаются в насыщенном #A240C0.

Противоположные цвета смешиваются в серый. Соседи смешиваются во что-то среднее, что всё ещё остаётся цветом. Если бренд сочетает две противоположности, их всё равно можно использовать в градиенте: поставьте между ними среднюю точку или смешивайте в OKLCH.

Синий в оранжевый, смешивание по умолчанию

Градиент от синего к оранжевому с коричневато-серой серединой

Синий в оранжевый, in oklch

Тот же градиент от синего к оранжевому, смешанный в OKLCH, проходит через фиолетовый и розовый вместо серого
Те же два края, что и раньше, изменилось только смешивание. Серого больше нет, а середина ярко-розовая.

Как проверить собственный градиент

  1. Смотрите на середину, а не на края.
  2. Назовите цвет, который там видите. Если название серый, коричневый или грязь, как у #808080 или #807780, это и есть проблема.
  3. Выберите один из способов выше и сравните две версии рядом.

Градиент хорош ровно настолько, насколько хороша его худшая точка, а худшая точка почти всегда посередине.

Пять градиентов, которые можно забрать

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

Градиент от синего через бирюзовый к жёлтому
Синий, бирюзовый, жёлтый. Нажмите на цвет, чтобы скопировать код.
Градиент от фиолетового к розовому
От фиолетового к розовому. Нажмите на цвет, чтобы скопировать код.
Градиент от синего к бирюзовому
От синего к бирюзовому. Нажмите на цвет, чтобы скопировать код.
Градиент от оранжевого к ярко-розовому
От оранжевого к ярко-розовому. Нажмите на цвет, чтобы скопировать код.
Градиент от зелёного к лаймовому
От зелёного к лаймовому. Нажмите на цвет, чтобы скопировать код.
ГрадиентНачалоСерединаКонецПочему работает
Синий, бирюзовый, жёлтый#0000FF#0EBAAE#FFFF00Противоположные края, спасённые настоящей средней точкой
Фиолетовый в розовый#6440E0нет#E040A0Соседи на круге
Синий в бирюзовый#2F5BEAнет#14B8A6Соседи на круге
Оранжевый в ярко-розовый#FF7A00нет#FF2E93Соседи на круге
Зелёный в лаймовый#00A86Bнет#C6F432Соседи на круге

Передайте это разработчику

css
.gradient-sunrise { background: linear-gradient(90deg, #0000FF, #0EBAAE, #FFFF00); } .gradient-violet { background: linear-gradient(90deg, #6440E0, #E040A0); } .gradient-ocean { background: linear-gradient(90deg, #2F5BEA, #14B8A6); } .gradient-sunset { background: linear-gradient(90deg, #FF7A00, #FF2E93); } .gradient-meadow { background: linear-gradient(90deg, #00A86B, #C6F432); } /* Two opposite colors, no middle stop: choose the blend space instead. */ .gradient-opposites { background: linear-gradient(in oklch, #0066FF, #FF8800); }

Если браузер не понимает in oklch, он игнорирует всё объявление целиком. Сначала напишите обычную строку linear-gradient(...) как запасной вариант, а после неё строку с OKLCH.

FAQ

Почему мой градиент серый посередине?

Hex-цвета смешиваются в RGB, а два цвета, далёкие друг от друга на цветовом круге, усредняются в серый. Синий #0000FF и жёлтый #FFFF00 встречаются в #808080.

Как сделать так, чтобы CSS-градиент не выглядел грязным?

Добавьте среднюю цветовую точку с живым цветом, смешивайте в OKLCH через linear-gradient(in oklch, ...) или выберите два цвета, которые стоят на круге рядом.

Что делает "in oklch" в CSS-градиенте?

Он говорит браузеру смешивать цвета в пространстве OKLCH вместо RGB, поэтому середина сохраняет цвет, а не падает в серый.

Какие цвета для градиента хорошо сочетаются?

Соседи по цветовому кругу, например фиолетовый #6440E0 в розовый #E040A0 или зелёный #00A86B в лаймовый #C6F432. Их смешивание остаётся ярким на всём протяжении.

Все ли браузеры поддерживают градиенты в OKLCH?

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

Почему синий с жёлтым даёт серый, а не зелёный?

Потому что смешивание идёт по прямой через RGB, где среднее двух цветов серое. Зелёная середина появится, только если добавить её как точку или смешивать в OKLCH.

Источники

  • CSS Color Module Level 4, interpolation: устаревшие цвета sRGB, такие как hex, по умолчанию интерполируются в sRGB, а другие пространства выбираются методом интерполяции цвета.
  • MDN, linear-gradient(): синтаксис <color-interpolation-method>, in oklch.
  • MDN, OKLCH color: светлота, насыщенность и оттенок.
  • Середина между (0, 0, 255) и (255, 255, 0) это (127.5, 127.5, 127.5), то есть #808080 с OKLCH chroma 0. Средние точки #0066FF в #FF8800 (#807780) и #6440E0 в #E040A0 (#A240C0) мы рассчитали в sRGB. Полосы на этой странице отрисованы по этим расчётам, а полоса OKLCH обрезает цвета за пределами диапазона экрана, как это делают браузеры.
  • Впервые опубликовано как карусель в UX Brainy.

Want gradients, color and every other detail designed as one system? Our team designs and builds product UI that holds up on every screen.

Get Started

More from Brainy Papers

Keep reading