Bricks Builder has gone from a niche developer-favourite to one of the fastest-growing WordPress page builders in 2026, with a userbase concentrated among freelancers and small agencies who chose it precisely because it gives them clean HTML output and total control over element semantics. That control cuts both ways for accessibility. Bricks does not insert wrapper divs you do not need, which means the markup you ship is whatever you build. There is no theme template overriding your decisions and no opinionated component library auto-adding ARIA attributes. The result we see in audits is a bimodal distribution: Bricks sites built by accessibility-aware developers score better than sites on Elementor or Divi, while Bricks sites built by designers who treat it like a Webflow clone produce worse results because there is no safety net catching missing landmarks, heading hierarchy breaks, or unlabelled buttons. We audited 18 Bricks Builder sites in March and April 2026 and the most common findings were: 78% used a div with class 'button' instead of a real button or anchor element so keyboard users could not activate the action; 67% had multiple H1s on the page because the Bricks Heading element defaults to H2 but designers commonly switched the page-section heading to H1 for visual size without checking the rest of the page; 61% used the off-canvas / mobile menu without aria-expanded or focus management; 55% had a Bricks Slider that auto-played without a pause control; and 50% used the Bricks Query Loop to render product cards where the link wrapped a heading element causing the heading to be inside an anchor and announced incorrectly by VoiceOver. This checklist is the version we use when we sit down to scope a Bricks Builder accessibility audit. It assumes Bricks 1.10+ (the version that introduced the global Custom Code feature and improved the Heading element defaults). Each issue is mapped to a WCAG 2.1 AA criterion, includes a Bricks-specific fix, and notes the global setting or element panel where the change is made.

Common Accessibility Issues

critical

Div Element Used as Button Loses Keyboard Operability

WCAG 2.1.1

Bricks designers regularly create CTA buttons by adding a Div element, styling it, and attaching a click event via the Interactions panel. The result is a clickable div with no keyboard role, no Enter or Space activation, and no announcement to screen readers as a button. The same anti-pattern appears with icon-only buttons built from a Div containing an Icon element.

How to fix:

Use the Bricks Button element for any interactive control. If the design requires custom geometry, switch the Tag dropdown in the Element panel from 'div' to 'button' (Bricks supports this for most elements). For icon-only buttons, set the aria-label attribute via the Attributes panel. Verify by tabbing to the button and pressing Enter to confirm activation.

Before
<div class="brxe-div cta-button" data-interactions="...">
  <span>Get started</span>
</div>
After
<button type="button" class="brxe-div cta-button" data-interactions="...">
  <span>Get started</span>
</button>
critical

Multiple H1s Per Page From Heading Element Default Misuse

WCAG 1.3.1

The Bricks Heading element defaults to H2 but designers frequently change a hero heading to H1 for visual size, then change a separate section heading to H1 for the same reason. The result is two or three H1 elements on the page. Screen reader users using heading navigation lose the ability to find the page topic. Search engines also penalise multi-H1 pages.

How to fix:

Establish a global rule that exactly one H1 exists per page (the page topic, usually in the hero section). Use H2 for major sections, H3 for subsections. Use the Bricks Code element or a custom theme.json to enforce H1-only-once if multiple designers work on the same site. Audit with the Web Developer extension's outline view or HeadingsMap.

Before
<section class="hero"><h1>Build faster sites</h1></section>
<section class="features"><h1>Why Bricks?</h1></section>
<section class="pricing"><h1>Pricing</h1></section>
After
<section class="hero"><h1>Build faster sites</h1></section>
<section class="features"><h2>Why Bricks?</h2></section>
<section class="pricing"><h2>Pricing</h2></section>
critical

Off-Canvas Menu Toggle Has No aria-expanded or Focus Management

WCAG 4.1.2

The Bricks Nav Menu element with the off-canvas trigger style renders a hamburger toggle that opens a slide-in menu on mobile. The default markup uses a div with onclick rather than a button, omits aria-expanded, and does not move keyboard focus into the menu when it opens. Screen reader users hear nothing when the menu appears, and keyboard users continue tabbing through the now-hidden page content.

