Search code examples
javascriptsassbootstrap-5wcag

How to mimic bootstrap WCAG algorithm to pick active colors in JavaScript?


When I moved to bootstrap 5, I noticed that they use an algorithm to pick the text color when a button is hovered or active.

eg:

  • If your primary color is black, when you hover the button, the background gets black but the button text color is white.
  • If you primary color is white, when you hover the button, the background gets white but the text color is black.
  • If your primary color is, lets say, green, the variable that bootstrap uses to decide is the min-contrast-ratio.

I want to replicate this in JavaScript, because I'm doing a theme builder, but I don't know how to implement it. Bootstrap docs says they implement a WCAG 2.1 algorithm to do this thing. But I can't find any docs on how to implement this algorithm in JavaScript. I also tried to read bootstrap source code but I'm kind of beginner in scss and I didn't understand a thing.

Any help would be appreciated.


Solution

  • There is no WCAG algorithm for picking a color relative to another color. There is an algorithm for computing the contrast between two colors but you have to plug in the two colors manually. WCAG doesn't have a way to generate a second color given the first color.

    The contrast ratio formula starts off simple:

    (L1 + 0.05) / (L2 + 0.05), where

    • L1 is the relative luminance of the lighter of the colors, and
    • L2 is the relative luminance of the darker of the colors.

    It's the "relative luminance" that gets messy.

    L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:

    • if RsRGB <= 0.04045 then R = RsRGB/12.92 else R = ((RsRGB+0.055)/1.055) ^ 2.4
    • if GsRGB <= 0.04045 then G = GsRGB/12.92 else G = ((GsRGB+0.055)/1.055) ^ 2.4
    • if BsRGB <= 0.04045 then B = BsRGB/12.92 else B = ((BsRGB+0.055)/1.055) ^ 2.4

    and RsRGB, GsRGB, and BsRGB are defined as:

    • RsRGB = R8bit/255
    • GsRGB = G8bit/255
    • BsRGB = B8bit/255

    I warned you :-)

    It's actually not too bad once you've played with it a bit. Just take a hex RGB value, such as #123456, and split it into the RGB values (R=#12, G=#34, B=#56). Convert the hex values to decimal and divide each one by 255. That gives you the bottom part of the "relative luminance" formula (RsRGB, GsRGB, BsRGB). Then you can work your way up.

    Having said all that, I have another answer where someone was trying to adjust two colors to give them a better contrast. Perhaps this will help:

    Adapt given color pairs to adhere to W3C Accessibility standard for ePubs