50+ HTML5 Accessibility Interview Questions 2025: ARIA, WCAG & Semantic HTML

·15 min read
html5interview-questionsaccessibilitya11yfrontend

Over 1 billion people worldwide live with some form of disability, and web accessibility lawsuits in the US have increased 300% since 2018. Yet 96% of home pages have detectable WCAG failures. This guide covers the accessibility questions you'll face in frontend interviews, from semantic HTML basics to complex focus management patterns.

Table of Contents

  1. Accessibility Fundamentals Questions
  2. Semantic HTML Questions
  3. ARIA Questions
  4. Keyboard Navigation Questions
  5. Form Accessibility Questions
  6. Focus Management Questions
  7. Testing and Compliance Questions
  8. Quick Reference

Accessibility Fundamentals Questions

These questions test your understanding of web accessibility principles and why they matter.

What is web accessibility and why does it matter?

Web accessibility means building websites that everyone can use, including people with visual, hearing, motor, or cognitive disabilities. Different users need different accommodations: blind users rely on screen readers that read content aloud, low-vision users need zoom and high contrast, deaf users need captions and transcripts, motor-impaired users navigate with keyboards only, and cognitively impaired users need clear language and consistent layouts.

Beyond ethics, accessibility is often legally required. ADA lawsuits against inaccessible websites are increasing, and it also improves SEO since search engines rely on the same semantic structure that screen readers use.

What are the WCAG guidelines and their conformance levels?

WCAG (Web Content Accessibility Guidelines) is the international standard for web accessibility. It organizes requirements into three conformance levels that build on each other.

Level A is the minimum—must-fix issues like alt text for images and keyboard access. Level AA is the standard target for most websites, including color contrast ratios of 4.5:1 for normal text and the ability to resize text to 200%. Level AAA is the highest level, including requirements like sign language interpretation for video and contrast ratios of 7:1.

Most legal requirements and best practices target WCAG 2.1 Level AA compliance.

What is WCAG Level AA and what does it require?

WCAG AA is the standard compliance target that most organizations aim for. The key requirements include color contrast of 4.5:1 for normal text and 3:1 for large text, content that works at 200% zoom, all functionality accessible via keyboard, clear focus indicators, logical heading structure, proper form labels with error identification, adjustable time limits, and multiple ways to find pages with consistent navigation.

Level A covers the minimum baseline like alt text, while AAA represents the ideal standard including features like sign language for video content.


Semantic HTML Questions

Semantic HTML is the foundation of accessibility. These questions test whether you understand why element choice matters.

What is semantic HTML and why is it important for accessibility?

Semantic HTML uses elements that describe their meaning—like header, nav, main, article, and button—rather than generic divs and spans. Screen readers use these elements to help users navigate and understand page structure. A native button element is automatically focusable and keyboard-accessible; a div styled as a button is not.

Semantic HTML also improves SEO, code readability, and reduces the need for ARIA attributes. When you use the right element, you get accessibility features for free.

How does semantic HTML compare to div-based markup?

The difference is dramatic for screen reader users. Consider this comparison:

<!-- BAD: Div soup - no meaning to screen readers -->
<div class="header">
  <div class="nav">
    <div class="nav-item" onclick="goHome()">Home</div>
    <div class="nav-item" onclick="goAbout()">About</div>
  </div>
</div>
<div class="content">
  <div class="article">
    <div class="title">Article Title</div>
    <div class="text">Article content...</div>
  </div>
</div>
 
<!-- GOOD: Semantic HTML - meaningful to everyone -->
<header>
  <nav aria-label="Main navigation">
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/about">About</a></li>
    </ul>
  </nav>
</header>
<main>
  <article>
    <h1>Article Title</h1>
    <p>Article content...</p>
  </article>
</main>

The semantic version gives screen readers landmarks to navigate, proper link behavior, and heading structure. The div version is just a wall of text.

Why should you use a native button element instead of a styled div?

A native button element provides accessibility features automatically: it's focusable, responds to Enter and Space keys, and is announced as "button" by screen readers. A div styled as a button has none of these features.

<!-- BAD: Div pretending to be a button -->
<div class="btn" onclick="submit()">Submit</div>
<!-- Problems: Not focusable, no keyboard support, not announced as button -->
 
<!-- GOOD: Native button element -->
<button type="submit">Submit</button>
<!-- Benefits: Focusable, Enter/Space work, announced as "Submit, button" -->
 
<!-- If you MUST use a div (rare), add accessibility: -->
<div
  role="button"
  tabindex="0"
  onclick="submit()"
  onkeydown="if(event.key === 'Enter' || event.key === ' ') submit()"
>
  Submit
