Adobe Experience Manager is an enterprise CMS used by large brands, banks, healthcare systems, and public-sector organizations, which means AEM sites are routinely subject to VPAT requests, procurement accessibility clauses, the European Accessibility Act, and EN 301 549. Adobe has invested in accessibility at the platform level: the AEM Core Components - the maintained library of authoring components such as Title, Text, Image, List, Navigation, Breadcrumb, Tabs, Carousel, and Accordion - are built to produce semantic, WCAG-aware markup with keyboard support and ARIA when used as intended. The trouble is that most production AEM sites do not rely solely on Core Components. Brand and agency teams build custom components on top of AEM, and those custom components are where accessibility is usually lost: div-based layouts with no landmarks, headings driven by a 'style' dropdown rather than real heading elements, and interactive widgets re-implemented without the keyboard and ARIA wiring that the Core Components already solved. The Digital Asset Manager (DAM) stores a description/alt field on every asset, but authors leave it blank, so informative images reach screen reader users as file names - and because the same asset is reused across many pages, one missing description multiplies. AEM Adaptive Forms can be configured with placeholder-only labels and validation that is not associated with the field that failed. The Carousel, Tabs, and Accordion components are accessible when configured correctly but are frequently overridden with custom styling or scripts that break their built-in keyboard handling and ARIA state. Experience Fragments and language copies make multilingual delivery easy but often ship with the wrong html lang attribute. The Style System lets authors pick visual styles that can drop color contrast below the minimum. This checklist focuses on the decisions - use Core Components or rebuild them, fill in DAM metadata, override form templates, keep language attributes correct - that determine whether an AEM site passes a WCAG 2.1 AA, EN 301 549, or EAA audit.

Common Accessibility Issues

critical

Custom Components Bypassing Core Components and Their Built-In Semantics

WCAG 1.3.1

AEM Core Components produce semantic, accessible markup - real headings, lists, navigation with landmarks, and figure/figcaption for images. Custom components built by brand or agency teams frequently throw that away in favor of generic <div> structures with no landmarks, headings chosen from a style dropdown rather than real heading elements, and no list or table semantics. The result is a page that looks designed but has no machine-readable structure for screen reader users.

How to fix:

Prefer the AEM Core Components wherever they fit; they already solve headings, landmarks, image semantics, and navigation. When a custom component is genuinely required, mirror the Core Components' semantics: emit a real heading element whose level the author controls, use nav/main/header/footer landmarks in the page template and Layout Container, and use lists and tables for list and tabular content. Review custom component HTL (Sightly) output with a screen reader before it goes into the component library.

Before
<!-- custom component HTL -->
<div class="cmp-promo">
  <div class="cmp-promo__title">${properties.title}</div>
  <div class="cmp-promo__body">${properties.text @ context='html'}</div>
</div>
After
<section class="cmp-promo" role="region" aria-labelledby="promo-${id}">
  <sly data-sly-element="${properties.headingLevel || 'h2'}">
    <span id="promo-${id}">${properties.title}</span>
  </sly>
  <div class="cmp-promo__body">${properties.text @ context='html'}</div>
</section>
critical

DAM Assets and Image Components With Missing Alt Text

WCAG 1.1.1

Every asset in the AEM DAM has a description/alt metadata field, and the Core Image Component can pull alt from the asset or take it per placement. Authors routinely leave the description blank, so informative images reach screen reader users as a rendition file name. Because one asset is reused across many pages, a single missing description can affect dozens of placements. The Image Component's decorative toggle is also misused, hiding informative images or exposing decorative ones.

How to fix:

Treat the asset description as required for informative images in the DAM, and write text that conveys the image's purpose rather than its file name. When the same asset means different things on different pages, override the alt per placement in the Image Component. Use the Image Component's 'decorative' option only for images that add no information, so they get an empty alt and are skipped by assistive technology. Build a DAM metadata check into the asset-onboarding workflow.

Before
<img src="/content/dam/site/hero.jpg/_jcr_content/renditions/web.jpg" alt="hero">
After
<img src="/content/dam/site/hero.jpg/_jcr_content/renditions/web.jpg"
     alt="Nurse reviewing a patient chart on a tablet at a bedside">
serious

Adaptive Forms With Placeholder-Only Labels and Unassociated Errors

WCAG 3.3.1

