css-magic-gradient 1.2.0 — гармонии, палитры, WCAG по всей длине и canvas-экспорт

31.03.2026
css-magic-gradient 1.2.0 — гармонии, палитры, WCAG по всей длине и canvas-экспорт

Когда выходила версия 1.1.0, я написал: «это уже другая история». Оказалось, что история продолжается.

В 1.1.0 появились React-хуки, пресеты и базовые инструменты WCAG. Всё это работало, но оставалось ощущение, что возможности color-value-tools под капотом используются на треть. Там есть тетрадные и сплит-комплементарные гармонии. Есть tints, shades, tones с Oklab-интерполяцией. Есть createColorScale для многоточечных шкал. Библиотека их импортировала, но наружу не давала.

Версия 1.2.0 это исправляет.

Что нового

Расширенные генераторы гармоний

Старые генераторы — createComplementaryGradient, createTriadicGradient, createAnalogousGradient — стали другими внутри. Вместо createMixedLinearGradient с HSL-интерполяцией они теперь используют interpolateColors и createColorScale из color-value-tools, с явным параметром interpolationSpace.

ts Copy
import { createComplementaryGradient } from 'css-magic-gradient';

// Было: HSL-интерполяция, 5 шагов
// Стало: oklch по умолчанию, любое пространство на выбор
createComplementaryGradient('#3498db', { steps: 7, interpolationSpace: 'oklch' });
createComplementaryGradient('#3498db', { steps: 7, interpolationSpace: 'oklab' });

В oklch переходы через комплементарные цвета — это почти всегда ровная насыщенность без провала в серость. В oklab — чуть мягче. Разница видна особенно на переходах вроде синий → оранжевый.

У createTriadicGradient появился параметр smoothness — он управляет тем, сколько точек interpolateColors/createColorScale вставляет между якорями:

ts Copy
// smoothness: 3 — только сами три цвета гармонии
createTriadicGradient('#e74c3c', { smoothness: 3 });

// smoothness: 9 — 9 точек через createColorScale, плавный переход
createTriadicGradient('#e74c3c', { smoothness: 9, interpolationSpace: 'oklch' });

Две новые гармонии

Тетрадная — четыре цвета через 90° на цветовом колесе. Поддерживает линейный, радиальный и конический типы:

ts Copy
import { createTetradicGradient } from 'css-magic-gradient';

createTetradicGradient('#9b59b6');                           // линейный по умолчанию
createTetradicGradient('#9b59b6', { type: 'conic', steps: 24 });   // конический
createTetradicGradient('#9b59b6', { type: 'radial', interpolationSpace: 'oklab' });

Сплит-комплементарная — базовый цвет плюс два цвета на 150° и 210°. Визуально это что-то среднее между комплементарным и аналогичным: достаточно контрастно, но не так напряжённо, как полный комплемент.

ts Copy
import { createSplitComplementaryGradient } from 'css-magic-gradient';

createSplitComplementaryGradient('#3498db');
createSplitComplementaryGradient('#3498db', { steps: 7, interpolationSpace: 'oklch' });

Тинты, шейды и тоны

Три новых генератора, которых не хватало для типичных дизайн-задач. Все используют функции из color-value-tools с Oklab-интерполяцией — переходы перцептуально ровные.

ts Copy
import { createTintGradient, createShadeGradient, createToneGradient } from 'css-magic-gradient';

// База → белый (тинты через Oklab)
createTintGradient('#3498db', 7, { direction: 'to right' });

// База → чёрный
createShadeGradient('#e74c3c', 5);

// База → серый, можно указать свой оттенок серого
createToneGradient('#9b59b6', 7, { gray: '#707070' });

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


Новые режимы конического и радиального градиентов

У createConicGradient появились три новых опции.

harmonyType — конический градиент через цвета выбранной гармонии, с интерполяцией по всему кругу:

ts Copy
import { createConicGradient } from 'css-magic-gradient';

// Четыре тетрадных цвета, равномерно вокруг круга
createConicGradient('#e74c3c', { harmonyType: 'triadic', steps: 24 });
createConicGradient('#3498db', { harmonyType: 'tetradic', interpolationSpace: 'oklch' });

colorScale — передаёшь произвольный массив цветов, функция интерполирует их по кругу:

ts Copy
// Красный → зелёный → синий → обратно к красному
createConicGradient('#000', {
  colorScale: ['#ff0000', '#00ff00', '#0000ff'],
  steps: 36,
  interpolationSpace: 'oklch',
});

Для createRadialGradient тоже добавился harmonyType — цвета гармонии становятся стопами радиального градиента:

