# Building accessible pricing tables in WordPress with core blocks

> How to structure multi-tier pricing tables using semantic HTML, correct heading hierarchies, and accessible contrast in the WordPress block editor.

Published 25 August 2026 by Jake at Pattern Paste.
Canonical: https://patternpaste.com/blog/building-accessible-pricing-tables/
Tags: Accessibility, Patterns, Tutorial

---

Pricing tables are among the most visited sections on a commercial website, yet they frequently fail basic web accessibility audits. When built with visual drag-and-drop builders or unreviewed block kits, pricing cards often use visual-only headings, non-semantic icon lists, and unlabelled call-to-action buttons that confuse screen reader users and fail keyboard navigation checks.

You can construct clean, fully accessible pricing grids in WordPress using only standard core blocks.

## Common accessibility failures in pricing layouts

Audits of commercial pricing components consistently expose three critical structural defects:

1. **Broken heading hierarchies:** Tier names (like "Starter" or "Enterprise") are often styled using `<span>` or `<p>` tags with large inline font sizes rather than proper `<h3>` elements, preventing screen readers from building an outline of available tiers.
2. **Ambiguous call-to-action buttons:** Multiple buttons on the same page labelled simply "Get started" or "Buy now" provide zero context when a screen reader navigates by interactive elements.
3. **Low-contrast featured badges:** "Popular" or "Best value" badges placed on tinted background bands frequently fall below the WCAG AA minimum contrast ratio of 4.5:1 for standard text.

## Structuring the semantic markup

An accessible three-tier pricing grid relies on a clear container hierarchy:

1. A parent section with an `<h2>` introducing the pricing options.
2. A columns block where each column represents one distinct tier.
3. Inside each column, an `<h3>` naming the plan tier, followed by the price, a semantic unordered list (`<ul>`) for included features, and a uniquely identified button.

Here is the clean core block structure for an individual tier card:

```html
<!-- wp:group {"className":"pricing-card","style":{"spacing":{"padding":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40","left":"var:preset|spacing|40","right":"var:preset|spacing|40"}}},"layout":{"type":"flex","orientation":"vertical"}} -->
<div class="wp-block-group pricing-card">
  <!-- wp:heading {"level":3,"fontSize":"large"} -->
  <h3 class="wp-block-heading has-large-font-size">Professional</h3>
  <!-- /wp:heading -->

  <!-- wp:paragraph {"style":{"typography":{"fontSize":"2.5rem","lineHeight":"1"}}} -->
  <p style="font-size:2.5rem;line-height:1"><strong>$49</strong> <span style="font-size:1rem;color:var(--wp--preset--color--contrast-muted)">/ month</span></p>
  <!-- /wp:paragraph -->

  <!-- wp:paragraph {"fontSize":"small"} -->
  <p class="has-small-font-size">For growing teams requiring advanced workflow controls and priority support.</p>
  <!-- /wp:paragraph -->

  <!-- wp:list {"className":"pricing-features"} -->
  <ul class="wp-block-list pricing-features">
    <!-- wp:list-item -->
    <li>Unlimited active projects</li>
    <!-- /wp:list-item -->
    <!-- wp:list-item -->
    <li>Advanced permission controls</li>
    <!-- /wp:list-item -->
    <!-- wp:list-item -->
    <li>Standard integrations</li>
    <!-- /wp:list-item -->
  </ul>
  <!-- /wp:list -->

  <!-- wp:buttons {"layout":{"type":"flex","justifyContent":"center"}} -->
  <div class="wp-block-buttons">
    <!-- wp:button {"width":100} -->
    <div class="wp-block-button has-custom-width wp-block-button__width-100">
      <a class="wp-block-button__link wp-element-button" href="/checkout/?plan=pro" aria-label="Sign up for the Professional plan at $49 per month">Get Professional</a>
    </div>
    <!-- /wp:button -->
  </div>
  <!-- /wp:buttons -->
</div>
<!-- /wp:group -->
```

## Adding screen-reader context to CTA buttons

When a visually impaired user tabs through a webpage, their screen reader announces the link text in isolation. If every button in the grid announces "Get started", the user cannot determine which tier they are selecting without re-reading the surrounding card.

Adding an `aria-label` attribute directly to each button link solves this immediately:

```html
<a class="wp-block-button__link" href="/signup" aria-label="Sign up for the Professional plan at $49 per month">Get started</a>
```

Sighted users see the concise "Get started" label on the visual button, while assistive technologies announce the complete context including the plan name and price.

## Verifying contrast and keyboard focus

Before deploying a pricing section:

1. **Test keyboard tab order:** Press `Tab` repeatedly to cycle through each interactive element. Ensure the focus ring is clearly visible around each tier button and follows a logical left-to-right sequence.
2. **Inspect contrast ratios:** Use Chrome DevTools or Lighthouse to audit contrast between text, badges, and card backgrounds. Accent cards with coloured backgrounds must maintain at least a 4.5:1 contrast ratio against body text and 3:1 against UI borders.

*Pattern Paste provides accessible block patterns, including verified pricing layouts like [pricing-single](/pattern/pricing-single/) and [pricing-tiers](/pattern/pricing-tiers/) tested for WCAG AA compliance. [Browse the entire library](/patterns/).*
