Sheath rule
a11y-no-heading-inside-button
Heading elements should not be nested inside buttons.
- Package
- Core
- Category
- Accessibility
- Default severity
- error by default
- Auto-fix
- Manual fix
#Why
Screen readers offer a list of a page's headings as a way to jump around it. A heading inside a button puts a control in that list, so someone navigating by heading encounters a button instead of the start of a document section.
The button also stops being announced as a plain control, since its accessible name now arrives wrapped in heading semantics.
#Examples
#Bad
<!-- Heading inside button -->
<button>
<h2>Click Here</h2>
</button>
<!-- Nested heading inside button -->
<button>
<div>
<h3>Submit Form</h3>
</div>
</button>
<!-- Element with role="button" containing heading -->
<div role="button">
<h4>Action</h4>
</div>
#Good
<!-- Use span for styled text inside buttons -->
<button>
<span class="button-title">Click Here</span>
</button>
<!-- Plain text in button -->
<button>Submit Form</button>
<!-- Styled text without heading semantics -->
<button>
<span class="large-text">Action</span>
</button>
<!-- Heading before button -->
<h2>Actions</h2>
<button>Click Here</button>
#Notes
- Use CSS to style button text instead of headings
<span>elements can be styled to look like headings without semantic issues- Elements with
role="button"are included - The same principle applies to links - avoid headings inside
<a>tags
#References
- WCAG 1.3.1 Info and Relationships - Level A success criterion for semantic structure
- HTML Spec: Button Content Model - Defines valid content for button elements
#Related Rules
- a11y-no-empty-headings - Headings must have content
- a11y-no-skip-heading-levels - Heading level sequence
- best-practices-no-nested-interactive - No nested interactive elements