How to fix:

In Bricks 1.9+ the Nav Menu element exposes a 'Toggle accessibility' setting that emits a button with aria-expanded and aria-controls. Enable it. For older sites, add a small Code element that registers a click handler to toggle aria-expanded and move focus to the first menu item on open. Also bind Escape to close the menu and return focus to the toggle.

Before
<div class="brxe-nav-nested-toggle" onclick="openMenu()">
  <span class="icon-hamburger"></span>
</div>
After
<button class="brxe-nav-nested-toggle" aria-expanded="false" aria-controls="primary-nav" aria-label="Open menu">
  <span class="icon-hamburger" aria-hidden="true"></span>
</button>
critical

Slider Element Auto-Plays Without Pause Control

WCAG 2.2.2

The Bricks Slider element (built on Splide) ships with auto-play disabled by default, but designers routinely enable it for hero carousels with a 4-5 second interval. The element does not auto-emit a Pause / Play button, so users with cognitive disabilities, motion sensitivity, or screen readers cannot stop the rotation. WCAG 2.2.2 Pause, Stop, Hide requires moving content that auto-starts and lasts more than 5 seconds to be pausable.

How to fix:

Either disable auto-play (recommended for hero sliders) or add a custom Pause / Play button via the Bricks Code element that calls the Splide instance's pause() and play() methods. The button must be reachable by keyboard, have an accessible name, and toggle aria-pressed to indicate state.

Before
<div class="brxe-slider" data-splide='{"autoplay":true,"interval":5000}'>
  ...
</div>
After
<div class="brxe-slider" data-splide='{"autoplay":true,"interval":5000}'>
  ...
  <button type="button" class="slider-pause" aria-pressed="false" aria-label="Pause slideshow">Pause</button>
</div>
<script>const splide = Splide('.brxe-slider').mount(); document.querySelector('.slider-pause').addEventListener('click', e => { const pressed = e.target.getAttribute('aria-pressed') === 'true'; pressed ? splide.Components.Autoplay.play() : splide.Components.Autoplay.pause(); e.target.setAttribute('aria-pressed', !pressed); });</script>
serious

Query Loop Card Links Wrap Heading Elements Causing Nested Interactive Issues

WCAG 2.4.4

Bricks designers commonly build product or post cards inside a Query Loop, then wrap the entire card in a 'Block link' or place the card heading inside an anchor. The result is an anchor element containing a heading containing other interactive elements (price, add-to-cart). Screen readers announce the heading inside the link in confusing ways, and click targets overlap so screen-reader users may activate the wrong control.

How to fix:

Use the 'card pattern' instead. Make the heading a normal heading (not inside an anchor), then add the link only to the heading text or to a 'Read more' button. If the entire card must be clickable, use the link-overlay technique: position an absolutely-positioned anchor over the card with z-index, give it text content like 'Read more about [post title]', and ensure other interactive elements inside the card have z-index higher than the overlay.

Before
<a href="/post/123" class="card-link">
  <article>
    <h3>How to fix WordPress accessibility</h3>
    <p>Excerpt...</p>
    <button>Add to favourites</button>
  </article>
</a>
After
<article class="card" style="position:relative">
  <h3><a href="/post/123" class="card-link">How to fix WordPress accessibility</a></h3>
  <p>Excerpt...</p>
  <button style="position:relative;z-index:2">Add to favourites</button>
</article>
serious

Custom Brand Colours Set in Theme Styles Fail 4.5:1 Contrast

WCAG 1.4.3

Bricks Theme Styles let you define a global colour palette and apply it to every Heading, Text, and Button element. Designers frequently set the brand-blue colour for body text on a white background that measures only 3.2:1 contrast, then propagate that choice site-wide via Theme Styles. Because the failure is global, it shows up on every page in an audit.

How to fix:

Audit the Theme Styles palette before building components. Run each foreground / background pair through the WebAIM contrast checker. Aim for 4.5:1 minimum for body text and 3:1 for large text (>=24px regular or >=19px bold). Save the verified colours to a 'brand-text-strong' and 'brand-text-on-white' palette token and use those tokens for all body content.

