Test Page Notice
This page contains intentionally problematic accessibility patterns for testing and demonstration purposes only.
Do not use these examples in production websites. They violate accessibility guidelines and best practices.
This page is designed to work with the Accessibility Visualizer browser extension to help developers identify and understand accessibility issues.
Test Examples
This page serves as a testing ground for the Accessibility Visualizer browser extension. It contains various examples of web elements with accessibility issues to demonstrate how the extension highlights problems and provides information about accessible alternatives.
Categories
Headings
Headings provide a hierarchical structure to web content, helping users understand page organization and navigate efficiently. Assistive Technologiess use headings as navigation landmarks, so proper heading structure helps users to reach their objective content.
Heading Hierarchy
Heading hierarchy demonstration
This example shows the standard HTML heading hierarchy from h1 to h6, plus a custom heading using ARIA attributes. Notice how heading levels should follow a logical order.
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Custom Heading (role="heading" aria-level="7")
Best practices:
- Start with h1 for main page title
- Don't skip heading levels (h1 → h3 without h2)
- Use headings to create a logical content outline first
Problematic Headings
Problematic heading: Skipped level
❌ This example shows incorrect heading hierarchy where h4 appears without h2 or h3. This breaks the logical document structure.
Main Title (h1)
Skipped to h4 - This is problematic!
This h4 should be h2 to maintain proper hierarchy.
Empty heading
❌ Heading element with no text content. Assistive technology users cannot predict the content about the part with this heading.
This h6 element contains no text and provides no value to users.
Images
Images are a fundamental part of web content that must be accessible to users of assistive technologies such as screen readers. The following examples demonstrate various approaches to image accessibility, including both correct implementations and common mistakes.
<img> element
The img element requires proper alternative text (alt) to be accessible.
Image with alt text
Properly accessible image with descriptive alternative text. This is the correct way to make images accessible.
Image with alt and title
Image with both alt text and title attribute. The title attribute shows as a tooltip. Using tooltips can be problematic as users may not be aware of their existence or may not be able to see them at all.
Image without alt attribute
❌ Missing alt attribute - this is problematic! Screen readers will announce the filename or 'image' instead of meaningful content.
Image with title but no alt
❌ Alternative texts should be specified via alt attribute.
Decorative image with empty alt
⚠️ Empty alt attribute indicates that the image does not contain any information. It is important to consider carefully wheter or not there is really any informaiton that users should know.
Decorative image with empty alt and title
Decorative image marked properly with empty alt, assistive technologies may ingore it. However, the tooltip show by title attribute is only visible to mouse users, which is inappropriate.
Image with aria-hidden
Image hidden from assistive technologies using aria-hidden. This is another way to mark decorative images, though empty alt is more common.
<svg> element
Recently often used for icons. SVG elements can be made accessible using techniques including title elements, aria-label, and role attributes.
SVG with title element
⚠️ Using title element in svg element is the standard way to make SVG content accessible. But some screen readers and browsers may not support it well. It is better to set role to img.
SVG with title element and role=img
✅ Using title element to provide an accessible name and role=img to explicitly indicate it is an image. This makes it clear that the graphic is an image.
SVG without title element
❌ SVG without title or other accessibility attributes. Screen reader users cannot understand what this graphic represents.
SVG with aria-hidden
SVG hidden from assistive technologies. Use this for decorative graphics that don't convey any information.
SVG with aria-label
⚠️ SVG with aria-label attribute. But some screen readers and browsers may not support it well. It is better to set role to img.
SVG with img role
✅ SVG with explicit img role and aria-label. This clearly indicates the SVG is an image and provides its accessible name.
SVG with presentation role
SVG marked as decorative using role='presentation'. This removes semantic meaning from the SVG.
role="img"
Use role="img" to convey non-img elements as images. An accessible name must be provided using aria-label or aria-labelledby.
role="img" with aria-label
✅ Proper use of role='img' with descriptive aria-label. This technique is useful for text-based graphics or emoji.
role="img" without aria-label
❌ Missing accessible name. Screen readers may announce 'image' or read out the raw text characters, causing confusion.
Links
Links are essential navigation elements that allow users to move between pages or sections. They must be properly implemented to ensure keyboard accessibility and clear communication to assistive technology users.
<a> Element
Standard link with href
✅ Properly implemented link with href attribute. This is keyboard accessible and clearly identified by screen readers as a navigation element.
Anchor without href attribute
❌ Anchor element without href attribute. It does not function as a link. Even if JavaScript is used to implement link behavior, it lacks keyboard accessibility and proper communication to assistive technologies.
example 2 (under construction)
Sometimes an anchor without href is used to indicate a place that will become a link later. Assistive technologies will treat it as plain text.
Link Role
Element with role="link"
⚠️ Link-like element using role="link", tabindex="0", and JavaScript to mimic link behavior. This is insufficient as a link implementation, as it lacks features, for example 'Open in new tab' option in context menu (right-click) or other ways.
Link Variations
Link with target='_blank'
⚠️ Link that opens in a new window/tab. This can increase user burden by forcing new windows/tabs to open. Consider whether this is truly necessary.
Icon Links
Link with only an icon
❌ Link containing only an icon without text or accessible name. Screen readers may read parts of the URL, leaving users unable to understand the link's purpose or destination.
Link with icon and aria-label
✅ Icon link with proper role='img' and aria-label on the SVG element. This provides accessible naming for the icon while maintaining proper semantic structure.
Link with icon and text
✅ Link with an icon accompanied by text that conveys the same meaning. The icon is marked as decorative with aria-hidden='true'.
Buttons
Buttons are interactive elements that users activate to perform actions. They must convey the purpose of themselves what it does when pushed, to assistive technologies. They must be accessible to keyboard users and assistive technologies. The following examples show various button implementations and common accessibility issues.
<button> Element
Standard button element
✅ The most accessible way to create a button. Semantic HTML buttons are keyboard accessible by default and announced correctly by assistive technologies.
Button with aria-hidden="true"
❌ Button hidden from assistive technologies. While it remains visible and operable visually and via keyboard, users of assistive technologies may not be able to find or operate it.
Button containing image with alt text
✅ Button with an image that has proper alt text. The alt text becomes the accessible name of the button.
Button containing image without alt text
❌ Button with an image missing alt text. Assistive technologies cannot determine what this button does, making it inaccessible.
Button Role
Div with button role and tabindex
⚠️ A div element with role='button' and tabindex='0', along with JavaScript handling both click and key events. This is a complex implementation and it's better to use a button element.
Div as button without role
❌ Custom button missing role='button'. Assistive technologies won't identify this as an interactive element, making it inaccessible.
Div as button without tabindex
❌ Custom button that can't receive keyboard focus. Keyboard users won't be able to activate this button.
Input Elements
Input type="button"
✅ Input element with type="button". The value attribute provides the visible label and accessible name.
Input type="button" without value
❌ Input button without a value attribute has no accessible name. Assistive technologies cannot identify what this button does.
Input type="submit"
✅ Submit button with proper value. The value attribute provides the visible label and accessible name.
Input type="submit" without value
Submit button without explicit value. Browsers provide a default label ('Submit' etc), but it's better to be explicit.
Input type="reset"
✅ Reset button that clears form data. The value attribute provides the visible label and accessible name.
Input type="reset" without value
Reset button without explicit value. Browsers provide a default accessible name ('Reset' etc), but it's better to be explicit.
Input type="image" with alt text
✅ Image button by input element with type="image". The alt attribute provides the accessible name for this submit button type.
Input type="image"
❌ Image input without alt text. This creates an inaccessible submit button since assistive technologies can't determine its purpose.
Summary Element
Summary element
✅ Summary element within details for creating disclosure widgets. Semantically correct and accessible by default.
Click Me
Details content revealed when summary is clicked.
details without summary
When details lacks a summary, browsers display a default label like 'Details'.
Details content revealed when summary is clicked.
Summary element without details
❌ Summary element used outside of details. This is invalid HTML.
Summary without accessible name
❌ Summary element with no text content or accessible name. Users won't know what this control does.
Details content that can't be properly accessed.
Form Controls
Form controls are interactive elements that allow users to input data. They must have proper labels and be accessible to assistive technologies and keyboard users. The following examples demonstrate both accessible implementations and common accessibility issues.
Text Inputs
Input without label
❌ Input without a label. Assistive technologies cannot convey the purpose of this field to users.
Input with proper label
✅ Text input with associated label using 'for' and 'id' attributes. This creates a programmatic relationship between label and input.
Input inside label
✅ An alternative method is to nest the input inside the label element. This works similarly to 'for/id' association.
Select Elements
Select without label
❌ Select element without label. Users cannot determine what this dropdown is for.
Select with proper label
✅ Select element with associated label. Assistive technologies can tell their users both the label and the current selection.
Textarea Elements
Textarea without label
❌ Textarea without label. Users cannot understand what content should be entered here.
Textarea with proper label
✅ Textarea with associated label. Clearly communicates the purpose of the text area to assistive technology users.
Checkboxes
Checkboxes with labels
✅ Properly labeled checkboxes. Each checkbox has a clear, accessible name.
Checkboxes without labels
❌ Checkboxes without proper labels. While there is text nearby, it isn't programmatically associated, making it hard for screen reader users to understand what each checkbox represents.
Custom styled checkbox with display: none
❌ Custom checkbox using 'display: none' which can remove the element from keyboard navigation and screen readers.
Radio Buttons
Radio buttons with labels
✅ Properly labeled radio buttons with shared name attribute. Forms a logical group that browsers and assistive technologies can interpret. Each option is named using label elements. The group itself is labeled using fieldset and legend elements.
Radio buttons without labels
❌ Radio buttons without proper labels. Text appears next to radios but isn't programmatically associated, making it inaccessible.
Radio buttons without name attribute
❌ Radio buttons without shared name attribute. These don't form a proper group, so both can be selected simultaneously.
Radio buttons with different name attributes
❌ Radio buttons with different name attributes don't form a logical group. Each acts as an independent radio button.
Single radio button
❌ If there's only one option, use a checkbox instead of a radio button. Users cannot uncheck a radio button once selected.
Label Issues
Orphaned label
⚠️ Label element not associated with any form control. It makses no sense.
Label with non-existent ID reference
⚠️ Label references an ID that doesn't exist. Is the ID you meant to reference incorrect?
The input with id="non-existent-input" doesn't exist in the document.
Input States
Required input
✅ Input with required attribute. Screen readers can announce that this field is required. Consider adding visual indicators and clear error messaging.
Read-only input
Read-only input that users cannot modify. Screen readers will announce this state. Useful for displaying non-editable information in form context.
Editable Elements
Contenteditable div without role
⚠️ Contenteditable div without proper role. While functional, screen readers may not announce it as a text input field.
Contenteditable div with role='textbox' and aria-labelledby
✅ Contenteditable div with proper textbox role and accessible labeling. Uses aria-labelledby to connect with the label element.
Contenteditable without label
❌ Contenteditable element without any label or accessible name. Screen readers cannot identify what this field is for.
Layout & Landmarks
Semantic HTML elements and ARIA landmarks help users understand page structure and navigate efficiently. These elements provide important context about different sections of content.
Semantic Sections
HTML landmark elements
✅ Proper use of landmark elements that provide clear structure and meaning to page content.
<header> - Page or section header <main> - Main content area
ARIA Landmarks
ARIA landmark roles
✅ ARIA landmark roles that provide the same navigation benefits as semantic HTML elements. Use when semantic HTML isn't available.
role="banner" - Equivalent to <header>role="main" - Equivalent to <main>role="complementary" - Equivalent to <aside>role="contentinfo" - Equivalent to <footer>
Generic Containers
Generic div containers without semantic meaning
❌ Using generic div elements for major page sections provides no semantic information to assistive technologies.
These divs provide no information about content purpose or page structure.
Section Elements
Section with accessible name
Section element with an accessible name becomes a region role and functions as a landmark.
About Our Services
This section references the heading's id attribute value in the section element's aria-labelledby attribute.
Section without accessible name
Section element without an accessible name does not function as a landmark.
About Our Services
This section merely places a heading without associating it.iFrame Elements
iFrame with title attribute
✅ iFrame with proper title attribute that describes the content. Essential for assistive technologies to understand what the frame contains.
iFrame without title attribute
❌ iFrame missing title attribute. Accessible technologies cannot determine what content the frame contains, making it inaccessible.
Dialog and Modal
Dialog element
Example of HTML dialog element. When opened with showModal(), it becomes a modal that traps focus and blocks interaction with background content.
Element with aria-modal='true'
✅ Custom modal implementation with proper focus management - traps focus inside the modal and returns focus to the opening button when closed.
Tables
Tables organize data in rows and columns and must be properly structured for screen readers to understand relationships between data.
Table Structure
Table with proper headers
✅ Well-structured table with th elements for headers and proper scope attributes. Screen readers can announce column/row relationships.
| Name | Age | City |
|---|---|---|
| John | 25 | New York |
| Jane | 30 | London |
Table without headers
❌ Table using only td elements without proper th headers. Screen readers cannot establish relationships between data.
| Name | Age | City |
| John | 25 | New York |
| Jane | 30 | London |
Table with row headers
✅ Table with both column headers and row headers using appropriate scope attributes for complex data relationships.
| Quarter | Sales | Profit |
|---|---|---|
| Q1 | $100K | $20K |
| Q2 | $150K | $30K |
Table with caption
✅ Table with caption element providing context about the table's purpose. Helps users understand what data the table contains.
| Name | Department |
|---|---|
| Alice | Engineering |
| Bob | Marketing |
ARIA Hidden
The aria-hidden attribute controls whether elements are exposed to assistive technologies. When properly used, it can hide decorative content, but when misused, it can make important content inaccessible.
Visible Content
Visible text with aria-hidden="false"
Text that is visible and explicitly exposed to assistive technologies. The aria-hidden="false" is usually unnecessary as elements are exposed by default.
This text is visually visible and can be read by screen readers.
Visible text with aria-hidden="true"
❌ Visually visible but inaccessible to assistive technologies. Screen reader users will miss out on the content.
Icons
Decorative icon with aria-hidden="true"
✅ Proper use of aria-hidden for decorative icons that don't convey essential information. The icon is hidden while the text remains accessible.
Important icon without aria-hidden
❌ The information conveyed by the icon is not made available to assistive technologies.
Accessible icon with proper labeling
✅ Example of providing meaning with aria-label. Visually an icon, but conveys information to assistive technologies via the aria-label.
Live Regions
Live regions announce dynamic content changes to screen readers. They're essential for providing feedback about status updates, errors, and other dynamic content that users need to be aware of immediately.
aria-live Attribute
aria-live='polite'
Polite live region that announces changes when the user is idle. Good for status updates that aren't urgent.
aria-live='assertive'
Assertive live region that immediately interrupts screen readers to announce changes. Use for critical alerts and errors.
Live Region Roles
role='status'
Status role provides advisory information that isn't critical. Equivalent to aria-live='polite'.
role='alert'
Alert role for important, time-sensitive information. Equivalent to aria-live='assertive'.
Output Element
<output> element
Output element for displaying calculation results or form output. Automatically has live region behavior.
aria-atomic Attribute
Live region with aria-atomic='true'
Live region where the entire content is announced when any part changes, rather than just the changed portion.
Problematic Live Regions
Dynamic content without live region
Content that changes dynamically but isn't marked as a live region. Screen readers won't announce these changes.
Screen readers won't announce the time update because this isn't a live region.
Live Region Priority Interactions
Polite and Assertive simultaneous updates
Demonstrates how assertive live regions interrupt polite ones. When both update simultaneously, the polite announcement may be suppressed.
Polite (should be announced)
Assertive (will interrupt)
Test behavior: Click "Update Both Simultaneously" and observe that the polite region's announcement may be suppressed by the assertive region. The Accessibility Visualizer extension shows this behavior by only displaying the assertive announcement when both regions update at the same time.
Sequential updates with different priorities
Demonstrates how assertive announcements can clear pending polite announcements from the queue.
Polite announcements
Assertive interruptions
Test behavior: Start the polite sequence to see 8 polite messages being displayed sequentially. Then click "Interrupt with Assertive" - the assertive message will be triggered after 3 seconds to avoid focusin clearing the live region display. Observe how the assertive announcement interrupts and clears the remaining polite messages.
aria-busy Suppression
Live region with aria-busy suppression
Demonstrates how aria-busy='true' suppresses live region announcements. When a region is marked as busy, content changes are not announced to screen readers.
Live region (will be suppressed when busy)
aria-busy status:
false
Test behavior: Click "Update Content" to see normal live region announcements. Then click "Toggle aria-busy" to mark the region as busy, and try "Update Content" again - the content will change but no announcement will be made. The Accessibility Visualizer extension respects aria-busy and will not display announcements for busy regions.
Continuously Updating Live Regions
Timer with polite announcements
Timer that updates every second with polite live region. Good for testing extension behavior with frequent updates.
Live counter with assertive announcements
Counter that auto-increments every 2 seconds with assertive live region. Useful for testing frequent interruptions.
Status updates with role='status'
Status messages that update every 3 seconds. Tests extension handling of role-based live regions with continuous updates.