SuperAPI AI Directory

accessibility-wcag

Frontend & websites

View repository

Updated 10-15 18:45

About this skill

Accessibility (WCAG 2.2)

This is a skill that enforces compliance with the web accessibility standard WCAG 2.2.

2025 Context

WCAG 2.2 was adopted as an ISO standard (ISO/IEC 40500) in October 2023. The European Accessibility Act (EAA) takes effect in June 2025.

Core Principles (POUR)

Principle Description Example
Perceivable Perceivable Alternative text, captions, color contrast
Operable Operable Keyboard access, sufficient time
Understandable Understandable Clear language, predictable behavior
Robust Robust Assistive technology compatibility

Rules

1. Semantic HTML (Required)

// ❌ BAD: div 남용
<div onClick={handleClick}>버튼</div>
<div class="header">제목</div>

// ✅ GOOD: 시맨틱 태그 사용
<button onClick={handleClick}>버튼</button>
<h1>제목</h1>

2. Image Alternative Text (Required)

// ❌ BAD: alt 누락 또는 의미 없음
<img src="logo.png" />
<img src="chart.png" alt="이미지" />

// ✅ GOOD: 의미 있는 alt
<img src="logo.png" alt="회사명 로고" />
<img src="chart.png" alt="2024년 매출 증가 추이 그래프" />

// ✅ 장식용 이미지는 빈 alt
<img src="decoration.png" alt="" role="presentation" />

3. Keyboard Accessibility (Required)

// ❌ BAD: 키보드 접근 불가
<div onClick={handleClick} style={{ cursor: 'pointer' }}>
  클릭
</div>

// ✅ GOOD: 키보드 접근 가능
<button onClick={handleClick}>클릭</button>

// 또는 커스텀 요소 사용 시
<div
  role="button"
  tabIndex={0}
  onClick={handleClick}
  onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
  클릭
</div>

4. Focus Management

// ❌ BAD: 포커스 스타일 제거
button:focus {
  outline: none;
}

// ✅ GOOD: 명확한 포커스 표시
button:focus {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

button:focus-visible {
  outline: 2px solid #005fcc;
}

5. Color Contrast (WCAG AA Standard)

Text Size Minimum Contrast Ratio
Normal Text 4.5:1
Large Text (18pt+, 14pt bold+) 3:1
UI Components/Graphics 3:1
/* ❌ BAD: 낮은 대비 */
.text {
  color: #999;  /* 회색 on 흰색 = 2.85:1 */
  background: #fff;
}

/* ✅ GOOD: 충분한 대비 */
.text {
  color: #595959;  /* 4.54:1 */
  background: #fff;
}

6. Form Labels (Required)

// ❌ BAD: 레이블 없음
<input type="email" placeholder="이메일" />

// ✅ GOOD: 명시적 레이블
<label htmlFor="email">이메일</label>
<input id="email" type="email" />

// 또는 aria-label 사용
<input type="email" aria-label="이메일 주소" placeholder="이메일" />

7. ARIA Roles and Properties

// 모달 다이얼로그
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">확인</h2>
  ...
</div>

// 알림 메시지
<div role="alert" aria-live="polite">
  저장되었습니다.
</div>

// 로딩 상태
<button aria-busy={isLoading} disabled={isLoading}>
  {isLoading ? '처리 중...' : '제출'}
</button>

8. Skip Links

// 페이지 상단에 추가
<a href="#main-content" className="skip-link">
  본문으로 건너뛰기
</a>

// CSS
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}

WCAG 2.2 New Criteria

2.4.11 Focus Not Obscured (AA)

// ❌ BAD: 고정 헤더가 포커스 요소를 가림
.header { position: fixed; top: 0; }

// ✅ GOOD: scroll-margin으로 여유 공간 확보
:target {
  scroll-margin-top: 80px;
}

*:focus {
  scroll-margin-top: 80px;
}

2.5.7 Dragging Movements (AA)

// ❌ BAD: 드래그만 지원
<DraggableList onDrag={handleReorder} />

// ✅ GOOD: 드래그 + 버튼 대안 제공
<DraggableList onDrag={handleReorder}>
  <button onClick={moveUp}>위로 이동</button>
  <button onClick={moveDown}>아래로 이동</button>
</DraggableList>

2.5.8 Target Size (AA)

/* 최소 터치 타겟: 24x24px (AA), 44x44px 권장 */
button, a, input[type="checkbox"] {
  min-width: 44px;
  min-height: 44px;
}

Testing Tools

Automated Tools

# axe-core (React)
npm install @axe-core/react

# eslint-plugin-jsx-a11y
npm install eslint-plugin-jsx-a11y --save-dev

# Lighthouse CI
npm install -g @lhci/cli
lhci autorun

eslint Configuration

{
  "extends": ["plugin:jsx-a11y/recommended"],
  "rules": {
    "jsx-a11y/alt-text": "error",
    "jsx-a11y/anchor-is-valid": "error",
    "jsx-a11y/click-events-have-key-events": "error",
    "jsx-a11y/no-static-element-interactions": "error"
  }
}

Manual Testing Checklist

  • All functions usable with keyboard only
  • Tab order is logical
  • Focus indication is clear
  • Content understandable with screen reader
  • No content loss when zoomed to 200%
  • Information not conveyed by color alone

Workflow

1. When Writing Components

체크포인트:
1. 시맨틱 HTML 사용했는가?
2. 키보드 접근 가능한가?
3. 적절한 ARIA 속성이 있는가?
4. 포커스 스타일이 있는가?

2. During Code Review

접근성 체크:
1. img에 alt 있는가?
2. form에 label 있는가?
3. 색상 대비 충분한가?
4. 터치 타겟 크기 충분한가?

Checklist

  • Use semantic HTML tags
  • Meaningful alt for all images
  • Connect labels to form elements
  • Operable with keyboard only
  • Clear focus indication
  • Color contrast of 4.5:1 or higher
  • Touch targets 44x44px or larger
  • Provide skip links
  • Pass axe/Lighthouse tests

References