XKit-Rewritten icon indicating copy to clipboard operation
XKit-Rewritten copied to clipboard

Themed Posts: Adjust identical background/foreground colors.

Open marcustyphoon opened this issue 10 months ago • 2 comments

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

marcustyphoon avatar Feb 23 '25 14:02 marcustyphoon

  • 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-color to 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

marcustyphoon avatar Feb 23 '25 16:02 marcustyphoon

Hey look, a wild undocumented browser bug: https://github.com/mdn/browser-compat-data/issues/26041. Whee!

marcustyphoon avatar Feb 24 '25 17:02 marcustyphoon