BelajarKoding Logobelajarkoding

Platform belajar web development Indonesia. Artikel, cheat sheets, roadmap, dan code challenges untuk developer Indonesia.

Navigasi

  • Artikel
  • Cheat Sheets
  • Roadmap
  • Challenges
  • Pricing
  • Search

Produk Lain

  • JagoHermes
  • KelasClaude
  • KilatKoding
  • BelajarVibeCoding
  • JualanKoding

Support

  • Privacy Policy
  • Terms of Service
  • Email

© 2026 BelajarKoding. All rights reserved.

Galih PratamaBagian dari ekosistem Galih Pratama
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade

Daftar Isi

WCAG Principles (POUR)WCAG Compliance LevelsColor Contrast RequirementsSemantic HTMLHeading HierarchyAlt Text GuidelinesForm AccessibilityKeyboard NavigationFocus ManagementARIA AttributesCommon RolesCommon AttributesLive RegionsScreen Reader Only ContentSkip LinksTouch TargetsCustom Interactive ElementsModal DialogMedia AccessibilityTesting ChecklistManual TestingScreen Reader TestingAutomated TestingVisual TestingKesalahan UmumTesting ToolsBrowser ExtensionsColor ContrastScreen ReadersValidatorsQuick ReferenceARIA Live RegionsButton StatesProgressive EnhancementResourcesRemember
Accessibilitya11yFrontendHTMLARIA

Web Accessibility (a11y) Cheat Sheet

Quick reference untuk web accessibility best practices. WCAG guidelines, ARIA attributes, testing tools, dan checklist lengkap.

HTML7 min read1.352 kata
Silakan login atau daftar untuk membaca cheat sheet ini.

#WCAG Principles (POUR)

Prinsip-prinsip dasar Web Content Accessibility Guidelines yang harus dipenuhi untuk membuat website yang accessible.

PrincipleDescription
PerceivableContent dapat dipersepsi oleh user
OperableUI dapat dioperasikan via keyboard/input lain
UnderstandableContent dan operasi dapat dipahami
RobustBekerja di berbagai teknologi & browser

#WCAG Compliance Levels

Level-level kepatuhan WCAG untuk mengukur seberapa accessible website kita.

  • Level A - Minimum (basic requirements)
  • Level AA - Target ini! (mid-range, industry standard)
  • Level AAA - Highest (ideal, not always achievable)

#Color Contrast Requirements

Persyaratan kontras warna yang harus dipenuhi agar text mudah dibaca oleh semua orang.

Content TypeWCAG AAWCAG AAA
Normal text (< 24px)4.5:17:1
Large text (≥ 24px)3:14.5:1
UI components3:1-

#Semantic HTML

Penggunaan elemen HTML yang tepat sesuai dengan fungsinya untuk membantu assistive technology.

html
<!-- Use proper elements -->
<button>Click</button>     <!-- NOT <div onclick> -->
<a href="/page">Link</a>    <!-- NOT <span onclick> -->
<nav>...</nav>         <!-- NOT <div class="nav"> -->
<main>...</main>        <!-- NOT <div id="main"> -->
<header>...</header>
<footer>...</footer>
<article>...</article>
<section>...</section>

#Heading Hierarchy

html
<!-- Correct hierarchy -->
<h1>Page Title</h1>
 <h2>Section</h2>
  <h3>Subsection</h3>
  <h3>Subsection</h3>
 <h2>Section</h2>
 
<!-- Don't skip levels -->
<h1>Title</h1>
<h3>Section</h3> <!-- Skipped h2! -->

Rules:

  • One <h1> per page
  • Don't skip levels
  • Logical hierarchy

#Alt Text Guidelines

html
<!-- Informative image -->
<img src="chart.png" alt="Sales increased 50% in Q4 2024" />
 
<!-- Decorative image -->
<img src="divider.svg" alt="" />
 
<!-- Linked image -->
<a href="/profile">
 <img src="avatar.jpg" alt="Go to profile page" />
</a>
 
<!-- Icon with text -->
<button>
 <svg aria-hidden="true">...</svg>
 Delete
</button>
 
<!-- Icon without text -->
<button aria-label="Delete item">
 <svg aria-hidden="true">...</svg>
</button>