ts Copy
createRadialGradient('#3498db', {
  harmonyType: 'triadic',
  interpolationSpace: 'oklch',
  shape: 'circle',
});

createRadialGradientLayers — вложенные кольца

Утилита, которой раньше не было. Генерирует набор RadialGradientLayer с убывающими размерами и распределёнными по гармонии цветами. Результат — вложенный многослойный эффект, не требующий ручного подбора размеров.

ts Copy
import { createRadialGradientLayers, createRadialGradient } from 'css-magic-gradient';

const layers = createRadialGradientLayers('#3498db', {
  count: 4,
  harmonyType: 'triadic',
  minSizePercent: 20,
  maxSizePercent: 100,
});

// layers — готовый массив RadialGradientLayer[]
const gradient = createRadialGradient('#3498db', { layers });

Каждый слой получает цвет из createColorScale по гармонии, размер рассчитывается равномерно от maxSizePercent до minSizePercent. Можно передать в createRadialGradient как есть, или поправить руками перед этим.


Шесть новых пресетов

Предыдущие девять пресетов покрывали основные «настроения» — закат, океан, аврора. Добавились ещё шесть:

ts Copy
import {
  forestGradient,    // Светло-зелёный → глубокий зелёный леса
  goldenHourGradient, // Золото → розовый → тёплый оранжевый
  neonGradient,      // Электрический зелёный → малиновый → яркий голубой
  nordicGradient,    // Ледяной синий → серый → почти белый
  pastelGradient,    // Лаванда → нежно-розовый → бледная мята
  deepSpaceGradient, // Почти-чёрный синий → тёмно-фиолетовый → фиолетовый акцент
} from 'css-magic-gradient';

Всё как раньше — просто строки, готовые к использованию как background.


Переработанная доступность

Старые функции работали по принципу «проверим середину градиента». Это приводило к тому, что у градиента с тёмным началом и светлой серединой можно было получить wcagLevel: 'AAA' — при том, что 40% градиента текст не читается вообще.

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

gradientContrastRatio возвращает теперь минимальный коэффициент контраста по всему градиенту, не средний:

ts Copy
import { gradientContrastRatio } from 'css-magic-gradient';

// Два цвета — сигнатура прежняя, логика внутри изменилась
gradientContrastRatio('#ffffff', '#1a1a2e', '#e94560');

// Массив стопов — новая форма
gradientContrastRatio('#ffffff', ['#1a1a2e', '#c0357a', '#e94560']);

gradientWcagLevel теперь возвращает объект GradientWcagReport вместо просто строки:

ts Copy
import { gradientWcagLevel } from 'css-magic-gradient';

const report = gradientWcagLevel('#ffffff', '#1a1a2e', '#e94560');
// → {
//     level: 'AAA',
//     minContrast: 8.4,
//     problematicStops: []
//   }

// Градиент с провалом в середине:
const report2 = gradientWcagLevel('#ffffff', ['#ffffff', '#aaaaaa', '#3498db']);
// → {
//     level: 'fail',
//     minContrast: 1.07,
//     problematicStops: [0, 0.09, 0.18, 0.27, 0.36]
//   }

problematicStops — дробные позиции (0–1) где контраст ниже 4.5. Удобно, если хочешь подсветить проблемную зону в редакторе или подсказать пользователю, где поставить фоновую плашку под текст.

bestGradientTextColor теперь принимает массив и умеет возвращать подробный отчёт:

ts Copy
// Как раньше — два цвета, возвращает '#000000' или '#ffffff'
bestGradientTextColor('#1a1a2e', '#e94560');

// Новый режим — массив стопов
bestGradientTextColor(['#1a1a2e', '#c0357a', '#e94560']);

// Подробный результат
const detail = bestGradientTextColor(['#1a1a2e', '#e94560'], { detailed: true });
// → {
//     recommended: '#ffffff',
//     black: { contrast: 1.8, wcag: 'fail' },
//     white: { contrast: 9.3, wcag: 'AAA' },
//   }

У createAccessibleGradient появился adjustmentStrategy — раньше функция умела только двигать яркость. Теперь можно двигать насыщенность или оба параметра сразу:

ts Copy
createAccessibleGradient('#3498db', '#ffffff', {
  targetLevel: 'AAA',
  adjustmentStrategy: 'both', // 'lightness' | 'saturation' | 'both'
});

Работа с CSS-переменными

Добавились две небольшие утилиты, которые пригодятся при работе с design tokens.

ts Copy
import { extractGradientVariables, resolveGradientVariables } from 'css-magic-gradient';

