Contentful is a headless CMS, which means it delivers content as structured JSON over an API and has no opinion about how that content is rendered on the page. Accessibility on a Contentful-powered site therefore has two very different failure modes: problems baked into the content model that make it impossible for editors to supply accessible content, and problems in the front-end framework (Next.js, Nuxt, Astro, SvelteKit, Remix, native mobile apps) that consumes the API and decides how to turn it into HTML. A site can have a perfect React component library and still fail WCAG because the content model makes the alt text field optional. A site can have an exemplary content model and still fail WCAG because the Rich Text renderer outputs divs where it should output headings. This checklist addresses both sides. With the European Accessibility Act now enforceable, organizations that use Contentful to power public websites, customer portals, or ecommerce front-ends serving European customers must ensure both the content model and the front-end that renders it meet WCAG 2.1 AA requirements. Contentful is widely used in the enterprise segment, which also places many of its customers under ADA and Section 508 obligations in the United States. This checklist covers content model accessibility (the shape of your data), rendering accessibility (how front-end code transforms that data into HTML), and editorial workflow (how your content team uses the Contentful web app to produce compliant content). Each item includes the relevant WCAG 2.1 success criterion and guidance you can apply in the content model, in Contentful's web app, and in your consuming front-end framework.

Common Accessibility Issues

critical

Image Asset Fields Without a Required Alt Text Field

WCAG 1.1.1

Contentful's native Asset type has a "Description" field that is often repurposed as alt text but is not marked required by default. Editors routinely upload images with no description, and front-end code falls back to the asset title (a filename) or omits the alt attribute entirely. Every image field on the site ships without accessible text alternatives.

How to fix:

In the Contentful web app, edit your Asset field appearance and mark the Description field as required. Alternatively, add a dedicated "altText" short-text field to any content type that references images and mark it required at the content type level. In your consuming front-end, read the alt text from the field you chose and never fall back to the filename. For explicitly decorative images, add a Boolean "decorative" field and output alt="" when it is true.

Before
function Image({ asset }) {
  return <img src={asset.fields.file.url} />;
}
After
function Image({ asset, decorative = false }) {
  const alt = decorative ? "" : (asset.fields.description || "");
  if (!decorative && !alt) {
    console.warn(`Missing alt text for asset ${asset.sys.id}`);
  }
  return (
    <img
      src={asset.fields.file.url}
      width={asset.fields.file.details.image.width}
      height={asset.fields.file.details.image.height}
      alt={alt}
      {...(decorative ? { role: "presentation" } : {})}
    />
  );
}
critical

Rich Text Renderer Outputting Divs Instead of Semantic Elements

WCAG 1.3.1

The official @contentful/rich-text-react-renderer and equivalent packages for other frameworks produce semantic HTML by default, but many teams customize the renderers and accidentally replace paragraphs with divs, lose heading hierarchy, or drop list markup. Screen reader users navigating by heading, list, or landmark lose all structure and the Rich Text field becomes an unbroken wall of text.

How to fix:

When customizing Rich Text renderers, keep the semantic mapping intact: BLOCKS.HEADING_1 to h1, BLOCKS.HEADING_2 to h2, BLOCKS.PARAGRAPH to p, BLOCKS.UL_LIST to ul, BLOCKS.OL_LIST to ol, BLOCKS.LIST_ITEM to li, INLINES.HYPERLINK to a. Only add styling classes, do not change the element type. Restrict which heading levels editors can insert so they cannot produce an h1 in a field that renders inside a page section.

Before
const options = {
  renderNode: {
    [BLOCKS.PARAGRAPH]: (node, children) => <div className="copy">{children}</div>,
    [BLOCKS.HEADING_2]: (node, children) => <div className="h2">{children}</div>,
  },
};
After
const options = {
  renderNode: {
    [BLOCKS.PARAGRAPH]: (node, children) => <p className="copy">{children}</p>,
    [BLOCKS.HEADING_2]: (node, children) => <h2 className="h2">{children}</h2>,
    [BLOCKS.HEADING_3]: (node, children) => <h3 className="h3">{children}</h3>,
    [INLINES.HYPERLINK]: (node, children) => (
      <a href={node.data.uri} {...(isExternal(node.data.uri) ? { rel: "noopener" } : {})}>{children}</a>
    ),
  },
};
critical

Embedded Video and Audio Assets Without Captions or Transcripts

WCAG 1.2.2

Contentful stores video and audio files as assets or references to external platforms (Vimeo, Wistia, YouTube). There is no field on the default asset type to hold captions, transcripts, or audio descriptions. Many Contentful sites ship video players with autoplaying media and no captions, which fails WCAG 1.2.2 Captions (Prerecorded) and leaves Deaf and hard-of-hearing users unable to access the content.

How to fix:

Add a "captionsFile" reference field (to a VTT or SRT asset) and a "transcript" long text field on any content type that references a video. In the front-end, pass the captions file to the video element via a track element and link to the transcript below the player. For embedded external videos, require editors to supply captions on the source platform before the video can be referenced in Contentful (enforce via editorial guidelines and a validation workflow).

