Umbraco is a major open-source .NET content management system with particularly strong adoption in Europe, the United Kingdom, and Australia. Umbraco-powered sites include government portals, healthcare organizations, universities, and large ecommerce storefronts, most of which fall under the European Accessibility Act, the European Web Accessibility Directive, or equivalent national legislation. Because Umbraco outputs HTML through Razor views that developers write from scratch, accessibility is almost entirely determined by template code, document type configuration, and the discipline of the content team using the Umbraco backoffice. The Umbraco HQ team has invested significant effort into the backoffice accessibility itself, and version 13 and later ship with improved focus management, keyboard navigation, and ARIA support in the content editing interface. However, the public-facing front-end remains the developer's responsibility, and Block List and Block Grid editors introduce their own accessibility risks: an editor choosing the wrong block preset or heading level can produce a page that fails WCAG even on a well-built site. This checklist covers both the front-end (Razor views, partials, Block List and Block Grid rendering, form templates) and the editorial experience (document type configuration, backoffice usage, media library). Each item references the relevant WCAG 2.1 success criterion and includes Umbraco-specific remediation guidance using Razor, ModelsBuilder, document types, and the Umbraco backoffice.

Common Accessibility Issues

critical

Razor Views Using Div-Based Layouts Without HTML5 Landmarks

WCAG 1.3.1

Many Umbraco starter templates and agency-built sites use div-heavy master layouts with no header, nav, main, or footer landmarks. Screen reader users rely on these landmarks to jump directly to the content they want. Without them, the page appears as a flat DOM where every read starts from the top and moves linearly.

How to fix:

Refactor your _Layout.cshtml and page templates to use semantic HTML5 elements: header for the site header, nav with an aria-label for primary navigation, main for the primary content region (exactly one per page), aside for complementary content, and footer for the site footer. Ensure partial views that render site chrome (navigation, footer) produce these elements rather than leaving them to the consuming template.

Before
<!-- Views/_Layout.cshtml -->
<div class="site-header">@await Html.PartialAsync("_Header")</div>
<div class="site-nav">@await Html.PartialAsync("_Navigation")</div>
<div class="page-content">@RenderBody()</div>
<div class="site-footer">@await Html.PartialAsync("_Footer")</div>
After
<!-- Views/_Layout.cshtml -->
<header class="site-header">@await Html.PartialAsync("_Header")</header>
<nav aria-label="Primary" class="site-nav">@await Html.PartialAsync("_Navigation")</nav>
<main id="main" class="page-content">@RenderBody()</main>
<footer class="site-footer">@await Html.PartialAsync("_Footer")</footer>
critical

Media Library Images Without Alt Text

WCAG 1.1.1

The Umbraco media library treats the "Alternative text" field on the Image media type as optional. Editors routinely upload images without filling it in, and Razor views that read the alt attribute fall back to the media item name, which is often a filename like "DSC_04821.jpg". Every image on the site ships without accessible text alternatives.

How to fix:

Edit the Image media type (Settings > Media Types) and mark the "Alternative text" property as required (or add a custom validation rule). In your Razor views, always output the alt attribute from the alternative text property, and do not fall back to the media name. For decorative images, add a "Decorative" Boolean property to the media type and output alt="" when true. Use the built-in ImageCropper for responsive images and always emit width and height attributes.

Before
@{ var image = Model.HeroImage; }
@if (image != null)
{
    <img src="@image.Url()" />
}
After
@{ var image = Model.HeroImage; }
@if (image != null)
{
    var alt = image.Value<string>("alternativeText") ?? string.Empty;
    var decorative = image.Value<bool>("decorative");
    <img src="@image.GetCropUrl(width: 1280, height: 720)"
         srcset="@image.GetCropUrl(width: 640, height: 360) 640w, @image.GetCropUrl(width: 1280, height: 720) 1280w"
         width="1280" height="720"
         alt="@(decorative ? string.Empty : alt)"
         @(decorative ? Html.Raw("role=\"presentation\"") : null) />
}
serious

Block List and Block Grid Blocks With Fixed Heading Levels

WCAG 1.3.1

Umbraco's Block List and Block Grid editors let editors assemble pages from reusable blocks (hero, text, callout, quote). Most block partial views hardcode a heading level like h2 or h3. When an editor places a "Quote" block (h3) before the first "Section" block (h2), the page produces an h3 before any h2, breaking heading hierarchy for screen reader users navigating by heading.

How to fix:

Pass the current heading level into each block partial from the parent template as a ViewData or render argument, starting at h2 below the page h1, and increment by one for nested blocks. Alternatively, add a "Heading level" dropdown property to each block document type with choices h2, h3, h4, and render the selected level dynamically. Document the hierarchy rules for your content team directly in the block description inside Umbraco.

critical

Umbraco Forms Templates Missing Labels and Error Associations

WCAG 3.3.2

