Diamond-градиенты
Diamond-градиент - это gradiente-specific вид градиента. С точки зрения пользователя он работает почти как радиальный градиент, но вместо круглого поля расстояния использует diamond distance field. Пиксели измеряются по тому, насколько далеко они ушли от центра по горизонтали и вертикали, поэтому контуры одинакового расстояния образуют ромбы.
Из-за этого diamond-gradient(...) хорошо подходит для faceted glows, UI-подсветок, isometric-looking поверхностей, жестких полос, генерируемых pattern-систем и эффектов, где обычный radial gradient выглядит слишком круглым.
diamond-gradient(farthest-corner at 48% 45% in oklch, #5851db 0%, #c13584 35%, #fcb045 70%, #405de6 100%)diamond-gradient(at 48% 45% in oklch, #5851db 0%, #c13584 35%, #fcb045 70%, #405de6 100%)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-контекстов одновременно.
Использование diamond-градиента во фреймворке
Diamond-градиенты не являются нативными CSS-функциями, поэтому transformTo('css') возвращает готовый для background SVG data URL. Одну и ту же распарсенную модель gradiente все равно можно подключить в React, Vanilla JS, Vue или Svelte.
Из чего состоит diamond-градиент
У модели diamond-градиента есть пять смысловых частей:
Внутри GradientDiamond переиспользует radial config model. Главное отличие не в публичном синтаксисе, а в расчете расстояния, который используют рендереры.
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-полосы, чтобы закрыть углы.
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-листа:
diamond-gradient(
[shape] [size] [at position] [in color-space [hue-mode hue]],
color-stop-or-hint,
color-stop-or-hint,
...
)Первый элемент до запятой считается конфигурацией только тогда, когда содержит diamond config tokens. Все после первой запятой относится к stop-листу.
diamond-gradient(closest-side at 30% 35% in oklch, red 0%, 35%, blue 100%)diamond-gradient(closest-side at 30% 35% in oklch, red 0%, 35%, blue 100%)В этом примере есть:
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, что и радиальное семейство:
diamond-gradient(red, blue)diamond-gradient(red, blue)Дефолты класса:
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 поле расстояния:
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 симметричные оси.
diamond-gradient(circle, red, blue)diamond-gradient(circle, red, blue)ellipse позволяет использовать разные радиусы по x и y. Это дефолт, потому что он лучше адаптируется к прямоугольным областям.
diamond-gradient(ellipse 35% 70%, cyan, blue 60%, black)diamond-gradient(35% 70%, cyan 0%, blue 60%, black 100%)Слова circle и ellipse унаследованы из radial-синтаксиса, но для diamond-градиента они описывают радиусы, которые использует diamond distance field, а не круглую визуальную форму.
Размер
Размер определяет вычисленные x/y радиусы, которые использует diamond field. Он может быть keyword-based или явным.
Extent keywords:
closest-side полезен для локальных подсветок, которые должны быстро заканчиваться.
diamond-gradient(closest-side, red, blue)diamond-gradient(closest-side, red, blue)closest-corner зависит и от центра, и от прямоугольной области отрисовки.
diamond-gradient(closest-corner at 25% 75%, #ff74f6, #405de6)diamond-gradient(closest-corner at 25% 75%, #ff74f6, #405de6)farthest-side создает более широкие поля, но не заставляет diamond доходить до самого дальнего угла.
diamond-gradient(farthest-side at left center, #ff74f6, #405de6)diamond-gradient(farthest-side at left center, #ff74f6, #405de6)Явные размеры используют конкретные радиусы. Для circle нужен один length; для ellipse можно использовать два length или percentage значения. Для явного diamond ellipse первое значение - это радиус по x, второе - радиус по y:
diamond-gradient(40% 80% at 35% 65% in oklab, red 0%, yellow 50%, blue 100%)diamond-gradient(40% 80% at 35% 65% in oklab, red, yellow, blue)Позиция
Позиция двигает diamond-центр. Она всегда указывается после at.
Keyword-позиции используют x/y keywords:
diamond-gradient(at top left, red, blue)diamond-gradient(at left top, red, blue)gradiente нормализует keyword-позиции в порядок x/y. Например, at top left сериализуется как at left top.
Value-позиции используют два length-percentage значения:
diamond-gradient(at 25% 75%, red, blue)diamond-gradient(at 25% 75%, red, blue)Текущий 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 между известными позициями распределяются равномерно.
diamond-gradient(red 0%, yellow 40%, blue 100%)diamond-gradient(red 0%, yellow 40%, blue 100%)Color hints - это bare percentages между двумя color stops. Они не создают новый color stop, а двигают воспринимаемую середину сегмента интерполяции.
diamond-gradient(red 0%, 35%, blue 100%)diamond-gradient(red 0%, 35%, blue 100%)Double-position stops создают жесткие diamond-полосы. Цвет, записанный с двумя позициями, хранится как два соседних color stops с одним и тем же цветом, а потом по возможности сериализуется обратно в компактную форму.
diamond-gradient(red 0% 35%, blue 35% 100%)diamond-gradient(red 0% 35%, blue 35% 100%)Интерполяция
Интерполяция управляет путем между цветами. Для diamond-градиентов она особенно важна, потому что острый центр и диагональные полосы делают грязные середины или резкие изменения hue очень заметными.
Дефолтное пространство интерполяции - srgb.
diamond-gradient(in srgb, red, blue)diamond-gradient(red, blue)Перцепционные пространства вроде oklab часто дают более плавные переходы.
diamond-gradient(at 25% 75% in oklab, red, blue)diamond-gradient(at 25% 75% in oklab, red, blue)Полярные цветовые пространства могут использовать режимы hue-интерполяции. gradiente поддерживает shorter, longer, increasing и decreasing.
diamond-gradient(in oklch longer hue, hsl(325, 64%, 54%), hsl(208, 94%, 47%))diamond-gradient(in oklch longer hue, hsl(325, 64%, 54%), hsl(208, 94%, 47%))Поддерживаемые color spaces:
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.
repeating-diamond-gradient(at center, red 0%, blue 20%)repeating-diamond-gradient(red 0%, blue 20%)Повторяющиеся diamond-градиенты полезны для жестких UI-колец, scan-эффектов, генерируемых pattern-систем, isometric grids, warning fields и абстрактных фонов.
Программное создание
Большинству пользователей стоит начинать с parse(), потому что он принимает ту же форму ввода, которую использует DSL. Когда градиент нужно собрать напрямую, используйте GradientDiamond.
Конструктор принимает два параметра:
new GradientDiamond(stops, config?)stops обязателен. config опционален, а пропущенные значения берутся из дефолтов класса.
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-gradient(closest-side at 35% 45% in oklch, #ff74f6, #405de6)Трансформация diamond-градиента
Каждый renderer target получает одну и ту же исходную модель. В этом главный смысл Core API: один раз распарсить, много раз трансформировать.
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-gradient(40% 80% at 35% 65% in oklch longer hue, #ff74f6, #405de6)У outputs трансформеров разные формы:
Нормализация
Используйте format() перед сохранением пользовательского ввода. Он парсит строку во внутреннюю модель и сериализует ее обратно в каноническую строку gradiente.
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-gradient(closest-side at 35% 45% in oklch, #ff74f6 0%, 42%, #405de6 100%)Нормализация полезна, когда пользователи вводят градиенты вручную, когда сохраняется состояние редактора или когда сгенерированным градиентам нужен стабильный output для тестов и snapshots.
Практический чеклист
Используйте этот порядок при создании или валидации diamond-градиента:
- Решите, достаточно ли дефолтной
ellipse-метрики илиcircleдолжен принудительно сделать x/y радиусы одинаковыми. - Выберите размер: extent keyword для адаптивного поведения или явные радиусы для контролируемой геометрии.
- Выберите позицию через
at, если diamond-центр должен уйти из дефолтного центра. - Выберите интерполяцию:
srgbдля простой совместимости,oklabилиoklchдля более плавных переходов. - Добавьте минимум два color stops, чтобы получить полезный визуальный результат.
- Добавьте явные позиции stops, если ширина полос должна переживать редактирование.
- Используйте color hints, когда нужно сдвинуть середину перехода.
- Используйте double-position stops, когда нужны жесткие diamond-полосы.
- Используйте
format()перед сохранением пользовательского ввода. - Используйте
transformTo()для renderer output вместо попыток вручную конвертировать строку.