serious

Link Fields With Validation That Allows Empty or Generic Link Text

WCAG 2.4.4

Contentful content types often include short-text fields for link labels ("ctaText", "linkText") without any validation. Editors enter "Click here", "Read more", or "Learn more", which fails WCAG 2.4.4 Link Purpose (In Context) when screen reader users list links out of context. The weak validation also permits empty strings that produce invisible, keyboard-focusable links.

How to fix:

Configure validation on link text fields: set minimum length to 4 characters, add a regex or custom validation that rejects common generic phrases ("click here", "read more", "learn more", "here"), and make the field required. For CTAs that must use a consistent phrase, bind the link text to the linked entry's title or a computed field that includes descriptive context (e.g., "Read the 2026 report on accessibility lawsuits").

serious

Locales Without Corresponding Lang Attribute on Rendered Markup

WCAG 3.1.1

Contentful supports multi-locale content out of the box, but consuming front-ends frequently forget to set the lang attribute on the html element (or on fragments) to match the locale requested from the Contentful API. Screen readers then read French or Japanese content with an English speech synthesizer, producing incomprehensible audio.

How to fix:

In your front-end, determine the locale of the content being rendered from the Contentful request and set the lang attribute on the html element accordingly (for example lang="fr" for French content). For individual fields in a different language within a page, wrap them in a span or div with a lang attribute that matches. Use the Contentful Content Delivery API's locale parameter to request the correct content rather than relying on client-side detection.

Before
<!-- Next.js _document.tsx -->
<Html>
  <Head />
  <body>
    <Main />
    <NextScript />
  </body>
</Html>
After
<!-- Next.js _document.tsx -->
<Html lang={locale ?? "en"}>
  <Head />
  <body>
    <Main />
    <NextScript />
  </body>
</Html>
moderate

Preview API Exposing Unpublished Content Without Accessibility Checks

WCAG 1.1.1

Contentful's Preview API serves draft content to preview environments. Editors review copy and layout in preview but rarely run accessibility tools against preview URLs, which means alt text issues, heading hierarchy problems, and missing form labels are only caught after publication, when they affect real users.

How to fix:

Integrate an automated accessibility check into your preview workflow. Options include adding axe-core to your preview environment and surfacing violations in a floating debug panel, running Lighthouse against preview URLs from your CI pipeline, or using a service like Deque Axe Monitor that crawls preview environments on a schedule. Configure the preview URL in Contentful's app settings to link directly to the front-end preview, and document the expected review workflow for editors.

moderate

App Framework Plugins With Inaccessible Editor UI

WCAG 2.1.1

Contentful's App Framework lets third parties and in-house teams build custom editor UIs for specific fields. These custom apps often do not follow Contentful's Forma 36 design system and ship with keyboard traps, missing labels, and inaccessible dropdowns. Content editors with disabilities cannot use the affected fields.

How to fix:

When building custom apps, import Contentful's Forma 36 React component library, which handles keyboard navigation, ARIA attributes, and focus management for common UI patterns. Test every custom app with a keyboard only and with a screen reader before shipping. For third-party apps, raise accessibility issues with the vendor and consider replacing apps that consistently fail WCAG with alternatives or custom builds.

Contentful-Specific Tips

  • Bake accessibility requirements into content types, not documentation. A required alt text field catches every editor; a style guide catches only the editors who read it. Set validation rules (required, minimum length, regex) on fields that affect accessibility.
  • Expose accessibility metadata on all reference content, not just assets. A "Hero" content type that references an image should have its own "altText" override field so editors can write alt text tuned to the context the image appears in, rather than the generic asset description.
  • Prefer Contentful's Rich Text field over Markdown for long-form content. Rich Text is a structured AST with defined semantic meaning for each node, while Markdown is a string that your renderer re-parses on every request. The structured Rich Text model is far easier to render accessibly.
  • Use Contentful's Content Delivery API "include" parameter to fetch linked accessibility assets (captions, transcripts) in the same request as the primary content. This avoids front-end code that forgets to load accessibility assets separately and ships pages with the video but not the caption file.
  • Run axe-core against rendered pages in your CI pipeline, not against Storybook alone. Rendering a component in isolation masks heading hierarchy violations, landmark problems, and locale mismatches that only appear when real Contentful data flows through the page template.

Forma 36 Design System

Contentful's official React component library for building App Framework integrations. Components include built-in keyboard navigation, ARIA attributes, and focus management that match the Contentful web app experience. Using Forma 36 avoids reinventing accessibility features in custom editor UIs.

axe DevTools

A browser extension and CI tool for automated WCAG testing. Indispensable for catching Rich Text rendering bugs, missing alt text propagation, and locale mismatches in Contentful-driven front-ends before they reach production.

@contentful/rich-text-react-renderer

The official Contentful renderer for Rich Text fields in React. Produces semantic HTML by default. Customize it carefully to avoid replacing semantic elements with divs, which silently breaks assistive technology support.

Further Reading

Other CMS Checklists