Tips:

  • Be concise (< 150 characters)
  • Describe content & function
  • Don't say "image of..."
  • Empty alt for decorative images

#Form Accessibility

html
<!-- Label association -->
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
 
<!-- Implicit label -->
<label>
 Email
 <input type="email" name="email" />
</label>
 
<!-- Hint text -->
<label for="password">Password</label>
<input
 type="password"
 id="password"
 aria-describedby="pwd-hint"
/>
<span id="pwd-hint">Min 8 characters</span>
 
<!-- Error message -->
<label for="username">Username</label>
<input
 type="text"
 id="username"
 aria-invalid="true"
 aria-describedby="username-error"
/>
<span id="username-error" role="alert">
 Username already taken
</span>
 
<!-- Radio group -->
<fieldset>
 <legend>Choose plan</legend>
 <label><input type="radio" name="plan" value="free" /> Free</label>
 <label><input type="radio" name="plan" value="pro" /> Pro</label>
</fieldset>

#Keyboard Navigation

Essential keys:

  • Tab - Next focusable element
  • Shift + Tab - Previous element
  • Enter - Activate link/button
  • Space - Activate button, check checkbox
  • Arrow keys - Navigate within component
  • Esc - Close dialog/menu

All functionality must be keyboard accessible!

#Focus Management

css
/* Never do this */
*:focus {
 outline: none;
}
 
/* Custom focus style */
button:focus {
 outline: 2px solid #0066cc;
 outline-offset: 2px;
}
 
/* Better - focus-visible (keyboard only) */
button:focus-visible {
 outline: 2px solid #0066cc;
 outline-offset: 2px;
}

#ARIA Attributes

#Common Roles

html
<div role="button">Custom Button</div>
<div role="dialog">Modal</div>
<div role="navigation">Nav</div>
<div role="alert">Error message</div>
<div role="status">Loading...</div>
<div role="progressbar">Progress</div>

Catatan: Prefer semantic HTML over ARIA roles!

#Common Attributes

AttributeUsageExample
aria-labelLabel element<button aria-label="Close">×</button>
aria-labelledbyReference label<div aria-labelledby="title">
aria-describedbyExtra description<input aria-describedby="hint">
aria-hiddenHide from screen readers<span aria-hidden="true">✓</span>
aria-liveAnnounce changes<div aria-live="polite">
aria-expandedExpandable state<button aria-expanded="false">
aria-pressedToggle button<button aria-pressed="true">
aria-invalidInvalid input<input aria-invalid="true">
aria-requiredRequired field<input aria-required="true">
aria-disabledDisabled state<button aria-disabled="true">

#Live Regions

html
<!-- Polite - wait for pause -->
<div aria-live="polite">Message sent!</div>
 
<!-- Assertive - interrupt immediately -->
<div aria-live="assertive">Error occurred!</div>
 
<!-- Atomic - read entire region -->
<div aria-live="polite" aria-atomic="true">
 <p>3 new messages</p>
</div>

#Screen Reader Only Content

css
.sr-only {
 position: absolute;
 width: 1px;
 height: 1px;
 padding: 0;
 margin: -1px;
 overflow: hidden;
 clip: rect(0, 0, 0, 0);
 white-space: nowrap;
 border-width: 0;
}
html
<button>
 <span aria-hidden="true">×</span>
 <span class="sr-only">Close dialog</span>
</button>

#Skip Links

html
<body>
 <a href="#main" class="skip-link">Skip to main content</a>
 <header>...</header>
 <main id="main">...</main>
</body>
css
.skip-link {
 position: absolute;
 top: -40px;
 left: 0;
 background: #000;
 color: #fff;
 padding: 8px;
}
 
.skip-link:focus {
 top: 0;
}

#Touch Targets

css
/* Minimum 44×44px (WCAG AAA) */
.button {
 min-width: 44px;
 min-height: 44px;
 padding: 12px 24px;
}

#Custom Interactive Elements

html
<!-- Custom button -->
<div
 role="button"
 tabindex="0"
 onkeydown="handleKeyDown(event)"
 onclick="handleClick()">
 Custom Button
</div>
 
<script>
function handleKeyDown(e) {
 if (e.key === 'Enter' || e.key === ' ') {
  e.preventDefault();
  handleClick();
 }
}
</script>