AEM Adaptive Forms can be authored with placeholder text in place of visible labels and with validation messages that are not programmatically tied to the field that failed. Placeholders disappear on focus and are not reliable labels, and a screen reader user who hits an error has no way to navigate to the broken field or hear the specific message. Multi-step Adaptive Forms can also fail to move focus or announce when a new panel loads.

How to fix:

Give every Adaptive Forms field a persistent, visible title (label) and avoid using the placeholder as the only label. Mark required fields so they expose required/aria-required. Configure validation so each error is associated with its field via aria-describedby and the field gets aria-invalid, and place the error summary in an aria-live region. On multi-step forms, move focus to the new panel's heading and announce step changes. Use the Adaptive Forms accessibility options and override field templates where the defaults fall short.

Before
<input type="text" name="ssn" placeholder="Social security number">
<div class="af-error">Required.</div>
After
<label for="ssn">Social security number <abbr title="required">*</abbr></label>
<input type="text" id="ssn" name="ssn" required aria-required="true"
       aria-invalid="true" aria-describedby="ssn-err">
<span id="ssn-err">Enter your 9-digit social security number.</span>
serious

Carousel, Tabs, and Accordion Components Broken by Custom Overrides

WCAG 4.1.2

The AEM Core Carousel, Tabs, and Accordion components ship with keyboard support and ARIA state (roles, aria-selected, aria-expanded, arrow-key handling). Teams frequently override them with custom CSS or replace their scripts, which strips the keyboard handling and leaves the ARIA attributes static or absent. Keyboard users then cannot reach panels, and screen reader users are not told which tab is selected or whether an accordion section is open. Auto-rotating carousels without a pause control are an additional failure.

How to fix:

Use the Core Components' built-in interactivity rather than reimplementing it, and restyle with CSS that does not remove the focus outline or the ARIA wiring. If a custom widget is unavoidable, follow the ARIA Authoring Practices patterns for tabs, carousel, and disclosure: manage roles and state, support arrow keys and Enter/Space, keep focus visible, and provide a pause/stop control for any auto-advancing carousel (2.2.2). Test each widget with the keyboard only and with a screen reader.

Before
<div class="tabs">
  <div class="tab active" onclick="show(0)">Overview</div>
  <div class="tab" onclick="show(1)">Pricing</div>
</div>
After
<div role="tablist" aria-label="Plan details">
  <button role="tab" aria-selected="true" id="t1" aria-controls="p1">Overview</button>
  <button role="tab" aria-selected="false" id="t2" aria-controls="p2" tabindex="-1">Pricing</button>
</div>
<div role="tabpanel" id="p1" aria-labelledby="t1">...</div>
moderate

Experience Fragments and Language Copies With Wrong Language Attributes

WCAG 3.1.1

AEM language copies and the Translation framework make multilingual delivery straightforward, but the rendered html lang attribute is often hard-coded to one language for every locale, and Experience Fragments reused across languages keep the source language's markup. Screen readers then pronounce translated content with the wrong voice and phonetics, which can make it unintelligible.

How to fix:

Drive the html lang attribute from the page's language (the /content/site/<lang> structure or the jcr:language property) so each locale outputs the correct value. When an Experience Fragment contains text in a different language from its host page, ensure the fragment carries its own lang attribute (3.1.2 Language of Parts). Verify the rendered lang value on each language version after publishing.

Before
<html lang="en"> <!-- same on every locale -->
After
<html lang="${currentPage.language.language}"> <!-- e.g. de, fr, ja -->
serious

Style System Choices Dropping Color Contrast Below the Minimum

WCAG 1.4.3

The AEM Style System lets authors apply predefined visual styles to components, and some of those styles - light text on light backgrounds, low-contrast 'subtle' button or badge styles, muted captions - fall below the 4.5:1 minimum for normal text or 3:1 for large text and meaningful UI elements. Authors choosing styles by appearance have no warning that a choice fails contrast.

How to fix:

Audit every Style System option against the WCAG contrast minimums when the styles are defined, and remove or fix any that fail. Because authors pick from this list, the safest fix is to make every available style compliant rather than relying on authors to avoid the bad ones. Also confirm the design system's focus styles meet 3:1 against adjacent colors and are not removed by any style. Re-check after brand refreshes.

