Fast color parsing and manipulation library with comprehensive conversion and accessibility features
—
Additional utility functions for color comparison, mixing, random color generation, and working with ratio-based values. These static methods provide essential tools for advanced color operations and programmatic color generation.
Compares two colors to determine if they represent the same color value.
/**
* Compares two colors for equality
* @param color1 - First color (any valid tinycolor input)
* @param color2 - Second color (any valid tinycolor input)
* @returns boolean indicating if colors are equal
*/
tinycolor.equals(color1: any, color2: any): boolean;Usage Examples:
import tinycolor from "tinycolor2";
// Compare different representations of the same color
const red1 = "#ff0000";
const red2 = "rgb(255, 0, 0)";
const red3 = "red";
const red4 = {r: 255, g: 0, b: 0};
console.log(tinycolor.equals(red1, red2)); // true
console.log(tinycolor.equals(red2, red3)); // true
console.log(tinycolor.equals(red3, red4)); // true
// Compare different colors
console.log(tinycolor.equals("red", "blue")); // false
// Compare with slight variations
const almostRed = "#ff0001";
console.log(tinycolor.equals("red", almostRed)); // false
// Useful for color validation in arrays
const palette = ["#ff0000", "#00ff00", "#0000ff"];
const targetColor = "rgb(255, 0, 0)";
const exists = palette.some(color => tinycolor.equals(color, targetColor));
console.log("Color exists in palette:", exists); // true
// Remove duplicates from color array
function removeDuplicateColors(colors) {
const unique = [];
colors.forEach(color => {
const isDuplicate = unique.some(existing => tinycolor.equals(existing, color));
if (!isDuplicate) {
unique.push(color);
}
});
return unique;
}
const colorsWithDupes = ["red", "#ff0000", "rgb(255,0,0)", "blue", "#0000ff"];
const uniqueColors = removeDuplicateColors(colorsWithDupes);Blends two colors together by a specified percentage.
/**
* Mixes two colors together
* @param color1 - First color (any valid tinycolor input)
* @param color2 - Second color (any valid tinycolor input)
* @param amount - Mixing percentage (0-100), where 0 returns color1, 100 returns color2
* @returns new tinycolor instance representing the mixed color
*/
tinycolor.mix(color1: any, color2: any, amount?: number): tinycolor;Usage Examples:
// Basic color mixing
const red = "red";
const blue = "blue";
const purple25 = tinycolor.mix(red, blue, 25); // 25% blue, 75% red
const purple50 = tinycolor.mix(red, blue, 50); // Equal mix
const purple75 = tinycolor.mix(red, blue, 75); // 75% blue, 25% red
console.log("25% blue:", purple25.toHexString()); // More red
console.log("50% mix:", purple50.toHexString()); // Equal purple
console.log("75% blue:", purple75.toHexString()); // More blue
// Create gradients
function createGradient(startColor, endColor, steps = 10) {
const gradient = [];
for (let i = 0; i <= steps; i++) {
const amount = (i / steps) * 100;
const mixed = tinycolor.mix(startColor, endColor, amount);
gradient.push(mixed.toHexString());
}
return gradient;
}
const redToBlue = createGradient("#ff0000", "#0000ff", 5);
console.log("Gradient:", redToBlue);
// Mix with transparency
const opaqueRed = "rgba(255, 0, 0, 1)";
const transparentBlue = "rgba(0, 0, 255, 0.3)";
const mixed = tinycolor.mix(opaqueRed, transparentBlue, 50);
console.log("Mixed with alpha:", mixed.toRgbString());
// Color blending for design
function blendColors(baseColor, overlayColor, opacity) {
return tinycolor.mix(baseColor, overlayColor, opacity * 100);
}
const background = "#ffffff";
const overlay = "#ff0000";
const blended = blendColors(background, overlay, 0.3);Creates a completely random color.
/**
* Generates a random color
* @returns new tinycolor instance with random RGB values
*/
tinycolor.random(): tinycolor;Usage Examples:
// Generate single random color
const randomColor = tinycolor.random();
console.log("Random color:", randomColor.toHexString());
// Generate multiple random colors
const randomPalette = Array.from({length: 5}, () => tinycolor.random());
console.log("Random palette:", randomPalette.map(c => c.toHexString()));
// Generate random colors with constraints
function randomColorWithConstraints(options = {}) {
const {
minBrightness = 0,
maxBrightness = 255,
minSaturation = 0,
maxSaturation = 1,
hueRange = null
} = options;
let color;
let attempts = 0;
const maxAttempts = 100;
do {
color = tinycolor.random();
const hsl = color.toHsl();
const brightness = color.getBrightness();
const brightnessOk = brightness >= minBrightness && brightness <= maxBrightness;
const saturationOk = hsl.s >= minSaturation && hsl.s <= maxSaturation;
const hueOk = !hueRange || (hsl.h >= hueRange[0] && hsl.h <= hueRange[1]);
if (brightnessOk && saturationOk && hueOk) {
return color;
}
attempts++;
} while (attempts < maxAttempts);
return color; // Return last attempt if no perfect match
}
// Generate bright colors only
const brightColors = Array.from({length: 3}, () =>
randomColorWithConstraints({ minBrightness: 150 })
);
// Generate colors in blue range
const blueishColors = Array.from({length: 3}, () =>
randomColorWithConstraints({ hueRange: [200, 260] })
);
// Generate pastel colors
const pastelColors = Array.from({length: 3}, () =>
randomColorWithConstraints({
minBrightness: 180,
maxSaturation: 0.6
})
);Creates colors using ratio values (0-1) instead of standard ranges.
/**
* Creates a tinycolor from ratio values (0-1 range instead of 0-255 for RGB)
* @param color - Color object with ratio values
* @param opts - Optional configuration object
* @returns new tinycolor instance
*/
tinycolor.fromRatio(color: {r?: number, g?: number, b?: number, h?: number, s?: number, l?: number, v?: number, a?: number}, opts?: object): tinycolor;Usage Examples:
// RGB ratios (0-1 instead of 0-255)
const redRatio = tinycolor.fromRatio({r: 1, g: 0, b: 0});
const grayRatio = tinycolor.fromRatio({r: 0.5, g: 0.5, b: 0.5});
const customRatio = tinycolor.fromRatio({r: 0.8, g: 0.2, b: 0.6});
console.log("Red from ratio:", redRatio.toHexString()); // "#ff0000"
console.log("Gray from ratio:", grayRatio.toHexString()); // "#808080"
console.log("Custom from ratio:", customRatio.toHexString());
// HSL ratios
const blueHslRatio = tinycolor.fromRatio({h: 0.67, s: 1, l: 0.5}); // Blue
const orangeHslRatio = tinycolor.fromRatio({h: 0.083, s: 1, l: 0.5}); // Orange
// HSV ratios
const yellowHsvRatio = tinycolor.fromRatio({h: 0.167, s: 1, v: 1}); // Yellow
// With alpha ratios
const transparentRedRatio = tinycolor.fromRatio({r: 1, g: 0, b: 0, a: 0.5});
console.log("Transparent red:", transparentRedRatio.toRgbString());
// Useful for mathematical color generation
function generateColorFromData(value, min, max) {
// Normalize value to 0-1 range
const ratio = (value - min) / (max - min);
// Create color based on ratio (red to green gradient)
return tinycolor.fromRatio({
r: 1 - ratio, // Red decreases as value increases
g: ratio, // Green increases as value increases
b: 0,
a: 1
});
}
// Data visualization colors
const dataPoints = [10, 25, 50, 75, 90];
const minValue = Math.min(...dataPoints);
const maxValue = Math.max(...dataPoints);
const colors = dataPoints.map(value =>
generateColorFromData(value, minValue, maxValue)
);
console.log("Data colors:", colors.map(c => c.toHexString()));// Convert between different ratio representations
function convertRatios(color, fromSpace, toSpace) {
const tc = tinycolor(color);
switch (toSpace) {
case 'rgb-ratio':
const rgb = tc.toRgb();
return {r: rgb.r/255, g: rgb.g/255, b: rgb.b/255, a: rgb.a};
case 'hsl-ratio':
const hsl = tc.toHsl();
return {h: hsl.h/360, s: hsl.s, l: hsl.l, a: hsl.a};
case 'hsv-ratio':
const hsv = tc.toHsv();
return {h: hsv.h/360, s: hsv.s, v: hsv.v, a: hsv.a};
default:
return tc.toRgb();
}
}
// Interpolation utilities
function interpolateColors(color1, color2, steps, space = 'rgb') {
const colors = [];
for (let i = 0; i <= steps; i++) {
const ratio = i / steps;
switch (space) {
case 'hsl':
const hsl1 = tinycolor(color1).toHsl();
const hsl2 = tinycolor(color2).toHsl();
colors.push(tinycolor.fromRatio({
h: (hsl1.h + (hsl2.h - hsl1.h) * ratio) / 360,
s: hsl1.s + (hsl2.s - hsl1.s) * ratio,
l: hsl1.l + (hsl2.l - hsl1.l) * ratio,
a: hsl1.a + (hsl2.a - hsl1.a) * ratio
}));
break;
default:
colors.push(tinycolor.mix(color1, color2, ratio * 100));
}
}
return colors;
}function validateAndCorrectColor(input, fallback = '#000000') {
const color = tinycolor(input);
if (!color.isValid()) {
console.warn(`Invalid color "${input}", using fallback "${fallback}"`);
return tinycolor(fallback);
}
return color;
}
function ensureContrast(backgroundColor, textColor, minRatio = 4.5) {
const bgColor = validateAndCorrectColor(backgroundColor);
let txtColor = validateAndCorrectColor(textColor);
const currentRatio = tinycolor.readability(bgColor, txtColor);
if (currentRatio >= minRatio) {
return txtColor;
}
// Try to adjust text color
const bgLuminance = bgColor.getLuminance();
const preferDark = bgLuminance > 0.5;
const options = preferDark
? ['#000000', '#333333', '#666666']
: ['#ffffff', '#cccccc', '#999999'];
return tinycolor.mostReadable(bgColor, options);
}// Weighted color mixing
function weightedMix(colors, weights) {
if (colors.length !== weights.length) {
throw new Error('Colors and weights arrays must have the same length');
}
const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
// Convert all colors to RGB ratios
const rgbColors = colors.map(color => {
const rgb = tinycolor(color).toRgb();
return {
r: rgb.r / 255,
g: rgb.g / 255,
b: rgb.b / 255,
a: rgb.a
};
});
// Calculate weighted average
const result = rgbColors.reduce((acc, color, index) => {
const weight = weights[index] / totalWeight;
return {
r: acc.r + color.r * weight,
g: acc.g + color.g * weight,
b: acc.b + color.b * weight,
a: acc.a + color.a * weight
};
}, {r: 0, g: 0, b: 0, a: 0});
return tinycolor.fromRatio(result);
}
// Usage
const mixed = weightedMix(
['red', 'blue', 'green'],
[0.5, 0.3, 0.2]
);
// Color distance calculation
function colorDistance(color1, color2) {
const rgb1 = tinycolor(color1).toRgb();
const rgb2 = tinycolor(color2).toRgb();
// Euclidean distance in RGB space
const dr = rgb1.r - rgb2.r;
const dg = rgb1.g - rgb2.g;
const db = rgb1.b - rgb2.b;
return Math.sqrt(dr * dr + dg * dg + db * db);
}
// Find closest color in palette
function findClosestColor(targetColor, palette) {
let closest = palette[0];
let minDistance = colorDistance(targetColor, closest);
palette.forEach(color => {
const distance = colorDistance(targetColor, color);
if (distance < minDistance) {
minDistance = distance;
closest = color;
}
});
return {
color: closest,
distance: minDistance
};
}Install with Tessl CLI
npx tessl i tessl/npm-tinycolor2