Color Contrast Checker
Periksa rasio kontras WCAG AA dan AAA antara warna teks dan latar belakang
Warna teks (latar depan)
Warna latar belakang
Sampel Teks Besar (18px tebal)
Sampel teks normal โ beginilah tampilan teks utama Anda terhadap warna latar belakang yang telah dipilih.
Rasio kontras
14.63:1
Kepatuhan WCAG
Lulus
Normal AA
Lulus
Normal AAA
Lulus
Besar AA
Lulus
Besar AAA
WCAG AA โ Teks normal: 4.5:1, Teks besar (18px+ atau 14px tebal): 3:1
WCAG AAA โ Teks normal: 7:1, Teks besar (18px+ atau 14px tebal): 4.5:1
Apa Itu Pemeriksaan Kontras Warna?
Pemeriksaan kontras warna mengukur perbedaan luminansi antara warna latar depan (biasanya teks) dan warna latar belakang, lalu menyatakan hasilnya sebagai rasio. Rasio 1:1 berarti kedua warna identik; 21:1 adalah nilai maksimum, mewakili hitam pada putih atau sebaliknya. Web Content Accessibility Guidelines (WCAG) yang diterbitkan oleh W3C mendefinisikan rasio kontras minimum yang harus dipenuhi teks agar dapat dibaca oleh orang dengan gangguan penglihatan rendah atau defisiensi warna.
Rumus rasio kontras berasal dari WCAG 2.x dan mengandalkan luminansi relatif, yaitu ukuran seberapa terang suatu warna tampak bagi mata manusia. Luminansi relatif dihitung dengan melinearkan setiap kanal sRGB (menghilangkan gamma) dan memberi bobot pada kanal-kanal tersebut sesuai koefisien ITU-R BT.709: 0,2126 untuk merah, 0,7152 untuk hijau, dan 0,0722 untuk biru. Hijau berkontribusi paling besar karena mata manusia paling sensitif terhadap cahaya hijau. Rasionya adalah (L1 + 0,05) / (L2 + 0,05), di mana L1 adalah luminansi warna yang lebih terang.
WCAG mendefinisikan dua tingkat kesesuaian. Level AA mensyaratkan rasio kontras minimal 4,5:1 untuk teks berukuran normal dan 3:1 untuk teks besar (18px ke atas, atau 14px tebal). Level AAA menaikkan standar menjadi 7:1 dan 4,5:1. WCAG 2.1 juga memperkenalkan Success Criterion 1.4.11, yang mensyaratkan rasio 3:1 untuk komponen UI non-teks seperti border, ikon, dan indikator fokus.
Mengapa Menggunakan Contrast Checker Ini?
Memeriksa kontras secara visual tidak dapat diandalkan. Warna yang tampak berbeda pada layar yang terkalibrasi mungkin menyatu di layar laptop berkualitas rendah, di bawah sinar matahari langsung, atau bagi seseorang dengan deuteranopia. Rasio numerik menghilangkan praduga dan memberikan hasil lulus/gagal berdasarkan standar WCAG.
Kasus Penggunaan Contrast Checker
Persyaratan Rasio Kontras WCAG
Tabel di bawah ini merangkum rasio kontras minimum yang dipersyaratkan oleh WCAG 2.1 untuk berbagai jenis konten dan level kesesuaian. Teks besar didefinisikan sebagai 18px (24 CSS pixel) ke atas dengan bobot normal, atau 14px (18,66 CSS pixel) ke atas dengan bobot tebal.
| Level | Rasio minimum | Berlaku untuk | Catatan |
|---|---|---|---|
| AA Normal text | 4.5 : 1 | Body text, paragraphs, labels | Minimum for most UI text |
| AA Large text | 3.0 : 1 | Text >= 18px, or >= 14px bold | Minimum for headings |
| AA UI components | 3.0 : 1 | Borders, icons, focus indicators | Non-text contrast (WCAG 1.4.11) |
| AAA Normal text | 7.0 : 1 | Body text at highest standard | Enhanced readability |
| AAA Large text | 4.5 : 1 | Large text at highest standard | Enhanced for headings |
Luminansi, AA, dan AAA Dijelaskan
Perhitungan rasio kontras memiliki tiga tahap: hitung luminansi untuk setiap warna, turunkan rasionya, dan bandingkan dengan ambang batas WCAG.
Contoh Kode
Hitung rasio kontras WCAG secara terprogram. Setiap contoh mengimplementasikan rumus luminansi relatif dari WCAG 2.x dan perhitungan rasio kontras. Pasangan hitam-pada-putih dan indigo-pada-putih yang sama diuji untuk perbandingan.
// Calculate relative luminance per WCAG 2.x (sRGB)
function luminance(r, g, b) {
const [rs, gs, bs] = [r, g, b].map(c => {
c /= 255
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)
})
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs
}
// Contrast ratio between two RGB colors
function contrastRatio(fg, bg) {
const l1 = luminance(...fg)
const l2 = luminance(...bg)
const lighter = Math.max(l1, l2)
const darker = Math.min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
}
contrastRatio([0, 0, 0], [255, 255, 255]) // -> 21.0
contrastRatio([99, 102, 241], [255, 255, 255]) // -> 3.95
contrastRatio([29, 78, 216], [255, 255, 255]) // -> 6.06 (AA pass)def luminance(r: int, g: int, b: int) -> float:
"""Relative luminance per WCAG 2.x, ITU-R BT.709 coefficients."""
channels = []
for c in (r, g, b):
c /= 255
channels.append(c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4)
return 0.2126 * channels[0] + 0.7152 * channels[1] + 0.0722 * channels[2]
def contrast_ratio(fg: tuple, bg: tuple) -> float:
l1 = luminance(*fg)
l2 = luminance(*bg)
lighter, darker = max(l1, l2), min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
print(f"{contrast_ratio((0, 0, 0), (255, 255, 255)):.2f}") # -> 21.00
print(f"{contrast_ratio((99, 102, 241), (255, 255, 255)):.2f}") # -> 3.95
# Check WCAG AA for normal text
ratio = contrast_ratio((29, 78, 216), (255, 255, 255))
print(f"{ratio:.2f} โ {'AA pass' if ratio >= 4.5 else 'AA fail'}") # -> 6.06 โ AA passpackage main
import (
"fmt"
"math"
)
func linearize(c float64) float64 {
c /= 255
if c <= 0.04045 {
return c / 12.92
}
return math.Pow((c+0.055)/1.055, 2.4)
}
func luminance(r, g, b int) float64 {
return 0.2126*linearize(float64(r)) +
0.7152*linearize(float64(g)) +
0.0722*linearize(float64(b))
}
func contrastRatio(fgR, fgG, fgB, bgR, bgG, bgB int) float64 {
l1 := luminance(fgR, fgG, fgB)
l2 := luminance(bgR, bgG, bgB)
lighter := math.Max(l1, l2)
darker := math.Min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
}
func main() {
ratio := contrastRatio(0, 0, 0, 255, 255, 255)
fmt.Printf("%.2f\n", ratio) // -> 21.00
ratio = contrastRatio(29, 78, 216, 255, 255, 255)
fmt.Printf("%.2f\n", ratio) // -> 6.06 (AA pass for normal text)
}/* WCAG-safe color pairs โ tested contrast ratios */
/* 12.63:1 โ passes AAA normal text */
.high-contrast {
color: #1e293b; /* slate-800 */
background: #f8fafc; /* slate-50 */
}
/* 7.07:1 โ passes AAA normal text */
.dark-theme-text {
color: #e2e8f0; /* slate-200 */
background: #0f172a; /* slate-900 */
}
/* 4.57:1 โ passes AA normal, fails AAA */
.accent-on-white {
color: #1d4ed8; /* blue-700 */
background: #ffffff;
}
/* 2.14:1 โ fails AA for text, but passes 3:1 for large text */
.muted-heading {
color: #94a3b8; /* slate-400 */
background: #ffffff;
}