도입 스토리
"멘토님, 고객센터에서 연락이 왔어요." 김개발이 메일을 보여주었습니다. "글자가 너무 작다는 민원이에요. 노안이 있는 분인데, 브라우저에서 확대를 하면 레이아웃이 깨진다고요."
박멘토가 Chrome에서 Ctrl+Plus를 눌러 200%까지 확대했습니다.
내비게이션 바가 다른 콘텐츠 위로 겹쳐 버렸습니다. 텍스트는 컨테이너를 벗어났습니다. 스크롤 없이는 내용을 읽을 수 없었습니다.
"이게 접근성 위반이에요." 박멘토가 말했습니다. "WCAG에서는 200%까지 확대해도 콘텐츠와 기능이 손실되지 않아야 한다고 규정해요."
핵심 개념 설명
텍스트 크기 조정 — WCAG 1.4.4
WCAG 성공 기준 1.4.4는 텍스트를 200%까지 확대할 수 있어야 한다고 요구합니다. 콘텐츠나 기능의 손실 없이.
이를 위해 픽셀(px) 대신 상대 단위를 사용해야 합니다.
/* 잘못된 예: 고정 픽셀 단위 */body { font-size: 14px;}h1 { font-size: 24px;}/* 올바른 예: 상대 단위 */:root { font-size: 16px; /* 기준 크기 */}body { font-size: 1rem; /* 16px */}h1 { font-size: 1.5rem; /* 24px */}
브라우저 기본 글자 크기는 16px입니다. 사용자가 브라우저 설정에서 글자 크기를 20px로 바꿔도 rem 단위는 이 설정을 따릅니다. px 단위는 무시합니다.
rem과 em의 차이
| 단위 | 기준 | 사용 시기 |
|---|---|---|
rem |
루트 요소(html)의 폰트 크기 |
전체 레이아웃, 기본 텍스트 크기 |
em |
부모 요소의 폰트 크기 | 컴포넌트 내부의 상대적 크기 조정 |
px |
절대값 | 테두리(border), 그림자 등 UI 세부 요소 |
/* rem 예시 — 항상 html 폰트 크기 기준 */.container { padding: 1.5rem; /* html이 16px이면 24px */}/* em 예시 — 부모 기준 */.card { font-size: 0.875rem; /* 14px */}.card .label { font-size: 0.8em; /* 카드 폰트 크기의 80% = 11.2px */}
뷰포트 단위와 접근성
뷰포트 단위(vw, vh)를 텍스트에 사용하면 확대 시 문제가 생깁니다.
/* 잘못된 예: vw 단위로 텍스트 크기 설정 */h1 { font-size: 5vw; /* 확대해도 크기가 변하지 않음 */}/* 올바른 예: clamp()로 반응형 + 확대 가능 */h1 { font-size: clamp(1.5rem, 4vw, 3rem);}
clamp(최소값, 선호값, 최대값)은 뷰포트에 따라 유연하게 변하면서도 최소·최대 크기를 rem으로 고정해 확대에 대응합니다.
200% 확대 시 레이아웃 유지
확대해도 가로 스크롤이 생기거나 내용이 잘리지 않아야 합니다.
/* 유연한 레이아웃 기본 설정 */* { box-sizing: border-box;}.container { max-width: 1200px; width: 100%; padding: 0 1rem; margin: 0 auto;}/* 고정폭 컨테이너 대신 유연한 그리드 */.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1.5rem;}
텍스트가 넘칠 때는 overflow-wrap: break-word로 처리합니다.
p, h1, h2, h3, li { overflow-wrap: break-word; word-break: keep-all; /* 한국어 단어 단위 줄바꿈 */}
줄 간격과 텍스트 가독성
WCAG 1.4.12 텍스트 간격 기준:
| 속성 | 최소 기준 |
|---|---|
줄 높이(line-height) |
폰트 크기의 1.5배 이상 |
단락 간격(margin-bottom) |
폰트 크기의 2배 이상 |
자간(letter-spacing) |
폰트 크기의 0.12em 이상 |
단어 간격(word-spacing) |
폰트 크기의 0.16em 이상 |
/* 텍스트 간격 접근성 기준 충족 */body { line-height: 1.6; /* 1.5 이상 */ letter-spacing: 0.02em; word-spacing: 0.1em;}p + p { margin-top: 2em; /* 단락 간격 2em 이상 */}
사용자 정의 텍스트 크기 설정 존중
사용자가 OS나 브라우저에서 큰 글꼴을 설정했을 때 이를 덮어쓰면 안 됩니다.
/* 잘못된 예: 브라우저 설정을 무시 */html { font-size: 62.5%; /* 1rem = 10px 트릭 — 권장하지 않음 */}/* 올바른 예: 브라우저 기본값 유지 */html { /* font-size 설정하지 않음 = 브라우저 기본 16px 사용 */}/* 또는 백분율로 기준 조정 */html { font-size: 100%; /* 브라우저 설정 그대로 */}
단계별 실습
따라하기: 200% 확대 테스트
- 브라우저에서 작업 중인 페이지를 엽니다.
- Ctrl+Plus(Windows) 또는 Cmd+Plus(macOS)로 200%까지 확대합니다.
- 다음을 확인합니다.
- 텍스트가 잘리거나 겹치지 않는가.
- 가로 스크롤이 생기지 않는가.
- 모든 기능(버튼, 폼, 메뉴)이 정상 작동하는가.
- 텍스트가 컨테이너 밖으로 나가지 않는가.
변형하기: px를 rem으로 변환하기
기존 CSS에서 px 단위를 찾아 rem으로 변환합니다.
/* 변환 전 */.nav { font-size: 14px; padding: 16px 24px;}.hero-title { font-size: 48px; margin-bottom: 32px;}/* 변환 후 (기준: 1rem = 16px) */.nav { font-size: 0.875rem; /* 14 ÷ 16 */ padding: 1rem 1.5rem; /* 16 ÷ 16, 24 ÷ 16 */}.hero-title { font-size: 3rem; /* 48 ÷ 16 */ margin-bottom: 2rem; /* 32 ÷ 16 */}
계산식: rem값 = px값 ÷ 기준px(16)
응용하기: 텍스트 간격 준수 확인
Chrome DevTools Computed 탭에서 line-height, letter-spacing, word-spacing 값을 확인합니다.
혹은 아래 JavaScript로 페이지 전체를 빠르게 검사합니다.
// 줄 높이 1.5 미만 요소 찾기document.querySelectorAll('p, li, td, span').forEach(el => { const style = window.getComputedStyle(el); const lineHeight = parseFloat(style.lineHeight); const fontSize = parseFloat(style.fontSize); if (lineHeight / fontSize < 1.5) { console.warn('줄 높이 부족:', el, lineHeight / fontSize); }});
정리와 확인
핵심 내용 요약
- px 대신 rem: 브라우저 글꼴 설정을 존중하고 200% 확대에 대응
- 200% 확대 기준(WCAG 1.4.4): 콘텐츠·기능 손실 없어야 함
- clamp(): 반응형 타이포그래피를 접근성 있게 구현
- 줄 높이 1.5 이상(WCAG 1.4.12): 텍스트 가독성 확보
- 유연한 레이아웃:
auto-fit,minmax,overflow-wrap으로 확대 대응
확인 문제
문제 1. 브라우저에서 기본 글꼴 크기를 20px로 설정한 사용자에게 1.5rem은 몇 px로 표시되는가?
30px
(1.5rem × 20px = 30px, rem은 브라우저 설정을 따름)
문제 2. 다음 중 WCAG 1.4.12 텍스트 간격 기준을 위반하는 것은?
p { line-height: 1.2; } /* 위반 — 1.5 이상이어야 함 */p { line-height: 1.6; } /* 통과 */
PART 02를 마쳤습니다. 다음 PART에서는 "운용할 수 있는(Operable)" 원칙을 다룹니다. 마우스 없이 키보드만으로 웹을 탐색할 수 있어야 하는 이유와 방법을 배웁니다.