const gradient = 'linear-gradient(var(--start, #ff0000), var(--end))';

// Извлечь имена всех кастомных свойств
extractGradientVariables(gradient);
// → ['--start', '--end']

// Подставить реальные значения
resolveGradientVariables(gradient, { '--end': '#0000ff' });
// → 'linear-gradient(#ff0000, #0000ff)'
// Если переменная есть в строке с fallback — используется fallback.
// Если нет ни переменной в словаре, ни fallback — var() сохраняется как есть.

Позволяет, например, рендерить градиент с реальными цветами на сервере, даже если в браузере он живёт через CSS-переменные.


Экспорт в canvas

Три функции для тех, кому градиент нужен не только как CSS-строка.

gradientToCanvasGradient создаёт нативный CanvasGradient из параметров:

ts Copy
import { gradientToCanvasGradient } from 'css-magic-gradient';

const gradient = gradientToCanvasGradient(
  {
    type: 'linear',
    stops: [
      { color: '#ff9a3c', offset: 0 },
      { color: '#c0357a', offset: 1 },
    ],
  },
  ctx,
);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

Поддерживаются все три типа: 'linear', 'radial', 'conic'. Координаты и радиусы опциональны — по умолчанию подхватывают размер канваса.

gradientToImageData и gradientToDataURL рендерят градиент в ImageData или PNG data URL. Полезно для Open Graph-превью или серверной генерации изображений через npm-пакет canvas:

ts Copy
// Для вставки в <img src> или CSS background
const url = gradientToDataURL(
  { type: 'linear', stops: [{ color: '#ff9a3c', offset: 0 }, { color: '#c0357a', offset: 1 }] },
  800, 400,
);
// → 'data:image/png;base64,…'

В браузере используется OffscreenCanvas или document.createElement('canvas'). В Node.js — нужен canvas из npm, или любая другая реализация, которая ставит document в globalThis. Если ничего нет — кидается читаемая ошибка с подсказкой, без загадочного Cannot read properties of undefined.


9 новых хуков для Vue и React

Все новые генераторы получили реактивные хуки — одинаковые имена в Vue (ComputedRef<string>) и React (string через useMemo).

ts Copy
// Vue
import {
  useTetradicGradient,
  useSplitComplementaryGradient,
  useTintGradient,
  useShadeGradient,
  useToneGradient,
  useAccessibleGradient,
  useComplementaryGradient,
  useTriadicGradient,
  useAnalogousGradient,
} from 'css-magic-gradient';

// React — то же самое из css-magic-gradient/react

Пример с useAccessibleGradient — хук сам подбирает контрастный градиент на лету:

tsx Copy
// React
const [bgColor, setBgColor] = useState('#3498db');
const gradient = useAccessibleGradient(bgColor, '#ffffff', { targetLevel: 'AAA' });
// При каждом изменении bgColor — градиент пересчитывается и уже гарантированно проходит AAA
vue Copy
<!-- Vue -->
<script setup>
const color = ref('#3498db');
const gradient = useAccessibleGradient(color, ref('#ffffff'), { targetLevel: 'AA' });
</script>

Все хуки SSR-safe — внутри нет обращений к window или document, только строковые вычисления.


Итог

1.2.0 — это в основном раскрытие того, что уже лежало в color-value-tools и просто ждало своего часа. Тетрадные гармонии, сплит-комплементарные, Oklab-тинты, многоточечная проверка WCAG, canvas-экспорт.

Из следующего в планах: unit-тесты (сейчас их нет, и это видно), документированный playground и поддержка hwb() и oklch() напрямую как базовых цветов.

GitHub: github.com/macrulezru/css-magic-gradient
npm: npmjs.com/package/css-magic-gradient

Читать далее

30.03.2026

color-value-tools 1.1.1: от конвертера форматов до полноценного инструментария для работы с цветом

color-value-tools вырос из простого конвертера цветовых форматов в полноценный инструментарий: CSS Color Level 4, перцептивная интерполяция, цветовые гармонии, симуляция дальтонизма, WCAG-доступность, генераторы и CLI — всё в одном пакете без зависимостей.

Метки
colortypescriptnpmwcagcss
28.03.2026

vue-i18n-kit — локализация для Vue 3 с ICU-плюрализацией, lazy loading и CLI

Написал собственный npm-пакет для локализации Vue 3, потому что устал каждый раз копировать один и тот же бойлерплейт из проекта в проект. ICU-плюрализация, lazy loading, метаданные локалей, форматирование дат и валют, Vite-плагин и CLI — всё из коробки.

Метки
vue3i18nlocalizationnpmopen-source