Structural Role On An Interactive Element

ID

html.interactive_element_non_interactive_role

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Html

Tags

accessibility, reliability

Description

Flags a structural ARIA role on an element that is an interactive control.

Rationale

An interactive element keeps its behaviour whatever role it claims: the button is still clickable, the link still navigates, both are still in the tab order. Only the announcement changes, and it changes to something that says the element does nothing. A screen reader user is told this is a heading, or a decoration, and has no reason to activate it — the control becomes invisible while remaining reachable by Tab, which is the worst of both.

<button role="heading" onclick="open()">Details</button>   <!-- FLAW — announced as a heading -->
<a href="/home" role="presentation">Home</a>               <!-- FLAW — a link with no semantics -->
<input type="text" name="q" role="img">                    <!-- FLAW — a field announced as an image -->

<button onclick="open()">Details</button>                  <!-- OK -->
<button role="tab" onclick="open()">Details</button>       <!-- OK — still a control -->
<a role="presentation">No href</a>                         <!-- OK — not a link without one -->
<input type="hidden" name="csrf" role="img">               <!-- OK — a hidden field is no control -->
<button role="${kind}">Save</button>                       <!-- OK — settled at render time -->

role="presentation" and role="none" are the sharpest form of this: they ask for the semantics to be stripped, and on a focusable element the specification says that request is ignored, so the markup states an intent the browser will not honour.

The elements judged are the interactive controls: button, select, textarea, summary and details; a and area when they carry an href; and input of any type but hidden. The roles reported are the structural ones — headings, landmarks, lists, content and presentation. Roles whose interactivity depends on their container (row, gridcell) and group, the implicit role of details, are left out on purpose.

Only a role written as plain HTML with a literal value is judged. A directive such as th:role, a template expression, a valueless role and a namespaced element are all left alone.

Remediation

Drop the role: the element already exposes the right one. When the document needs the structure the role was reaching for, wrap the control in the element that provides it, so the heading is a heading and the control is a control.

<h2><button onclick="open()">Details</button></h2>
<a href="/home">Home</a>

© 2026 Xygeni. All rights reserved