WCAG

Web Content Accessibility Guidelines.

Colour contrast

WCAG AA

html

<div class="wcag-demo" data-level="AA" style="--accent:#A8E6C1;">
  <div class="wcag-demo__head">
    <p class="wcag-demo__title">Colour contrast</p>
    <span class="wcag-demo__badge">WCAG AA</span>
  </div>
  <div class="wcag-demo__bar"><div class="wcag-demo__fill"></div></div>
  
  <ul class="wcag-demo__list">
    <li class="wcag-demo__item wcag-demo__item--a">Perceivable basics met</li>
    <li class="wcag-demo__item wcag-demo__item--aa">Enhanced contrast &amp; resize met</li>
    <li class="wcag-demo__item wcag-demo__item--aaa">Highest-tier support met</li>
  </ul>
  
</div>
<style>
.wcag-demo { width: 300px; font: 14px system-ui, sans-serif; color: #241430; }
.wcag-demo__head { display: flex; align-items: center; justify-content: space-between; }
.wcag-demo__title { margin: 0; font-weight: 700; }
.wcag-demo__badge { padding: 3px 10px; border-radius: 999px; background: var(--accent); font-size: 11px; font-weight: 700; }
.wcag-demo__bar { margin-top: 10px; height: 8px; border-radius: 999px; background: #24143014; overflow: hidden; }
.wcag-demo__fill { height: 100%; background: var(--accent); width: 33%; }
.wcag-demo[data-level="AA"] .wcag-demo__fill { width: 66%; }
.wcag-demo[data-level="AAA"] .wcag-demo__fill { width: 100%; }
.wcag-demo__list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.wcag-demo__item { font-size: 12px; color: #241430aa; opacity: .4; }
.wcag-demo__item::before { content: "\2713  "; }
.wcag-demo[data-level="A"] .wcag-demo__item--a { opacity: 1; color: #241430; }
.wcag-demo[data-level="AA"] .wcag-demo__item--a, .wcag-demo[data-level="AA"] .wcag-demo__item--aa { opacity: 1; color: #241430; }
.wcag-demo[data-level="AAA"] .wcag-demo__item { opacity: 1; color: #241430; }
</style>

tailwind

<div class="wcag-tw wcag-tw--AA" style="width:300px;font-family:system-ui,sans-serif;color:#241430">
  <div class="flex items-center justify-between">
    <p class="m-0 font-bold">Colour contrast</p>
    <span class="px-2.5 py-0.5 rounded-full text-[11px] font-bold" style="background:#A8E6C1">WCAG AA</span>
  </div>
  <div class="mt-2.5 h-2 rounded-full bg-[#24143014] overflow-hidden">
    <div class="wcag-tw__fill h-full" style="background:#A8E6C1"></div>
  </div>
  
  <ul class="list-none m-0 mt-3 p-0 flex flex-col gap-1">
    <li class="wcag-tw__item wcag-tw__item--a text-xs text-[#241430aa]">&#10003; Perceivable basics met</li>
    <li class="wcag-tw__item wcag-tw__item--aa text-xs text-[#241430aa]">&#10003; Enhanced contrast &amp; resize met</li>
    <li class="wcag-tw__item wcag-tw__item--aaa text-xs text-[#241430aa]">&#10003; Highest-tier support met</li>
  </ul>
  
</div>
<style>
.wcag-tw--A .wcag-tw__fill { width: 33%; }
.wcag-tw--AA .wcag-tw__fill { width: 66%; }
.wcag-tw--AAA .wcag-tw__fill { width: 100%; }
.wcag-tw__item { opacity: .4; }
.wcag-tw--A .wcag-tw__item--a { opacity: 1; color: #241430; }
.wcag-tw--AA .wcag-tw__item--a, .wcag-tw--AA .wcag-tw__item--aa { opacity: 1; color: #241430; }
.wcag-tw--AAA .wcag-tw__item { opacity: 1; color: #241430; }
</style>

react

export function WcagBadge({
  title = "Colour contrast",
  level = "AA",
  showChecklist = true,
  accent = "#A8E6C1",
}) {
  const fillWidth = { A: "33%", AA: "66%", AAA: "100%" }[level];
  const items = [
    { key: "a", label: "Perceivable basics met" },
    { key: "aa", label: "Enhanced contrast & resize met" },
    { key: "aaa", label: "Highest-tier support met" },
  ];
  const active = { A: ["a"], AA: ["a", "aa"], AAA: ["a", "aa", "aaa"] }[level];
  return (
    <div style={{ width: 300, fontFamily: "system-ui, sans-serif", fontSize: 14, color: "#241430" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <p style={{ margin: 0, fontWeight: 700 }}>{title}</p>
        <span style={{ padding: "3px 10px", borderRadius: 999, background: accent, fontSize: 11, fontWeight: 700 }}>WCAG {level}</span>
      </div>
      <div style={{ marginTop: 10, height: 8, borderRadius: 999, background: "#24143014", overflow: "hidden" }}>
        <div style={{ height: "100%", background: accent, width: fillWidth }} />
      </div>
      {showChecklist && (
        <ul style={{ listStyle: "none", margin: "12px 0 0", padding: 0, display: "flex", flexDirection: "column", gap: 4 }}>
          {items.map((it) => (
            <li key={it.key} style={{ fontSize: 12, color: "#241430aa", opacity: active.includes(it.key) ? 1 : 0.4 }}>&#10003; {it.label}</li>
          ))}
        </ul>
      )}
    </div>
  );
}