</div>
<!-- But why do all this when <button> does it automatically? -->

The lesson is clear: use native HTML elements whenever possible.

How do you make images accessible?

Image accessibility depends on the image's purpose. Informative images need descriptive alt text that conveys meaning, not appearance. Decorative images should have empty alt text so screen readers skip them. Complex images need extended descriptions.

<!-- Informative image - describe the meaning -->
<img
  src="chart.png"
  alt="Sales increased 50% from Q1 to Q2 2024"
 />
 
<!-- Decorative image - empty alt -->
<img src="decorative-border.png" alt="" />
 
<!-- Complex image - extended description -->
<figure>
  <img
    src="complex-chart.png"
    alt="Quarterly sales comparison"
    aria-describedby="chart-desc"
   />
  <figcaption id="chart-desc">
    Q1: $1M, Q2: $1.5M (50% increase), Q3: $1.8M, Q4: $2.1M.
    Total annual growth: 110%.
  </figcaption>
</figure>
 
<!-- Icon button - aria-label for meaning -->
<button aria-label="Close dialog">
  <svg aria-hidden="true"><!-- X icon --></svg>
</button>

Never use "image of" or "picture of" in alt text—screen readers already announce it's an image.


ARIA Questions

ARIA can enhance or harm accessibility depending on how it's used. These questions test your understanding of when and how to apply it.

What is ARIA and when should you use it?

ARIA (Accessible Rich Internet Applications) is a set of attributes that make web content more accessible. It includes roles (like role="button"), states (like aria-expanded), and properties (like aria-label).

The first rule of ARIA is: don't use ARIA if you can use native HTML. ARIA should fill gaps when HTML isn't enough—like aria-label for icon buttons or aria-live for dynamic updates. Incorrect ARIA is worse than no ARIA because it can confuse screen readers.

<!-- DON'T: Using ARIA when HTML works -->
<div role="button" tabindex="0">Click me</div>
 
<!-- DO: Use native HTML -->
<button>Click me</button>
 
<!-- DON'T: ARIA label on element with visible text -->
<button aria-label="Submit form">Submit</button>
 
<!-- DO: Just use the visible text -->
<button>Submit form</button>

When is ARIA actually necessary?

ARIA becomes necessary when you're building custom widgets that don't have native HTML equivalents, or when you need to communicate dynamic changes to screen readers.

<!-- Icon-only button needs label -->
<button aria-label="Search">
  <svg aria-hidden="true"><!-- magnifying glass --></svg>
</button>
 
<!-- Custom tabs widget -->
<div role="tablist" aria-label="Product information">
  <button role="tab" aria-selected="true" aria-controls="panel-1">
    Description
  </button>
  <button role="tab" aria-selected="false" aria-controls="panel-2">
    Reviews
  </button>
</div>
<div role="tabpanel" id="panel-1">Description content</div>
<div role="tabpanel" id="panel-2" hidden>Reviews content</div>
 
<!-- Live region for dynamic updates -->
<div aria-live="polite" aria-atomic="true">
  <!-- Screen reader announces when content changes -->
  Item added to cart
</div>
 
<!-- Loading state -->
<button aria-busy="true" disabled>
  <span aria-hidden="true">Loading...</span>
  <span class="sr-only">Please wait, submitting form</span>
</button>

What is the difference between aria-label, aria-labelledby, and aria-describedby?

These three attributes serve different purposes for providing accessible names and descriptions.

aria-label provides text directly as the accessible name—use it when there's no visible text, like icon buttons. aria-labelledby references another element's ID whose text becomes the accessible name—use it when visible text exists elsewhere. aria-describedby references additional descriptive text that supplements the name, like hints or error messages—it's read after the name and role.

The priority order is: aria-labelledby > aria-label > native text content.

<!-- aria-label: Accessible name when no visible text -->
<button aria-label="Close">×</button>
 
<!-- aria-labelledby: Reference another element as label -->
<dialog aria-labelledby="dialog-title">
  <h2 id="dialog-title">Confirm Delete</h2>
</dialog>
 
<!-- aria-describedby: Additional description -->
<input type="email" aria-describedby="email-hint">
<p id="email-hint">We'll never share your email</p>
 
<!-- aria-expanded: Toggle state -->
<button aria-expanded="false" aria-controls="menu">Menu</button>
<ul id="menu" hidden>...</ul>
 
<!-- aria-hidden: Hide from screen readers -->
<span aria-hidden="true">★★★☆☆</span>
<span class="sr-only">3 out of 5 stars</span>
 
<!-- aria-live: Announce dynamic changes -->
<div aria-live="assertive">Error: Invalid email</div>
<div aria-live="polite">3 items in cart</div>

