Themed Posts: Adjust identical background/foreground colors.
Description
~~I am immeasurably pissed that this doesn't actually work. You should have heard me when I figured out that you could do it. I was, like, screaming. (I wasn't actually screaming. "You cannot be serious" was said more than a few times, though.)~~ Edit: Ha, victory.
On supporting browser versions, this makes the text/accent colors used by Themed Posts ~~10%~~ a bit lighter or darker if they exactly match the background depending on whether they're light or dark, ~~with the "is it light or dark; go the opposite way" logic implemented in pure CSS. Without sign().~~
~~This doesn't work because Tumblr uses the legacy rgba(var(--someVariable), 0.5) syntax instead of rgba(var(--someVariable) / 0.5), and since you can't mix and match modern and legacy syntax the resulting rgba(from /* etc */ r g b, 0.5) used value is invalid.~~
- [x] if you get this to work, make sure that the divide by zero case in the sign function doesn't cause everything to explode.
Resolves #1636.
Testing steps
- It looks like Tumblr's adjustments are probably in HSL. This results in quite a bit more saturation (at least on the color used in the blog referenced in the linked issue), and actually makes a really nice accent color in that case. I avoided it both for "oklch is technically superior" reasons and as, per https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl, there's a bug in certain chromium versions that would mess up relative
hsl()colors. - I previewed the effect using this code, which lets you use the dev tools color picker on
--background-colorto quickly see different backgrounds and adjusted foregrounds on them.
const hexToRGBAdjusted = color => {
const cssSign = val => `clamp(-1, ${val} * 100000, 1)`;
const isDarkThreshold = 0.4;
const direction = cssSign(`(${isDarkThreshold} - l)`);
const adjustmentAmount = 0.18;
const newColor = `oklch(from ${color} calc(l + ${adjustmentAmount} * ${direction}) c h)`;
const adjusted = `from ${newColor} r g b`;
return adjusted;
};
const backgroundColorRGB = hexToRGB(backgroundColor);
const titleColorRGB = hexToRGB(titleColor);
const linkColorRGB = hexToRGB(linkColor);
styleElement.textContent += `
[data-xkit-themed="${name}"] {
--background-color: ${backgroundColor};
--white: from var(--background-color) r g b;
--black: ${hexToRGBAdjusted('rgb(var(--white))')};
--deprecated-accent: ${linkColorRGB};
--color-primary-link: rgb(var(--deprecated-accent));
}
`;
Also, mdn seems to imply that CSSStyleDeclaration.getPropertyValue() may be able to read the computed values of relative color variables, in which case maybe we can round-trip back to rgb numbers? That would be kind of absurd ("the browser doesn't ship native js color manipulation constructs, but you can make a utility function that does it by constructing and reading back values off a DOM element"), but, sure. Noting this because I might come back to this later and not have remembered that I want to try this.
Edit: Huh. Well now.
const el = dom('div', { style: 'color: rgb(from oklch(from #eb1ff4 l calc(c + 0.03) h) r g b)' });
console.log(el.style.color);
console.log(
el.style.color
.replace('color(srgb ', '')
.replace(')', '')
.split(' ')
.map(Number)
.map(value => value * 256)
.join(', ')
);
// color(srgb 0.949722 -0.15044 0.991859)
// 243.128832, -38.51264, 253.915904
Hey look, a wild undocumented browser bug: https://github.com/mdn/browser-compat-data/issues/26041. Whee!