Contrast corrector

If contrast if not good enough correct it.

by Andrew Bone

HTML

<button class="example" style="color: #FFF; background: #FFF;">Button 1</button>
<button class="example" style="color: #ffffff; background: #093656;">Button 2</button>
<button class="example" style="color: #dce9f3; background: #19063A;">Button 3</button>
<button class="example" style="color: #000; background: #000;">Button 4</button>

CSS

.example {
  border: none;
  border-radius: 3px;
  padding: 10px 15px;
}

JavaScript

function hexToRgb(hex) {
  let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    R: parseInt(result[1], 16),
    G: parseInt(result[2], 16),
    B: parseInt(result[3], 16)
  } : null;
}

function splitRgb(hex) {
  let result = hex.split(/[()]/g)[1].split(/,/g);
  return result ? {
    R: result[0],
    G: result[1],
    B: result[2]
  } : null;
}

function calcLuminance(hex) {
  // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
  let color = hexToRgb(hex) || splitRgb(hex);
  const L = C => {
    return (C / 255) <= 0.03928 ? (C / 255) * (1 / 12.92) : Math.pow(((C / 255) + 0.055) / 1.055, 2.4)
  };
  return (0.2126 * L(color.R) + 0.7152 * L(color.G) + 0.0722 * L(color.B));
}

function calcContrast(foreground, background) {

  let bg = calcLuminance(background);
  let fg = calcLuminance(foreground);

  let ratio = (fg + 0.05) / (bg + 0.05);

  /* Invert ratio if need be */
  if (fg < bg) {
    ratio = 1 / ratio;
  }

  /* If it passes spec return it */
  if (ratio >= 7) return foreground;
  /* If it fails return black for white */
  if (bg > 0.5) return "#000000";
  return "#FFFFFF";
}


document.querySelectorAll('.example').forEach(ele => {
  let background = window.getComputedStyle(ele).getPropertyValue('background-color');
  let foreground = window.getComputedStyle(ele).getPropertyValue('color');
  ele.style.color = calcContrast(foreground, background);
})