Как вариант решения с обработкой переполнения разрядов и трехсимвольных цветов
function hexToTriple(hex) {
hex = hex.slice(1);
if (hex.length === 3) {
return hex.split('').map(byte => parseInt(byte.repeat(2), 16));
} else if (hex.length === 6) {
return hex.match(/.{2}/g).map(byte => parseInt(byte, 16));
} else {
throw new Error(`invalid color ${hex}`);
}
}
function tripleToHex(triple) {
return '#' + triple.map(byte => byte.toString(16).padStart(2, '0')).join('');
}
function hexColorSubtract(hexAColor, hexBColor) {
const [tripleA, tripleB] = [hexAColor, hexBColor].map(hexToTriple);
const resultTriple = tripleA.map((byte, index) => {
return Math.max(byte - tripleB[index], 0);
});
return tripleToHex(resultTriple);
}
// использование:
hexColorSubtract("#cef", "#110011"); // #bbeeee