Skip to content

Радиальные градиенты

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

В gradiente радиальный градиент - это типизированная модель с формой, размером, позицией, настройками интерполяции, stops, опциональными color hints и флагом повтора. Одну и ту же модель можно преобразовать в CSS, Canvas 2D, Canvas WebGL, SVG или в кастомный target трансформера.

css
radial-gradient(circle at 35% 35% in oklch, #ff74f6 0%, #fb7655 45%, #405de6 100%)
Пример радиального градиентаСмещенное OKLCH-свечениеradial-gradient(circle at 35% 35% in oklch, #ff74f6 0%, #fb7655 45%, #405de6 100%)
Превью загрузится, когда блок приблизится к viewport.

Каждый preview-блок на этой странице отрисовывает один и тот же исходный градиент сразу в четырех targets: CSS, Canvas 2D, Canvas WebGL и SVG. Колонка WebGL - это снимок, созданный через transformTo('canvas-webgl', gradient), чтобы страница не держала слишком много активных WebGL-контекстов одновременно. Превью грузятся лениво, когда пример приближается к области просмотра.

Интеграция gradiente

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

Одна и та же модель gradiente может быть подключена в React, Vanilla JS, Vue или Svelte. Каждый пример парсит исходную строку, преобразует ее через transformTo('css') и применяет результат как настоящий background image.

ReactRadialGradientPreview.tsx

Из чего состоит радиальный градиент

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

Имя функции`radial-gradient(...)` или `repeating-radial-gradient(...)`. Публичный тип экземпляра остается `radial-gradient`; повтор хранится в config.
Форма`circle` или `ellipse`. Значение по умолчанию - `ellipse`.
Размер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 вдоль радиуса.

Модель, которую хранит gradiente, не привязана к конкретному рендереру:

ts
type GradientRadialConfig = {
  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 означает вычисленный внешний радиус. Используется та же общая stop-модель:

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

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

Что делает gradiente

Для radial-gradient gradiente берет на себя работу, которая обычно распределяется между парсерами, UI-кодом, сериализаторами и рендерерами:

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

Анатомия

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

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

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

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

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

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

Дефолты

Если радиальная конфигурация не указана, gradiente использует CSS-like дефолт:

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

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

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

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

Форма

Форма управляет полем расстояния, которое использует рендерер.

circle сохраняет одинаковые радиусы по x и y. Это удобно для свечений, spotlight-эффектов, focus rings, круглых масок, кнопок, бейджей и центрированных эффектов.

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

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

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

Когда форма не указана, gradiente хранит ellipse. Когда форма явно равна circle, сериализатор сохраняет ее, потому что она меняет геометрию.

Размер

Размер определяет вычисленный радиус или радиусы. Он может быть keyword-based или явным.

Extent keywords:

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

closest-side дает компактный результат и часто полезен для контролируемых локальных подсветок.

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

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

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

farthest-side может создавать широкие поля, которые при этом останавливаются раньше самого дальнего угла.

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

Явные размеры используют конкретные радиусы. Для круга нужен один length; для эллипса можно использовать два length или percentage значения.

css
radial-gradient(circle 70px at center, red, blue)
Пример радиального градиентаЯвный радиус circleradial-gradient(circle 70px, red, blue)
Превью загрузится, когда блок приблизится к viewport.

Для явного эллипса первое значение - это радиус по x, второе - радиус по y:

css
radial-gradient(35% 70%, cyan 0%, blue 60%, black 100%)

Позиция

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

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

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

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

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

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

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

Stop-лист

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

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

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

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

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

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

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

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

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

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

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

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

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

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

css
radial-gradient(in oklch longer hue, hsl(325, 64%, 54%), hsl(208, 94%, 47%))
Пример радиального градиентаOKLCH-интерполяция longer hueradial-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

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

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

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

Повторяющиеся радиальные градиенты полезны для ripples, targets, колец, scan-эффектов, halftone-like поверхностей и генерируемых систем паттернов.

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

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

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

txt
new GradientRadial(stops, config?)

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

ts
import { GradientRadial } from 'gradiente'

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

Трансформация радиального градиента

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

ts
import { parse, transformTo } from 'gradiente'

const gradient = parse(
  'radial-gradient(ellipse 35% 70% at 35% 45% 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)
Пример радиального градиентаВход для renderer transformerradial-gradient(35% 70% at 35% 45% in oklch longer hue, #ff74f6, #405de6)
Превью загрузится, когда блок приблизится к viewport.

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

`css`Строка CSS background.
`canvas-2d`Paint-объект с `draw(ctx, width, height)`.
`canvas-webgl`Paint-объект с `draw(canvas, width, height)`.
`svg`SVG paint server payload с `defs`, `url` и сериализованными SVG-данными.

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

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

ts
import { format } from 'gradiente'

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

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

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

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

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