Design
COLOR PICKER & CONVERTER
Convert colors between HEX, RGB, HSL, HSV, and CMYK. Generate shades, tints, and complementary palettes.
Color Formats
HEX
#ff2200
RGB
rgb(255, 34, 0)
HSL
hsl(8, 100%, 50%)
HSV
hsv(8, 100%, 100%)
CMYK
cmyk(0%, 87%, 100%, 0%)
Tints & Shades
Color Harmony
Developer Reference
Core Algorithm & Standalone Script
Standalone, zero-dependency JavaScript implementation powering this tool. Free to inspect, copy, and build upon.
// ── Color math ───────────────────────────────────────────────
function hexToRgb(hex) {
hex = hex.replace(/^#/, '');
if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');
const n = parseInt(hex, 16);
return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };
}
function rgbToHex(r, g, b) {
return '#' + [r, g, b].map(v => v.toString(16).padStart(2, '0')).join('');
}
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) { h = s = 0; }
else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max) {
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
case g: h = ((b - r) / d + 2) / 6; break;
case b: h = ((r - g) / d + 4) / 6; break;
}
}
return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) };
}
function hslToRgb(h, s, l) {
s /= 100; l /= 100;
const k = n => (n + h / 30) % 12;
const a = s * Math.min(l, 1 - l);
const f = n => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
return { r: Math.round(f(0) * 255), g: Math.round(f(8) * 255), b: Math.round(f(4) * 255) };
}
function rgbToHsv(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min;
let h = 0, s = max === 0 ? 0 : d / max, v = max;
if (max !== min) {
switch(max) {
case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
case g: h = ((b - r) / d + 2) / 6; break;
case b: h = ((r - g) / d + 4) / 6; break;
}
}
return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100) };
}
function rgbToCmyk(r, g, b) {
r /= 255; g /= 255; b /= 255;
const k = 1 - Math.max(r, g, b);
if (k === 1) return { c: 0, m: 0, y: 0, k: 100 };
return {
c: Math.round(((1 - r - k) / (1 - k)) * 100),
m: Math.round(((1 - g - k) / (1 - k)) * 100),
y: Math.round(((1 - b - k) / (1 - k)) * 100),
k: Math.round(k * 100)
};
}
// CSS named colors lookup (subset)
const CSS_COLORS = {
'#000000':'black','#ffffff':'white','#ff0000':'red','#00ff00':'lime',
'#0000ff':'blue','#ffff00':'yellow','#00ffff':'cyan','#ff00ff':'magenta',
'#c0c0c0':'silver','#808080':'gray','#800000':'maroon','#808000':'olive',
'#008000':'green','#800080':'purple','#008080':'teal','#000080':'navy',
'#ffa500':'orange','#ff6347':'tomato','#ff69b4':'hotpink','#ffd700':'gold',
'#4169e1':'royalblue','#dc143c':'crimson','#00ced1':'darkturquoise',
'#ff8c00':'darkorange','#9932cc':'darkorchid','#8b0000':'darkred',
'#2f4f4f':'darkslategray','#696969':'dimgray','#b8860b':'darkgoldenrod',
'#006400':'darkgreen','#bdb76b':'darkkhaki','#8b008b':'darkmagenta',
'#556b2f':'darkolivegreen','#ff8c00':'darkorange','#9932cc':'darkorchid',
'#e9967a':'darksalmon','#8fbc8f':'darkseagreen','#483d8b':'darkslateblue',
'#1e90ff':'dodgerblue','#b22222':'firebrick','#fffaf0':'floralwhite',
'#228b22':'forestgreen','#dcdcdc':'gainsboro','#f8f8ff':'ghostwhite',
'#adff2f':'greenyellow','#ff69b4':'hotpink','#cd5c5c':'indianred',
'#4b0082':'indigo','#fffff0':'ivory','#f0e68c':'khaki','#e6e6fa':'lavender',
'#7cfc00':'lawngreen','#add8e6':'lightblue','#f08080':'lightcoral',
'#90ee90':'lightgreen','#ffb6c1':'lightpink','#20b2aa':'lightseagreen',
'#87ceeb':'lightskyblue','#778899':'lightslategray','#b0c4de':'lightsteelblue',
'#ffffe0':'lightyellow','#32cd32':'limegreen','#faf0e6':'linen',
'#66cdaa':'mediumaquamarine','#0000cd':'mediumblue','#ba55d3':'mediumorchid',
'#9370db':'mediumpurple','#3cb371':'mediumseagreen','#7b68ee':'mediumslateblue',
'#00fa9a':'mediumspringgreen','#48d1cc':'mediumturquoise','#c71585':'mediumvioletred',
'#191970':'midnightblue','#f5fffa':'mintcream','#ffe4e1':'mistyrose',
'#ffe4b5':'moccasin','#000080':'navy','#fdf5e6':'oldlace','#6b8e23':'olivedrab',
'#ff4500':'orangered','#da70d6':'orchid','#eee8aa':'palegoldenrod',
'#98fb98':'palegreen','#afeeee':'paleturquoise','#db7093':'palevioletred',
'#ffdab9':'peachpuff','#cd853f':'peru','#ffc0cb':'pink','#dda0dd':'plum',
'#b0e0e6':'powderblue','#bc8f8f':'rosybrown','#4169e1':'royalblue',
'#8b4513':'saddlebrown','#fa8072':'salmon','#f4a460':'sandybrown',
'#2e8b57':'seagreen','#fff5ee':'seashell','#a0522d':'sienna','#87ceeb':'skyblue',
'#6a5acd':'slateblue','#708090':'slategray','#fffafa':'snow',
'#00ff7f':'springgreen','#4682b4':'steelblue','#d2b48c':'tan',
'#d8bfd8':'thistle','#ff6347':'tomato','#40e0d0':'turquoise',
'#ee82ee':'violet','#f5deb3':'wheat','#9acd32':'yellowgreen'
};
// ── State ────────────────────────────────────────────────────
let currentRgb = hexToRgb('#ff2200');
function updateAll(hex) {
hex = hex.toLowerCase();
const rgb = hexToRgb(hex);
if (!rgb) return;
currentRgb = rgb;
// Swatch
document.getElementById('swatchBox').style.background = hex;
document.getElementById('colorPicker').value = hex;
document.getElementById('hexInput').value = hex;
document.getElementById('hexInput').classList.remove('invalid');
// CSS name
const cssName = CSS_COLORS[hex] || '';
document.getElementById('cssName').textContent = cssName;
// Conversions
const { r, g, b } = rgb;
const hsl = rgbToHsl(r, g, b);
const hsv = rgbToHsv(r, g, b);
const cmyk = rgbToCmyk(r, g, b);
document.getElementById('c-hex').textContent = hex;
document.getElementById('c-rgb').textContent = `rgb(${r}, ${g}, ${b})`;
document.getElementById('c-hsl').textContent = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
document.getElementById('c-hsv').textContent = `hsv(${hsv.h}, ${hsv.s}%, ${hsv.v}%)`;
document.getElementById('c-cmyk').textContent = `cmyk(${cmyk.c}%, ${cmyk.m}%, ${cmyk.y}%, ${cmyk.k}%)`;
if (cssName) {
document.getElementById('c-named').textContent = cssName;
document.getElementById('c-named-card').style.display = '';
} else {
document.getElementById('c-named-card').style.display = 'none';
}
updateShades(r, g, b);
updateHarmony(hsl.h, hsl.s, hsl.l);
}
function updateShades(r, g, b) {
const strip = document.getElementById('shadeStrip');
strip.innerHTML = '';
const hsl = rgbToHsl(r, g, b);
// 9 tints (lighter)
for (let i = 9; i >= 1; i--) {
const l = hsl.l + (100 - hsl.l) * (i / 10);
const rgb2 = hslToRgb(hsl.h, hsl.s, Math.min(100, Math.round(l)));
const hex2 = rgbToHex(rgb2.r, rgb2.g, rgb2.b);
addSwatch(strip, hex2, 'Tint ' + i, true);
}
// Original
const origHex = rgbToHex(r, g, b);
addSwatch(strip, origHex, 'Original', false, true);
// 9 shades (darker)
for (let i = 1; i <= 9; i++) {
const l = hsl.l * (1 - i / 10);
const rgb2 = hslToRgb(hsl.h, hsl.s, Math.round(l));
const hex2 = rgbToHex(rgb2.r, rgb2.g, rgb2.b);
addSwatch(strip, hex2, 'Shade ' + i, true);
}
}
function addSwatch(container, hex, label, clickable, active) {
const el = document.createElement('div');
el.className = 'shade-swatch';
el.style.background = hex;
el.title = hex;
if (active) el.style.borderColor = 'rgba(255,255,255,0.6)';
if (clickable) {
el.onclick = () => { copyHex(hex); updateAll(hex); };
}
container.appendChild(el);
}
function updateHarmony(h, s, l) {
const row = document.getElementById('harmonyRow');
row.innerHTML = '';
const harmonies = [
{ name: 'Complementary', angles: [h, (h + 180) % 360] },
{ name: 'Split-Complementary', angles: [h, (h + 150) % 360, (h + 210) % 360] },
{ name: 'Triadic', angles: [h, (h + 120) % 360, (h + 240) % 360] },
{ name: 'Analogous', angles: [h, (h + 30) % 360, (h - 30 + 360) % 360] },
];
harmonies.forEach(harm => {
const group = document.createElement('div');
group.className = 'harmony-group';
const label = document.createElement('div');
label.className = 'harmony-label';
label.textContent = harm.name;
group.appendChild(label);
const swatches = document.createElement('div');
swatches.className = 'harmony-swatches';
harm.angles.forEach(angle => {
const rgb2 = hslToRgb(angle, s, l);
const hex2 = rgbToHex(rgb2.r, rgb2.g, rgb2.b);
const wrap = document.createElement('div');
wrap.style.position = 'relative';
wrap.style.marginBottom = '20px';
const sw = document.createElement('div');
sw.className = 'harmony-swatch';
sw.style.background = hex2;
sw.title = hex2;
sw.onclick = () => { copyHex(hex2); updateAll(hex2); };
const hexLbl = document.createElement('div');
hexLbl.className = 'harmony-swatch-hex';
hexLbl.textContent = hex2;
wrap.appendChild(sw);
wrap.appendChild(hexLbl);
swatches.appendChild(wrap);
});
group.appendChild(swatches);
row.appendChild(group);
});
}
function copyHex(hex) {
navigator.clipboard.writeText(hex).catch(() => {});
showToast('Copied ' + hex);
}
function showToast(msg) {
const t = document.getElementById('toast');
t.textContent = msg;
t.classList.add('show');
setTimeout(() => t.classList.remove('show'), 2000);
}
function onPickerChange(val) {
updateAll(val);
}
function onHexInput(val) {
const clean = val.trim();
if (/^#[0-9a-fA-F]{6}$/.test(clean)) {
document.getElementById('hexInput').classList.remove('invalid');
updateAll(clean.toLowerCase());
} else if (/^#[0-9a-fA-F]{3}$/.test(clean)) {
document.getElementById('hexInput').classList.remove('invalid');
updateAll(clean.toLowerCase());
} else {
document.getElementById('hexInput').classList.add('invalid');
}
}
function copyConv(id, btn) {
const text = document.getElementById(id).textContent;
navigator.clipboard.writeText(text).catch(() => {});
btn.textContent = 'copied!';
btn.classList.add('copied');
setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('copied'); }, 2000);
}
// Init
updateAll('#ff2200');