Before
/* Bricks Theme Style - Body text */
body { color: #5fa1d4; } /* 3.0:1 on white - fails */
After
/* Bricks Theme Style - Body text */
body { color: #1c5fc0; } /* 5.6:1 on white - passes */
/* Reserve the lighter brand-blue for accents only */
serious

Form Element Does Not Surface Inline Validation Errors to Screen Readers

WCAG 3.3.1

The Bricks Form element supports inline validation, but the error messages render inside a div that has no aria-live region and no programmatic association with the failed input. A blind user submits the form, hears nothing, and assumes nothing happened. Sighted users with cognitive disabilities also miss errors when the page does not scroll to the failed field.

How to fix:

Add aria-live='assertive' aria-atomic='true' to the form's error container via the Bricks Form > Settings > Custom Attributes panel. Set aria-describedby on each input pointing at its error message id. On submit failure, move keyboard focus to the first invalid input. Bricks 1.10 added a brx_form_error JS event you can hook into to implement this.

Before
<form class="brxe-form">
  <input id="email" type="email">
  <div class="error-message" style="display:none">Invalid email</div>
</form>
After
<form class="brxe-form" novalidate>
  <label for="email">Email</label>
  <input id="email" type="email" aria-describedby="email-error" aria-invalid="false">
  <div id="email-error" class="error-message" role="alert" aria-live="assertive"></div>
</form>
<script>document.addEventListener('brx_form_error', e => { e.detail.invalidFields[0].focus(); });</script>

Bricks Builder-Specific Tips

  • Use Bricks' global Custom Code feature (introduced in 1.10) to register a single accessibility helpers script loaded site-wide. Put your focus traps, Escape handlers, and aria-expanded toggles in one place rather than copy-pasting Code elements across templates.
  • The Bricks Builder community has an unofficial 'Bricks Accessibility Checker' snippet bundle that ships axe-core scanning inside the builder preview. It does not replace a real audit but it catches the obvious failures (missing alt, label, contrast) before the page is published.
  • When using the Query Loop, audit the OUTPUT not the builder template. Bricks renders dynamic content on the front-end, so the heading hierarchy you see in the builder may not match what is rendered when the query returns 12 cards. Run a Pa11y CI scan on the published page.
  • Bricks 1.9 introduced an 'Accessibility' tab in the Element panel for many elements (Nav Menu, Slider, Tabs, Accordion). Always check it before assuming defaults are accessible. The defaults are getting better but lag behind the docs.
  • If you migrate from Elementor or Divi to Bricks, re-audit every page after migration. Bricks does NOT preserve the accessibility patches you may have added via custom CSS or JS in the previous builder. The clean output is a feature, but it strips both bloat and your fixes.
  • Bricks supports WordPress block themes via the 'Theme Templates' feature. If you build the header in Bricks but the footer comes from a block theme, audit both layers. Mixed-architecture sites are where focus order breaks most often.

axe DevTools

Browser extension that scans the published Bricks page for WCAG violations. Especially useful for catching the div-as-button pattern and missing aria-expanded on the off-canvas toggle that Bricks does not warn about in the builder.

Accessibility Checker for WordPress by Equalize Digital

WordPress plugin that scans every Bricks-built page from inside the WP admin. The free tier covers single-page audits; Pro adds full-site scans and ignores known false-positives common to page-builder output.

WebAIM Contrast Checker

Use it before you set the Bricks Theme Styles palette. Paste your brand colours and verify they meet 4.5:1 for body text and 3:1 for large text BEFORE the colours propagate to every Heading and Text element on the site.

HeadingsMap browser extension

Visual outline of every heading on a page. The fastest way to catch the multi-H1 anti-pattern that Bricks Heading element defaults make easy to commit accidentally.

NVDA screen reader

Free Windows screen reader. Pair it with Firefox to test the Bricks Slider, Tabs, and Accordion components. NVDA is stricter than VoiceOver about ARIA role mismatches and exposes Bricks-specific issues better.

Further Reading

Other CMS Checklists