Umbraco Forms ships with multiple Razor templates (Default, Bootstrap, Theme) and agencies frequently create custom themes. Custom themes often remove the label element or visually hide it without programmatic association, rely on placeholder text as the only field identifier, and display a global error summary without linking each error back to the field that failed.

How to fix:

Ensure every input in your Umbraco Forms theme has a label element with a for attribute matching the input id. For required fields, add required and aria-required="true" attributes. For error handling, wrap the form in an element that receives focus after submission errors, output each error inside an element with aria-describedby pointing to it from the corresponding input, and set aria-invalid="true" on invalid fields. Umbraco Forms v14 ships an accessible default theme; base custom themes on it rather than the legacy "Default" theme.

serious

Focus Styles Removed by Reset Stylesheets

WCAG 2.4.7

Many Umbraco sites ship with global CSS resets that include outline: 0 or outline: none on focusable elements without providing an alternative focus indicator. Keyboard users cannot see which element has focus, which fails WCAG 2.4.7 Focus Visible and makes keyboard navigation impractical for sighted users who rely on it.

How to fix:

Remove any outline: 0 or outline: none rule that targets :focus without a replacement. Use the :focus-visible pseudo-class to show a prominent focus indicator only when the user is navigating with a keyboard. Ensure the focus indicator has at least 3:1 contrast against the adjacent background, is at least 2 CSS pixels thick, and is not obscured by overlapping elements. Test every interactive component with keyboard only and confirm the focus indicator is visible on every element.

Before
/* Global reset in wwwroot/css/site.css */
*:focus { outline: none; }
button:focus, a:focus, input:focus { outline: 0; }
After
/* wwwroot/css/site.css */
*:focus-visible {
  outline: 3px solid #0057b8;
  outline-offset: 2px;
  border-radius: 2px;
}
/* Do not suppress focus with outline: none */
serious

Multi-Language Sites Missing Lang Attribute on Localized Pages

WCAG 3.1.1

Umbraco natively supports multi-language content through the Languages feature and the Culture property on nodes. Templates frequently hardcode lang="en" on the html element or omit the attribute entirely. Screen readers then read Danish, French, or German content with an English speech synthesizer, producing incomprehensible audio output.

How to fix:

In your _Layout.cshtml, read the current culture from Model.GetCultureFromDomains() or the IVariationContextAccessor and set lang on the html element dynamically. For inline content in a different language within a page, wrap it in a span with a lang attribute matching the quoted text's language. Verify every language variant of every page by viewing source and confirming the lang attribute matches the content language.

moderate

Custom Backoffice Dashboards and Property Editors Without Accessibility

WCAG 2.1.1

Umbraco's package ecosystem includes many custom property editors and backoffice dashboards. Older packages frequently ship with keyboard traps, missing labels, and dropdowns that work only with a mouse. Content editors with disabilities cannot use the affected property editors, which blocks them from specific content types.

How to fix:

When choosing packages, audit their property editors with a keyboard only and with a screen reader before installing them on production. For in-house property editors, follow the Umbraco UI library (Umbraco.UI) which ships accessible web components for common patterns. Umbraco 14 uses the new Lit-based backoffice where Umbraco.UI components are the default. Raise accessibility issues with package maintainers and prefer actively maintained alternatives.

Umbraco-Specific Tips

  • Use the built-in ImageCropper data type and the GetCropUrl Razor helper for responsive images. ImageCropper lets you define named crops that correspond to layout contexts, and the helper emits the correct URL for each crop while letting you pass explicit width and height values to the img tag.
  • Make the "Alternative text" property required on the Image media type at the data type level. This enforces alt text at the point of upload rather than relying on a code review or a content audit to catch missing alt text later.
  • Configure your Block List and Block Grid block document types with descriptive labels ("Section heading block (renders as h2)", "Quote block (renders as blockquote with h3 citation)"). These labels appear in the Umbraco backoffice and help editors understand the semantic role of each block.
  • Upgrade to Umbraco 14 or later if possible. The new Lit-based backoffice ships with substantially improved keyboard navigation, focus management, and ARIA support compared to the AngularJS backoffice in versions 8 through 13. Editors who rely on assistive technology will have a dramatically better experience.
  • Integrate axe-core into your build pipeline running against the rendered public site, not against the backoffice. Target typical page templates with representative content from a staging environment so heading hierarchy, landmarks, and locale issues are caught on every pull request.

Umbraco.UI

Umbraco's official web component library, used by the Umbraco 14+ backoffice. Components ship with built-in keyboard navigation, ARIA attributes, and focus management. Use it when building custom backoffice property editors and dashboards rather than reinventing accessibility primitives.

axe DevTools

A browser extension and CI tool for automated WCAG testing of rendered Razor views. Especially useful for catching missing alt text, insufficient color contrast, and heading hierarchy problems on Block List and Block Grid pages.

Umbraco Forms v14 Default Theme

The Umbraco Forms v14 default theme provides accessible form markup with proper label associations, aria-invalid, and per-field error messages. Base custom form themes on this template rather than the legacy Default theme from earlier versions.

Further Reading

Other CMS Checklists