Arms crossed picture of James Auble
disqus embed.js compiled source

OKLCH Colors Workaround For Disqus' Embed.js

Published

Tried using OKLCH colors on your blog that uses Disqus and finding that Disqus embed isn't loading? If you check the developer tools you might find something to the tune of

Uncaught Error: parseColor received unparseable color: oklch(000)

I ran into this today and after brief investigation discovered that the issue stems from the color detection logic in the embed.js library that Disqus uses.

From the compiled code we receive from Disqus, we can see that only Hex and sRGB/RGB values are accepted during the color detection process:

v = function(b) {
    function c(a) {
      return a.replace(/\s+/g, "").toLowerCase()
    }
    function d(a) {
      return a = a.replace(/^#([a-f0-9])([a-f0-9])([a-f0-9])$/, "#$1$1$2$2$3$3"),
      a = a.slice(1),
      {
        red: parseInt(a.slice(0, 2), 16),
        green: parseInt(a.slice(2, 4), 16),
        blue: parseInt(a.slice(4, 6), 16)
      }
    }
    function e(a) {
      var b = a.match(/^rgb\((\d+),(\d+),(\d+)\)$/);
      return {
        red: parseInt(b[1], 10),
        green: parseInt(b[2], 10),
        blue: parseInt(b[3], 10)
      }
    }
    function f(a) {
      var b = a.match(/^rgba\((\d+),(\d+),(\d+),([\d.]+)\)$/);
      return {
        red: parseInt(b[1], 10),
        green: parseInt(b[2], 10),
        blue: parseInt(b[3], 10),
        alpha: parseFloat(b[4])
      }
    }
    function g(b, c, d, e) {
      return c = a.document.createElement(c),
      i(c, {
        visibility: "hidden",
        color: d
      }),
      b.appendChild(c),
      d = e(c),
      b.removeChild(c),
      d
    }
    function h(b, d) {
      d = d || {};
      var f = d.container || a.document.body;
      return a.getComputedStyle ? (b = g(f, "span", b, function(b) {
        return a.getComputedStyle(b, null).getPropertyValue("color")
      }),
      e(c(b))) : (b = g(f, "textarea", b, function(a) {
        return a.createTextRange().queryCommandValue("ForeColor")
      }),
      {
        red: 255 & b,
        blue: b >>> 16,
        green: (65280 & b) >>> 8
      })
    }
    var i = u;
    return function(a, b) {
      a = c(a);
      var g;
      if ("transparent" === a)
        return {
          red: 0,
          green: 0,
          blue: 0,
          alpha: 0
        };
      if ("#" === a.charAt(0))
        g = d;
      else if ("rgba(" === a.slice(0, 5))
        g = f;
      else if ("rgb(" === a.slice(0, 4))
        g = e;
      else {
        if (!/^[a-z]+$/.test(a))
          throw new Error("parseColor received unparseable color: " + a);
        g = h
      }
      return g(a, b)
    }
  }({})

My Solution 

Since my OKLCH values were set via CSS variables on the :root element and cascade down until they're overridden, the obvious solution was to reset my CSS variables for colors on my Disqus container element.

So I ended up with something like this

:root,
.comments {
  --magenta: #ff00ff;
  --magenta-dark-box-shadow: rgba(127, 0, 127, 0.5);
  --blackberry: #4b0a37;
  --cyan: #83FAFF;
  --midnight-blue: #111C7E;
  --background-lightened: rgba(0, 0, 0, 0.9);
  --body-text-on-black: #fff;
  --background-black: rgba(0, 0, 0, 1);
}

This almost did the trick. But I noticed that the color parser was still failing when it was attempting to parse my background color which it was grabbing from the computed property somewhere up the cascade (likely the body or root element).

Since I was setting my body background to a color that was both within the OKLCH color space as well as the sRGB color space, it really didn't matter if I just swapped out my OKLCH color for an sRGB value to be compatible with the embed.js parsing logic.

So that's what I did.

@media (color-gamut: p3) { 
  :root {
    --magenta: oklch(70.17% 0.322 328.36);
    --magenta-dark-box-shadow: oklch(41.85% 0.192 328.36 / 50%);
    --blackberry: oklch(28.52% 0.107 343.77);
    --cyan: oklch(91.77% 0.10793602296908084 199.0626165273784);
    --midnight-blue: oklch(30.5% 0.161 268.08);
    --background-lightened: oklch(0% 0 0 / 90%);
    --body-text-on-black: oklch(100% 0 0);
    // hack for disqus color parsing compatibility
    --background-black: rgba(0, 0, 0, 1);
  }
}

And if only for a moment--once again everything is right in the world.

Code on web assassins!

Scrolldown Icon