How do you handle dynamic content for screen readers?

Use ARIA live regions to announce content changes. aria-live="polite" announces when the user is idle—good for status updates like cart counts. aria-live="assertive" interrupts immediately—use sparingly for critical errors.

Add aria-atomic="true" if the entire region should be re-read on any change, not just the changed portion.

<!-- Status messages -->
<div aria-live="polite">
  {{ cartItemCount }} items in cart
</div>
 
<!-- Error messages -->
<div aria-live="assertive" role="alert">
  Form submission failed: {{ errorMessage }}
</div>

Keyboard Navigation Questions

Keyboard accessibility is essential for users who can't use a mouse. These questions test your implementation skills.

How do you ensure keyboard accessibility?

Keyboard accessibility requires several key practices. All interactive elements must be focusable—use native elements or tabindex="0". Focus order should follow visual order, so don't rearrange elements with CSS or JavaScript without updating tab order. Focus must be visible—never use outline: none without providing an alternative. There should be no keyboard traps, meaning users can always tab out of any component.

Test by navigating your entire site using only Tab, Shift+Tab, Enter, Space, and arrow keys.

Skip links let keyboard users bypass repetitive navigation to reach main content quickly. They should be the first focusable element on the page and become visible when focused.

<!-- First element in body - skip to main content -->
<a href="#main-content" class="skip-link">
  Skip to main content
</a>
 
<header>
  <!-- Long navigation menu -->
</header>
 
<main id="main-content" tabindex="-1">
  <!-- tabindex="-1" allows programmatic focus -->
</main>
 
<style>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  padding: 8px;
  background: #000;
  color: #fff;
  z-index: 100;
}
 
.skip-link:focus {
  top: 0;  /* Visible when focused */
}
</style>

How should you style focus indicators?

Focus indicators must be visible for keyboard users. Never remove them without providing an alternative. Modern CSS allows showing focus styles only for keyboard users.

/* BAD: Removing focus indicator */
*:focus {
  outline: none;  /* NEVER do this without replacement */
}
 
/* GOOD: Custom focus indicator */
*:focus {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}
 
/* BETTER: Only for keyboard users */
*:focus:not(:focus-visible) {
  outline: none;
}
 
*:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}

What keyboard behaviors should custom widgets support?

Different widget types have expected keyboard patterns. Buttons should respond to Enter and Space. Menus should support arrow keys for navigation, Home and End for jumping to first and last items, and Escape to close.

// Buttons: Enter and Space
button.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    button.click();
  }
});
 
// Menus: Arrow keys
menu.addEventListener('keydown', (e) => {
  const items = menu.querySelectorAll('[role="menuitem"]');
  const current = Array.from(items).indexOf(document.activeElement);
 
  switch (e.key) {
    case 'ArrowDown':
      e.preventDefault();
      items[(current + 1) % items.length].focus();
      break;
    case 'ArrowUp':
      e.preventDefault();
      items[(current - 1 + items.length) % items.length].focus();
      break;
    case 'Home':
      e.preventDefault();
      items[0].focus();
      break;
    case 'End':
      e.preventDefault();
      items[items.length - 1].focus();
      break;
    case 'Escape':
      closeMenu();
      break;
  }
});

Form Accessibility Questions

Forms are where accessibility issues frequently appear. These questions cover proper labeling and error handling.

How do you properly label form inputs?

Every form input needs an associated label. You can use explicit association with for and id attributes, or implicit association by wrapping the input in a label element.

<!-- BAD: No label association -->
<input type="email" placeholder="Email">
 
<!-- GOOD: Explicit label -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">
 
<!-- ALSO GOOD: Implicit label -->
<label>
  Email address
  <input type="email" name="email">
</label>
 
<!-- Error messages -->
<label for="password">Password</label>
<input
  type="password"
  id="password"
  aria-describedby="password-error password-requirements"
  aria-invalid="true"
>
<p id="password-requirements">Must be at least 8 characters</p>
<p id="password-error" role="alert">Password is too short</p>
 
<!-- Required fields -->
<label for="name">
  Name <span aria-hidden="true">*</span>
</label>
<input type="text" id="name" required aria-required="true">

When should you use fieldset and legend elements?

Use fieldset and legend to group related form inputs, especially radio buttons and checkboxes that share a common question or category.

<!-- Group related inputs -->
<fieldset>
  <legend>Shipping Address</legend>
 
  <label for="street">Street</label>
  <input type="text" id="street" name="street">
 
  <label for="city">City</label>
  <input type="text" id="city" name="city">
</fieldset>
 
