예쁘게 뽑은 연회색 글씨가 정작 밝은 데서는 안 읽히는 일이 흔합니다. 대비는 취향이 아니라 숫자로 확인하는 것이고, 그 숫자를 코드에 반영하면 아무나 읽을 수 있는 화면이 됩니다. 아래 색값은 그대로 확인해 볼 수 있습니다.

50.1 명암비라는 기준

웹 접근성 지침은 본문 글자와 배경의 명암비를 4.5:1 이상으로 권합니다. 큰 글씨나 아이콘 같은 요소는 3:1이면 통과입니다.


/* 배경 흰색(#fff) 위 글자색 */
.pass-body { color: #595959; } /* 약 7:1, 본문 통과 */
.pass-large { color: #767676; } /* 약 4.5:1, 큰 글씨용 */
.fail-body { color: #9ca3af; } /* 약 2.5:1, 본문 실패 */


같은 회색 계열이라도 어디까지 밝아지면 탈락인지 선이 있습니다. #9ca3af는 보기엔 멀쩡해도 본문으로 쓰면 기준 미달입니다.

50.2 명암비는 어떻게 나오나

명암비는 두 색의 상대 휘도로 계산합니다. 밝은 쪽 휘도를 L1, 어두운 쪽을 L2라 하면 비율은 (L1 + 0.05) / (L2 + 0.05)입니다.


/* 흰색 휘도 L1 = 1.0 */
/* #767676 휘도 L2 = 약 0.175 */
/* (1.0 + 0.05) / (0.175 + 0.05) */
/* = 1.05 / 0.225 = 약 4.67 : 1 -> 통과 */


휘도는 단순한 밝기가 아니라 사람 눈이 초록에 민감한 점까지 반영한 값입니다. 그래서 노랑은 밝게, 파랑은 어둡게 계산됩니다. 실무에서는 검사 도구가 이 숫자를 대신 뽑아 주지만, 원리를 알면 왜 특정 조합이 탈락하는지 감이 옵니다.

50.3 통과와 실패를 나란히

같은 파란 버튼이라도 글자색을 잘못 얹으면 흐릿해집니다. 배경색이 진할수록 흰 글자가 안전합니다.


.btn-bad {
background: #60a5fa;
color: #ffffff; /* 약 2.1:1, 실패 */
}
.btn-good {
background: #1d4ed8;
color: #ffffff; /* 약 7.4:1, 통과 */
}


밝은 파랑 위 흰 글자는 의외로 잘 안 읽힙니다. 배경을 한두 단계 진하게 내리는 것만으로 비율이 훌쩍 올라갑니다.

50.4 링크와 본문 구분

링크는 본문과 구분되면서도 그 자체로 대비를 확보해야 합니다. 색만으로 구분하면 색각 이상이 있는 분은 링크를 못 알아봅니다.


p { color: #1f2937; }
a {
color: #1d4ed8; /* 흰 배경에서 통과 대비 */
text-decoration: underline; /* 색 말고 밑줄로도 표시 */
}


밑줄을 살려 두면 색을 못 봐도 링크임을 압니다. 색은 거들 뿐, 정보를 색 하나에만 싣지 않는 것이 원칙입니다.

50.5 포커스 외곽선도 보여야

키보드로 이동하는 사용자에게 지금 어디에 있는지 알리는 외곽선도 대비가 필요합니다. 배경과 구분되는 진한 색을 씁니다.


.btn:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 2px;
}


offset을 줘서 외곽선이 버튼에 딱 붙지 않고 살짝 떠 보이게 했습니다. 배경과 버튼 사이에서 또렷하게 자리를 잡습니다.

50.6 색만으로 말하지 않기

입력 오류를 빨간 테두리로만 표시하면 색을 구분 못 하는 분에게는 아무 신호가 아닙니다. 아이콘이나 글자를 함께 씁니다.


.field-error {
border: 1px solid #dc2626;
}
.field-error .msg::before {
content: "\26A0 "; /* 경고 기호 */
color: #dc2626;
}


빨간 테두리에 경고 기호와 안내 문구가 겹치면, 색을 못 봐도 무엇이 잘못됐는지 전해집니다. 신호를 두 겹으로 주는 셈입니다.

50.7 고대비 모드 대응

운영체제에서 고대비를 켠 사용자를 위한 미디어쿼리가 있습니다. 이때는 옅은 회색 대신 더 진한 값으로 갈아 줍니다.


.desc { color: #6b7280; }
@media (prefers-contrast: more) {
.desc { color: #1f2937; }
.btn { outline: 2px solid currentColor; }
}


평소엔 부드러운 회색 설명을 쓰다가, 고대비를 원하는 사용자에겐 진한 글자와 또렷한 외곽선을 내줍니다. 한 화면이 두 벌의 대비를 갖추는 방법입니다.

50.8 회색 텍스트의 함정

흐린 회색 설명 글자는 디자인 시안에서는 세련돼 보이지만 실제로는 탈락하기 쉽습니다. 배경별로 안전한 회색의 하한이 다릅니다.


/* 흰 배경(#fff) 기준 */
.caption-bad { color: #b0b0b0; } /* 약 2.1:1, 실패 */
.caption-ok { color: #767676; } /* 약 4.5:1, 큰 글씨만 */
.caption-good { color: #595959; } /* 약 7:1, 본문 안전 */


보조 설명이라고 무작정 옅게 두면 정작 필요한 사람이 못 읽습니다. 회색을 쓰더라도 4.5:1 선은 지키는 편이 좋습니다.

50.9 배경색 위 글자 자동 대비

배경이 밝으면 어두운 글자, 어두우면 밝은 글자가 안전합니다. 배지 색이 여러 개일 때는 배경 명도에 따라 글자색을 나눠 둡니다.


.tag {
padding: 2px 8px;
border-radius: 4px;
}
.tag-light {
background: hsl(48 96% 88%);
color: hsl(48 90% 24%); /* 밝은 배경엔 어두운 글자 */
}
.tag-dark {
background: hsl(221 70% 32%);
color: hsl(221 40% 94%); /* 어두운 배경엔 밝은 글자 */
}


같은 배지 컴포넌트라도 배경 명도에 맞춰 글자를 뒤집으니 어느 색을 골라도 읽힙니다. 배경과 글자의 명도 차를 늘 크게 유지하는 것이 핵심입니다.

50.10 큰 글씨의 예외

같은 글자라도 크고 굵으면 기준이 3:1로 느슨해집니다. 18.66px 굵은 글씨나 24px 이상이 여기에 해당합니다.


.hero-title {
font-size: 2rem;
font-weight: 700;
color: #6b7280; /* 약 3.9:1, 큰 글씨라 통과 */
}
.hero-desc {
font-size: 1rem;
color: #6b7280; /* 같은 색인데 본문 크기라 아슬 */
}


똑같은 회색이 제목에서는 통과, 본문에서는 위태롭습니다. 크기가 대비 기준을 바꾸니 색만이 아니라 글자 크기까지 함께 봐야 합니다. 작은 글씨일수록 대비를 넉넉히 잡는 편이 안전합니다.


.footnote {
font-size: 0.75rem;
color: #4b5563; /* 작은 글씨라 더 진하게, 약 8:1 */
}


각주처럼 작은 글씨는 아예 한 단계 더 진한 색으로 내려 잡습니다. 크기가 작을수록 대비의 여유가 줄어들기 때문입니다.

50.11 정리

대비는 눈대중이 아니라 4.5:1이라는 선이 있는 숫자입니다. 본문은 이 선을 넘기고, 색만으로 정보를 싣지 말고 밑줄이나 아이콘을 겹치고, 포커스 외곽선과 고대비 모드까지 챙기면 화면은 훨씬 많은 사람에게 열립니다. 접근성은 배려가 아니라 안 읽히는 글씨를 안 읽히게 두지 않는 기본기입니다.