paint-brush
How To Generate WCAG Compliant Contrast Color in Bootstrap by@itzsrikanth
1,070 reads
1,070 reads

How To Generate WCAG Compliant Contrast Color in Bootstrap

by Srikanth SharmaJanuary 15th, 2021
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The intent of this Success Criterion is to provide enough contrast between text and its background so that it can be read by people with moderately low vision. Contrast ratio can be calculated by finding out relative luminance of both background and foreground colors in current loop. All these values are looped to find the suitable match. To achieve WCAG 2 AA contrast ratio, use color-contrast function to generate contrast text color. The color is returned to a color that matches the contrast ratio of foreground and background colors.

Company Mentioned

Mention Thumbnail
featured image - How To Generate WCAG Compliant Contrast Color in Bootstrap
Srikanth Sharma HackerNoon profile picture

What is the importance of achieving the prescribed contrast ratio?

The intent of this Success Criterion is to provide enough contrast between text and its background so that it can be read by people with moderately low vision.
$theme-colors: (
  "primary":    $primary,
  "secondary":  $secondary,
  "success":    $success,
  "info":       $info,
  "warning":    $warning,
  "danger":     $danger,
  "light":      $light,
  "dark":       $dark
) !default;

Let us take example of a simple button. Based on the set, buttons are generated for each theme color variant in using mixin. This mixin receives a background color for which we need to generate corresponding contrast text color using function. This function uses , which defaults to

4.5
to achieve WCAG 2 AA contrast ratio.

@each $color, $value in $theme-colors {
  .btn-#{$color} {
    @include button-variant($value, $value);
  }
}

In

color-contrast
function, the background color's is compared with foreground colors in following order:

  • $color-contrast-light
  • $color-contrast-dark
  • $white
  • $black

We can override the values of

$color-contrast-light
and
$color-contrast-dark
which is set to default as
$white
and
$black
respectively. All these values are looped to find the suitable match.

@function color-contrast($background, $color-contrast-dark: $color-contrast-dark, $color-contrast-light: $color-contrast-light, $min-contrast-ratio: $min-contrast-ratio) {
  $foregrounds: $color-contrast-light, $color-contrast-dark, $white, $black;
  $max-ratio: 0;
  $max-ratio-color: null;

  @each $color in $foregrounds {
    $contrast-ratio: contrast-ratio($background, $color);
    @if $contrast-ratio > $min-contrast-ratio {
      @return $color;
    } @else if $contrast-ratio > $max-ratio {
      $max-ratio: $contrast-ratio;
      $max-ratio-color: $color;
    }
  }

  @warn "Found no color leading to #{$min-contrast-ratio}:1 contrast ratio against #{$background}...";

  @return $max-ratio-color;
}

When the value of contrast ratio is greater than

$min-contrast-ratio
, that color is returned. Contrast ratio can be calculated by finding out relative luminance of both background and foreground color in current loop.

@function contrast-ratio($background, $foreground: $color-contrast-light) {
  $l1: luminance($background);
  $l2: luminance(opaque($background, $foreground));

  @return if($l1 > $l2, ($l1 + .05) / ($l2 + .05), ($l2 + .05) / ($l1 + .05));
}
to calculate relative luminance is used, which replaces algorithm in Bootstrap.
relativeLuminance (c) {
  c = c / 255;
  return c < 0.03928 ? c / 12.92 : 
  Math.pow((c + 0.055) / 1.055, 2.4);
}
SCSS implementation:
@function luminance($color) {
  $rgb: (
    "r": red($color),
    "g": green($color),
    "b": blue($color)
  );

  @each $name, $value in $rgb {
    $value: if($value / 255 < .03928, $value / 255 / 12.92, nth($_luminance-list, $value + 1));
    $rgb: map-merge($rgb, ($name: $value));
  }

  @return (map-get($rgb, "r") * .2126) + (map-get($rgb, "g") * .7152) + (map-get($rgb, "b") * .0722);
}

Here,

$_luminance-list
is a list of all possible value for
Math.pow((c + 0.055) / 1.055, 2.4)
where
c
lies between [0, 255], which is the range for any channel. This method is used to overcome the difficulty of not having a power function in SCSS as mentioned . The same list is maintained in Bootstrap as well, with 4th decimal point. Refer for more precise value. This

The

red()
,
green()
and
blue()
are SCSS in-built functions to extract each channel's value for calculation.

is function, to remove the alpha channel by truncating it and mixing it with white in a ratio equal to alpha channel's value.

@function opaque($background, $foreground) {
  @return mix(rgba($foreground, 1), $background, opacity($foreground) * 100);
}
Few PRs are already resolved to achieve this contrast ratio like mentioned and .

References


바카라사이트 바카라사이트 온라인바카라