<!-- Radio buttons always need fieldset -->
<fieldset>
  <legend>Preferred contact method</legend>
 
  <input type="radio" id="contact-email" name="contact" value="email">
  <label for="contact-email">Email</label>
 
  <input type="radio" id="contact-phone" name="contact" value="phone">
  <label for="contact-phone">Phone</label>
</fieldset>

Without fieldset, screen reader users hearing "Email" as a radio button option have no context about what question they're answering.


Focus Management Questions

Focus management is critical for dynamic interfaces like modals and single-page applications.

How do you make a modal dialog accessible?

Accessible modals require proper ARIA roles, focus management, and keyboard support. When a modal opens, focus must move inside it. Users should not be able to tab to elements behind the modal. Escape should close the modal, and focus should return to the trigger element when closed.

Here's a typical inaccessible modal and its problems:

<!-- BAD: Typical inaccessible modal -->
<div class="modal" style="display: block;">
  <div class="modal-content">
    <span class="close" onclick="closeModal()">×</span>
    <h2>Modal Title</h2>
    <p>Modal content</p>
  </div>
</div>

Problems: Focus doesn't move to modal when it opens, user can tab to elements behind the modal, Escape key doesn't close it, screen reader doesn't know it's a dialog, and close button isn't keyboard accessible.

How do you implement accessible focus management for modals?

The solution involves ARIA attributes for screen readers and JavaScript for focus trapping:

<!-- GOOD: Accessible modal -->
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
  aria-describedby="modal-desc"
>
  <h2 id="modal-title">Modal Title</h2>
  <p id="modal-desc">Modal content goes here.</p>
 
  <button onclick="closeModal()">Close</button>
</div>
// Focus management
function openModal() {
  const modal = document.querySelector('[role="dialog"]');
  const firstFocusable = modal.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
 
  // Store the element that opened the modal
  previouslyFocused = document.activeElement;
 
  // Show modal and move focus
  modal.style.display = 'block';
  firstFocusable.focus();
 
  // Trap focus inside modal
  modal.addEventListener('keydown', trapFocus);
 
  // Close on Escape
  document.addEventListener('keydown', handleEscape);
}
 
function closeModal() {
  const modal = document.querySelector('[role="dialog"]');
  modal.style.display = 'none';
 
  // Return focus to trigger element
  previouslyFocused.focus();
 
  // Clean up listeners
  modal.removeEventListener('keydown', trapFocus);
  document.removeEventListener('keydown', handleEscape);
}
 
function trapFocus(e) {
  if (e.key !== 'Tab') return;
 
  const modal = e.currentTarget;
  const focusable = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
  const first = focusable[0];
  const last = focusable[focusable.length - 1];
 
  if (e.shiftKey && document.activeElement === first) {
    e.preventDefault();
    last.focus();
  } else if (!e.shiftKey && document.activeElement === last) {
    e.preventDefault();
    first.focus();
  }
}
 
function handleEscape(e) {
  if (e.key === 'Escape') closeModal();
}

This is where many developers fail accessibility—focus management requires explicit handling that native HTML doesn't provide.


Testing and Compliance Questions

These questions assess whether you know how to verify your accessibility work.

How do you test for accessibility?

Effective accessibility testing combines multiple approaches. Automated tools like axe DevTools, Lighthouse, and WAVE provide quick scans but only catch 30-40% of issues. Keyboard testing involves navigating the entire site with Tab, Enter, Space, and arrow keys. Screen reader testing uses VoiceOver on Mac, NVDA on Windows, or ChromeVox. Zoom testing verifies content works at 200% zoom and text-only zoom. Color contrast checkers like WebAIM verify sufficient contrast ratios.

Manual testing is essential because automated tools can't catch many real-world issues like illogical focus order or confusing screen reader announcements.

How do you create screen reader only content?

Sometimes you need content that's hidden visually but available to screen readers. The .sr-only pattern positions content off-screen without using display: none (which hides from screen readers too).

/* Hide visually but keep accessible */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
 
/* Allow element to be focusable when navigated to */
.sr-only-focusable:focus {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
}

Use this for skip links, icon descriptions, or additional context that sighted users get visually.


Quick Reference

TaskSolution
Make element focusableNative element or tabindex="0"
Hide from screen readersaria-hidden="true"
Hide visually but keep accessible.sr-only CSS class
Label icon buttonaria-label="Action name"
Announce dynamic contentaria-live="polite" or "assertive"
Required fieldrequired + aria-required="true"
Error statearia-invalid="true" + aria-describedby
Expanded/collapsedaria-expanded="true/false"
Group related inputs<fieldset> + <legend>
Color contrast (AA)4.5:1 normal text, 3:1 large text

Ready to ace your interview?

Get 550+ interview questions with detailed answers in our comprehensive PDF guides.

View PDF Guides