Skip to content

Diamond-градиенты

Diamond-градиент - это gradiente-specific вид градиента. С точки зрения пользователя он работает почти как радиальный градиент, но вместо круглого поля расстояния использует diamond distance field. Пиксели измеряются по тому, насколько далеко они ушли от центра по горизонтали и вертикали, поэтому контуры одинакового расстояния образуют ромбы.

Из-за этого diamond-gradient(...) хорошо подходит для faceted glows, UI-подсветок, isometric-looking поверхностей, жестких полос, генерируемых pattern-систем и эффектов, где обычный radial gradient выглядит слишком круглым.

css
diamond-gradient(farthest-corner at 48% 45% in oklch, #5851db 0%, #c13584 35%, #fcb045 70%, #405de6 100%)
Пример diamond-градиентаСмещенное OKLCH diamond-полеdiamond-gradient(at 48% 45% in oklch, #5851db 0%, #c13584 35%, #fcb045 70%, #405de6 100%)
Превью загрузится, когда блок приблизится к viewport.

diamond-gradient не является нативной CSS-функцией градиента. Каждый preview-блок на этой странице отрисовывается через gradiente сразу в четырех targets: CSS target, Canvas 2D, Canvas WebGL и SVG. CSS target - это сгенерированный SVG data URL, а SVG target - pattern payload. Колонка WebGL захватывается как snapshot, чтобы страница не держала слишком много активных WebGL-контекстов одновременно.

Интеграция gradiente

Использование diamond-градиента во фреймворке

Diamond-градиенты не являются нативными CSS-функциями, поэтому transformTo('css') возвращает готовый для background SVG data URL. Одну и ту же распарсенную модель gradiente все равно можно подключить в React, Vanilla JS, Vue или Svelte.

ReactDiamondGradientPreview.tsx

Из чего состоит diamond-градиент

У модели diamond-градиента есть пять смысловых частей:

Имя функции`diamond-gradient(...)` или `repeating-diamond-gradient(...)`. Публичный тип экземпляра остается `diamond-gradient`; повтор хранится в config.
Поле расстоянияDiamond-метрика. `circle` сохраняет одинаковые x/y радиусы; `ellipse` позволяет использовать разные x/y радиусы.
РазмерExtent keyword вроде `closest-side`, `closest-corner`, `farthest-side`, `farthest-corner` или явные радиусы в length/percentage.
ПозицияЦентральная точка после `at`: например `at left top`, `at center` или `at 25% 75%`.
Stop-листColor stops, опциональные процентные позиции, опциональные double positions и color hints вдоль diamond-радиуса.

Внутри GradientDiamond переиспользует radial config model. Главное отличие не в публичном синтаксисе, а в расчете расстояния, который используют рендереры.

ts
type GradientDiamondConfig = GradientRadialConfig

type GradientDiamondConfigResolved = {
  shape: 'circle' | 'ellipse'
  size:
    | {
        kind: 'extent'
        value: 'closest-side' | 'closest-corner' | 'farthest-side' | 'farthest-corner'
      }
    | {
        kind: 'explicit'
        x: GradientLengthPercentage
        y?: GradientLengthPercentage
      }
  position: GradientPosition
  interpolation: {
    colorSpace: GradientColorSpace
    hue?: GradientHueInterpolation
  }
  isRepeating?: boolean
}

Позиции stops - это нормализованные числа: 0 означает центр, а 1 означает вычисленную границу diamond. Repeating-рендереры могут сэмплировать дальше 1, когда видимому прямоугольнику нужны дополнительные diamond-полосы, чтобы закрыть углы.

ts
type GradientDiamondStop =
  | {
      type: 'color-stop'
      value: string
      position: number
    }
  | {
      type: 'color-hint'
      position: number
    }

Что делает gradiente

Для diamond-gradient gradiente берет на себя работу, которую нельзя переложить на нативный CSS:

  • Парсит diamond-строки в экземпляр GradientDiamond.
  • Хранит размер, позицию центра, интерполяцию, stops и состояние повтора.
  • Переиспользует radial config parsing без отдельной одноразовой модели.
  • Подставляет дефолтные значения из одного места в конструкторе.
  • Вычисляет отсутствующие позиции stops.
  • Сохраняет color hints как полноценные stop-данные.
  • Компактно сериализует double-position stops.
  • Сэмплирует diamond field для CSS и SVG targets.
  • Рисует ту же модель в Canvas 2D и Canvas WebGL.
  • Преобразует одну и ту же модель в CSS, Canvas 2D, Canvas WebGL и SVG.

Анатомия

Полный синтаксис состоит из одного опционального элемента конфигурации и обязательного stop-листа:

css
diamond-gradient(
  [shape] [size] [at position] [in color-space [hue-mode hue]],
  color-stop-or-hint,
  color-stop-or-hint,
  ...
)

Первый элемент до запятой считается конфигурацией только тогда, когда содержит diamond config tokens. Все после первой запятой относится к stop-листу.

css
diamond-gradient(closest-side at 30% 35% in oklch, red 0%, 35%, blue 100%)
Пример diamond-градиентаРазмер, позиция, интерполяция, color hint и stopsdiamond-gradient(closest-side at 30% 35% in oklch, red 0%, 35%, blue 100%)
Превью загрузится, когда блок приблизится к viewport.

В этом примере есть:

  • closest-side: diamond доходит до ближайшей стороны от своего центра.
  • at 30% 35%: центр смещен ближе к верхней левой области.
  • in oklch: цвета интерполируются в OKLCH.
  • red 0%: первый color stop расположен в центре.
  • 35%: color hint, который двигает середину перехода от red к blue.
  • blue 100%: последний color stop расположен на вычисленной границе diamond.

Дефолты

Если diamond config не указан, gradiente использует те же дефолты config, что и радиальное семейство:

css
diamond-gradient(red, blue)
Пример diamond-градиентаDiamond-градиент по умолчаниюdiamond-gradient(red, blue)
Превью загрузится, когда блок приблизится к viewport.

Дефолты класса:

txt
shape: "ellipse"
size.kind: "extent"
size.value: "farthest-corner"
position: center center
interpolation.colorSpace: "srgb"
isRepeating: false

Дефолтные значения не выводятся в toString(). Поэтому diamond-gradient(ellipse farthest-corner at center in srgb, red, blue) может сериализоваться в компактный diamond-gradient(red, blue).

Геометрия diamond

Diamond-рендерер использует Manhattan-like поле расстояния:

txt
t = abs(x - center.x) / radius.x + abs(y - center.y) / radius.y

Цвет сэмплируется в точке t. Когда t равно 0, пиксель находится в центре. Когда t равно 1, пиксель лежит на вычисленной diamond-границе. Значения выше 1 находятся за этой границей и в основном важны для repeating gradients или заливки внешней области.

circle сохраняет одинаковые радиусы по x и y, поэтому у diamond симметричные оси.

css
diamond-gradient(circle, red, blue)
Пример diamond-градиентаDiamond-метрика с равными радиусамиdiamond-gradient(circle, red, blue)
Превью загрузится, когда блок приблизится к viewport.

ellipse позволяет использовать разные радиусы по x и y. Это дефолт, потому что он лучше адаптируется к прямоугольным областям.

css
diamond-gradient(ellipse 35% 70%, cyan, blue 60%, black)
Пример diamond-градиентаЯвно растянутый diamonddiamond-gradient(35% 70%, cyan 0%, blue 60%, black 100%)
Превью загрузится, когда блок приблизится к viewport.

Слова circle и ellipse унаследованы из radial-синтаксиса, но для diamond-градиента они описывают радиусы, которые использует diamond distance field, а не круглую визуальную форму.

Размер

Размер определяет вычисленные x/y радиусы, которые использует diamond field. Он может быть keyword-based или явным.

Extent keywords:

`closest-side`Diamond доходит до ближайшей стороны от центра.
`closest-corner`Diamond доходит до ближайшего угла от центра.
`farthest-side`Diamond доходит до самой дальней стороны от центра.
`farthest-corner`Diamond доходит до самого дальнего угла от центра. Это дефолт.

closest-side полезен для локальных подсветок, которые должны быстро заканчиваться.

css
diamond-gradient(closest-side, red, blue)
Пример diamond-градиентаРазмер closest-sidediamond-gradient(closest-side, red, blue)
Превью загрузится, когда блок приблизится к viewport.

closest-corner зависит и от центра, и от прямоугольной области отрисовки.

css
diamond-gradient(closest-corner at 25% 75%, #ff74f6, #405de6)
Пример diamond-градиентаРазмер closest-cornerdiamond-gradient(closest-corner at 25% 75%, #ff74f6, #405de6)
Превью загрузится, когда блок приблизится к viewport.

farthest-side создает более широкие поля, но не заставляет diamond доходить до самого дальнего угла.

css
diamond-gradient(farthest-side at left center, #ff74f6, #405de6)
Пример diamond-градиентаРазмер farthest-sidediamond-gradient(farthest-side at left center, #ff74f6, #405de6)
Превью загрузится, когда блок приблизится к viewport.

Явные размеры используют конкретные радиусы. Для circle нужен один length; для ellipse можно использовать два length или percentage значения. Для явного diamond ellipse первое значение - это радиус по x, второе - радиус по y:

css
diamond-gradient(40% 80% at 35% 65% in oklab, red 0%, yellow 50%, blue 100%)
Пример diamond-градиентаЯвные x/y радиусыdiamond-gradient(40% 80% at 35% 65% in oklab, red, yellow, blue)
Превью загрузится, когда блок приблизится к viewport.

Позиция

Позиция двигает diamond-центр. Она всегда указывается после at.

Keyword-позиции используют x/y keywords:

css
diamond-gradient(at top left, red, blue)
Пример diamond-градиентаKeyword-позицияdiamond-gradient(at left top, red, blue)
Превью загрузится, когда блок приблизится к viewport.

gradiente нормализует keyword-позиции в порядок x/y. Например, at top left сериализуется как at left top.

Value-позиции используют два length-percentage значения:

css
diamond-gradient(at 25% 75%, red, blue)
Пример diamond-градиентаПроцентная позицияdiamond-gradient(at 25% 75%, red, blue)
Превью загрузится, когда блок приблизится к viewport.

Текущий parser держит позиции строгими: keyword-позиции состоят только из keywords, а value-позиции требуют два length-percentage токена. Смешанные CSS-формы вроде left 20px top 10px пока не входят в эту модель.

Stop-лист

Stop-лист определяет, какие цвета появляются, пока diamond раскрывается от центра. На практике diamond-градиенту обычно нужны минимум два color stops.

Если у color stop нет явной позиции, gradiente вычисляет ее по соседним stops. Первый неразрешенный color stop становится 0%, последний становится 100%, а неразрешенные stops между известными позициями распределяются равномерно.

css
diamond-gradient(red 0%, yellow 40%, blue 100%)
Пример diamond-градиентаПозиционированные color stopsdiamond-gradient(red 0%, yellow 40%, blue 100%)
Превью загрузится, когда блок приблизится к viewport.

Color hints - это bare percentages между двумя color stops. Они не создают новый color stop, а двигают воспринимаемую середину сегмента интерполяции.

css
diamond-gradient(red 0%, 35%, blue 100%)
Пример diamond-градиентаColor hintdiamond-gradient(red 0%, 35%, blue 100%)
Превью загрузится, когда блок приблизится к viewport.

Double-position stops создают жесткие diamond-полосы. Цвет, записанный с двумя позициями, хранится как два соседних color stops с одним и тем же цветом, а потом по возможности сериализуется обратно в компактную форму.

css
diamond-gradient(red 0% 35%, blue 35% 100%)
Пример diamond-градиентаЖесткие diamond-полосыdiamond-gradient(red 0% 35%, blue 35% 100%)
Превью загрузится, когда блок приблизится к viewport.

Интерполяция

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

Дефолтное пространство интерполяции - srgb.

css
diamond-gradient(in srgb, red, blue)
Пример diamond-градиентаsRGB-интерполяцияdiamond-gradient(red, blue)
Превью загрузится, когда блок приблизится к viewport.

Перцепционные пространства вроде oklab часто дают более плавные переходы.

css
diamond-gradient(at 25% 75% in oklab, red, blue)
Пример diamond-градиентаOKLab-интерполяцияdiamond-gradient(at 25% 75% in oklab, red, blue)
Превью загрузится, когда блок приблизится к viewport.

Полярные цветовые пространства могут использовать режимы hue-интерполяции. gradiente поддерживает shorter, longer, increasing и decreasing.

css
diamond-gradient(in oklch longer hue, hsl(325, 64%, 54%), hsl(208, 94%, 47%))
Пример diamond-градиентаOKLCH-интерполяция longer huediamond-gradient(in oklch longer hue, hsl(325, 64%, 54%), hsl(208, 94%, 47%))
Превью загрузится, когда блок приблизится к viewport.

Поддерживаемые color spaces:

txt
oklab
lch
oklch
hsl
hwb
lab
srgb
srgb-linear
xyz
display-p3
a98-rgb
prophoto-rgb
rec2020

Повторяющиеся diamond-градиенты

repeating-diamond-gradient(...) использует тот же внутренний вид градиента, что и diamond-gradient(...). Префикс выставляет isRepeating: true в config, а type экземпляра остается diamond-gradient.

css
repeating-diamond-gradient(at center, red 0%, blue 20%)
Пример diamond-градиентаПовторяющийся diamond-градиентrepeating-diamond-gradient(red 0%, blue 20%)
Превью загрузится, когда блок приблизится к viewport.

Повторяющиеся diamond-градиенты полезны для жестких UI-колец, scan-эффектов, генерируемых pattern-систем, isometric grids, warning fields и абстрактных фонов.

Программное создание

Большинству пользователей стоит начинать с parse(), потому что он принимает ту же форму ввода, которую использует DSL. Когда градиент нужно собрать напрямую, используйте GradientDiamond.

Конструктор принимает два параметра:

txt
new GradientDiamond(stops, config?)

stops обязателен. config опционален, а пропущенные значения берутся из дефолтов класса.

ts
import { GradientDiamond } from 'gradiente'

const gradient = new GradientDiamond(
  [
    {
      type: 'color-stop',
      value: '#ff74f6',
      position: 0,
    },
    {
      type: 'color-stop',
      value: '#405de6',
      position: 1,
    },
  ],
  {
    size: {
      kind: 'extent',
      value: 'closest-side',
    },
    position: {
      kind: 'values',
      x: {
        kind: 'percent',
        value: 35,
      },
      y: {
        kind: 'percent',
        value: 45,
      },
    },
    interpolation: {
      colorSpace: 'oklch',
    },
  },
)
Пример diamond-градиентаЭквивалентный вывод конструктораdiamond-gradient(closest-side at 35% 45% in oklch, #ff74f6, #405de6)
Превью загрузится, когда блок приблизится к viewport.

Трансформация diamond-градиента

Каждый renderer target получает одну и ту же исходную модель. В этом главный смысл Core API: один раз распарсить, много раз трансформировать.

ts
import { parse, transformTo } from 'gradiente'

const gradient = parse(
  'diamond-gradient(40% 80% at 35% 65% in oklch longer hue, #ff74f6, #405de6)'
)

const css = transformTo('css', gradient)
const canvas2d = transformTo('canvas-2d', gradient)
const webgl = transformTo('canvas-webgl', gradient)
const svg = transformTo('svg', gradient)
Пример diamond-градиентаВход для renderer transformerdiamond-gradient(40% 80% at 35% 65% in oklch longer hue, #ff74f6, #405de6)
Превью загрузится, когда блок приблизится к viewport.

У outputs трансформеров разные формы:

`css`Строка CSS background. Для diamond-градиентов это сгенерированный SVG data URL, потому что в CSS нет нативной функции `diamond-gradient()`.
`canvas-2d`Paint-объект с `draw(ctx, width, height)`.
`canvas-webgl`Paint-объект с `draw(canvas, width, height)`.
`svg`SVG pattern payload с `defs`, `url` и сериализованными SVG-данными.

Нормализация

Используйте format() перед сохранением пользовательского ввода. Он парсит строку во внутреннюю модель и сериализует ее обратно в каноническую строку gradiente.

ts
import { format } from 'gradiente'

const input = 'diamond-gradient(closest-side at 35% 45% in oklch, #ff74f6 0%, 42%, #405de6 100%)'
const normalized = format(input)
Пример diamond-градиентаФорматированный пользовательский вводdiamond-gradient(closest-side at 35% 45% in oklch, #ff74f6 0%, 42%, #405de6 100%)
Превью загрузится, когда блок приблизится к viewport.

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

Практический чеклист

Используйте этот порядок при создании или валидации diamond-градиента:

  1. Решите, достаточно ли дефолтной ellipse-метрики или circle должен принудительно сделать x/y радиусы одинаковыми.
  2. Выберите размер: extent keyword для адаптивного поведения или явные радиусы для контролируемой геометрии.
  3. Выберите позицию через at, если diamond-центр должен уйти из дефолтного центра.
  4. Выберите интерполяцию: srgb для простой совместимости, oklab или oklch для более плавных переходов.
  5. Добавьте минимум два color stops, чтобы получить полезный визуальный результат.
  6. Добавьте явные позиции stops, если ширина полос должна переживать редактирование.
  7. Используйте color hints, когда нужно сдвинуть середину перехода.
  8. Используйте double-position stops, когда нужны жесткие diamond-полосы.
  9. Используйте format() перед сохранением пользовательского ввода.
  10. Используйте transformTo() для renderer output вместо попыток вручную конвертировать строку.