Before
.cmp-button--subtle { color: #9aa0a6; background: #e8eaed; }
After
.cmp-button--subtle { color: #1f1f1f; background: #e8eaed; } /* >= 4.5:1 */

Adobe Experience Manager-Specific Tips

  • Prefer the AEM Core Components wherever they fit - they already produce semantic markup, landmarks, image semantics, and accessible Tabs/Carousel/Accordion - and treat custom components as the place accessibility is most likely to be lost.
  • When a custom component is required, mirror the Core Components' semantics in HTL: an author-controlled heading level, real list/table elements, and landmarks in the page template and Layout Container.
  • Treat the DAM asset description/alt as required for informative images, override alt per placement when an asset means different things on different pages, and use the Image Component's decorative toggle only for truly decorative images.
  • Restyle Tabs, Carousel, and Accordion with CSS only; do not replace their scripts in ways that strip the built-in keyboard handling and ARIA state, and give auto-rotating carousels a pause control.
  • Configure Adaptive Forms with visible labels, required indicators, aria-describedby error association, and focus/announcement handling on multi-step panels; override field templates where defaults fall short.
  • Drive the html lang attribute from the page language so each locale and language copy outputs the correct value, and mark foreign-language passages inside Experience Fragments.
  • Audit every Style System option for color contrast when it is defined, so authors can only pick compliant styles, and document Core vs custom component coverage for VPAT and EAA evidence.

axe DevTools

Deque's browser-based scanner runs axe-core against rendered AEM pages and reports WCAG-referenced issues across custom components, forms, and Style System output, helping distinguish Core Component output from where custom code breaks structure or contrast.

WAVE Browser Extension

WebAIM's free extension visually flags missing alt text, unlabeled form fields, heading-structure breaks, and contrast failures on the live page, which helps authors see the effect of empty DAM descriptions and Style System choices.

AEM WCM Core Components (GitHub)

The source and documentation for Adobe's maintained Core Components, including their accessibility behavior for Title, Image, Navigation, Tabs, Carousel, and Accordion - the reference for what accessible AEM markup should look like and what custom components must match.

AEM Accessibility: Where Failures Come From and How to Fix Them

Plugin / Tool LayerCommon FailureWhat WCAG 2.1 AA NeedsWhere to Fix It
Custom components 1.3.1 Div output bypassing Core Component semanticsReal headings, landmarks, list/table semanticsCustom HTL mirroring Core Components
DAM / images 1.1.1 Asset description blank; decorative toggle misusedDescriptive alt; empty alt for decorativeDAM metadata + per-placement override
Adaptive Forms 3.3.1 Placeholder labels, errors not tied to fieldsReal labels, aria-describedby error linkForm config + field template overrides
Tabs / Carousel / Accordion 4.1.2 / 2.2.2 Custom overrides strip keyboard + ARIA stateRoles/state, keyboard support, carousel pauseUse Core Components; restyle via CSS only
Style System 1.4.3 Selectable styles below contrast minimumAll options meet 4.5:1 / 3:1Audit styles when defined

Frequently Asked Questions

Are AEM Core Components accessible?

Yes - Adobe builds the AEM Core Components to produce semantic, WCAG-aware markup with keyboard support and ARIA when used as intended, which is why they are the recommended foundation. The accessibility problems on most AEM sites come from custom components built on top of AEM, from empty DAM alt text, from Adaptive Forms configured without real labels, and from custom overrides that strip the Core Components' built-in keyboard and ARIA behavior. This is general information, not legal advice.

Why do custom AEM components cause accessibility failures?

Custom components built by brand or agency teams replace the semantic markup the Core Components provide with generic divs, headings chosen from a style dropdown, and interactive widgets re-implemented without the keyboard and ARIA wiring the Core Components already solved. Because the custom component library is reused across the whole site, one inaccessible component can fail WCAG on every page that uses it. Mirroring the Core Components' semantics in custom HTL is the fix.

What standards should an AEM site target?

The practical working target is WCAG 2.1 AA, which underpins the European Accessibility Act, EN 301 549 (used for EU public-sector and procurement), ADA expectations in the US, and most enterprise procurement requirements. Enterprise buyers frequently also request a VPAT or accessibility conformance report. WCAG 2.2 adds criteria such as focus appearance, target size, and redundant entry that increasingly appear in audits. This is general information, not legal advice.

Further Reading

Other CMS Checklists