Requirements:

  • role - Define semantics
  • tabindex="0" - Make focusable
  • Handle Enter and Space
  • Visual focus indicator

#Modal Dialog

html
<div
 role="dialog"
 aria-labelledby="dialog-title"
 aria-describedby="dialog-desc"
 aria-modal="true">
 
 <h2 id="dialog-title">Confirm Delete</h2>
 <p id="dialog-desc">Are you sure you want to delete this item?</p>
 
 <button onclick="confirmDelete()">Delete</button>
 <button onclick="closeDialog()">Cancel</button>
</div>

Best practices:

  • Trap focus inside modal
  • Return focus on close
  • Close on Esc
  • aria-modal="true"

#Media Accessibility

html
<!-- Video with captions -->
<video controls>
 <source src="video.mp4" type="video/mp4" />
 <track
  kind="captions"
  src="captions.vtt"
  srclang="id"
  label="Indonesian"
  default
 />
</video>
 
<!-- Audio with transcript -->
<audio controls>
 <source src="audio.mp3" type="audio/mpeg" />
</audio>
<details>
 <summary>Transcript</summary>
 <p>Full transcript here...</p>
</details>

#Testing Checklist

#Manual Testing

  • Unplug mouse, navigate with keyboard only
  • All features accessible via keyboard?
  • Focus indicators visible?
  • Logical tab order?
  • Can skip repetitive content?

#Screen Reader Testing

  • Test with NVDA (Windows) or VoiceOver (Mac)
  • All content announced properly?
  • Form labels read correctly?
  • Error messages announced?
  • Dynamic content announced?

#Automated Testing

bash
# Lighthouse (Chrome DevTools)
# DevTools → Lighthouse → Accessibility → Run
 
# axe DevTools (Browser extension)
# Install from Chrome/Firefox store
 
# Command line
npm install -g @axe-core/cli
axe https://yoursite.com

#Visual Testing

  • Color contrast sufficient (4.5:1)?
  • Text readable when zoomed 200%?
  • Touch targets at least 44×44px?
  • Forms have visible labels?
  • Error states visible?

#Kesalahan Umum

WrongCorrect
<div onclick><button>
Only placeholder, no labelLabel + placeholder
Removing :focus outlineCustom focus style
Low contrast (2:1)Sufficient contrast (4.5:1)
Color only for meaningColor + icon/text
Skipping heading levelsLogical hierarchy
Empty link textDescriptive link text
Auto-play video/audioUser-controlled media
Time limits without optionExtendable/disablable

#Testing Tools

#Browser Extensions

  • axe DevTools - Best automated testing
  • WAVE - Visual feedback overlay
  • Lighthouse - Built into Chrome
  • Accessibility Insights - Microsoft tool

#Color Contrast

  • WebAIM Contrast Checker
  • Contrast Ratio
  • Chrome/Firefox DevTools (built-in)

#Screen Readers

  • NVDA (Windows) - Free
  • VoiceOver (Mac/iOS) - Built-in
  • TalkBack (Android) - Built-in
  • JAWS (Windows) - Paid

#Validators

  • W3C Markup Validator
  • WAVE
  • Pa11y

#Quick Reference

#ARIA Live Regions

html
<div aria-live="polite">Status message</div>
<div aria-live="assertive" role="alert">Error!</div>

#Button States

html
<button aria-pressed="false">Toggle Off</button>
<button aria-pressed="true">Toggle On</button>
<button aria-expanded="false">Collapsed</button>
<button aria-expanded="true">Expanded</button>
<button disabled>Disabled Button</button>

#Progressive Enhancement

html
<!-- Works without JS -->
<details>
 <summary>Click to expand</summary>
 <p>Content here...</p>
</details>
 
<!-- Enhanced with JS if available -->
<script>
 // Add custom behavior
</script>

#Resources

  • WCAG Quick Reference
  • MDN Accessibility
  • WebAIM
  • A11y Project
  • Inclusive Components

#Remember

"The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect." — Tim Berners-Lee

Accessibility = Better UX for everyone! 🌐♿

Baca Cheat Sheet Lengkap

Login atau daftar akun gratis untuk membaca cheat sheet ini.

LoginDaftar Gratis
Share: