Provide Text For A JSX Heading

ID

javascript.jsx_empty_heading

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

accessibility, jsx, reliability

Description

Reports a JSX heading (<h1>..<h6>) that renders nothing and carries no accessible name of its own.

Rationale

Screen-reader users navigate a page by its headings, so the heading list is the page outline. An empty heading puts an unlabelled entry in that list: it breaks the outline, announces nothing, and gives no clue what the section below it is.

In a component tree it is easy to produce by accident — a heading rendered before its data arrives, or a wrapper kept "for the styling".

What counts as content is what React would put in the DOM: text with something other than whitespace in it, a nested element or fragment, or an expression in braces. A brace pair holding only a comment renders nothing and is treated as empty. An aria-label or aria-labelledby names the heading without visible text and satisfies the rule; an element that spreads an object into its attributes is left alone, since either may arrive at runtime.

<h1></h1>                          // FLAW - nothing to announce
<h2 className="title" />           // FLAW - self-closing, so no content at all
<h3> </h3>                         // FLAW - whitespace is not content

<h1>Dashboard</h1>                 // OK
<h2>{title}</h2>                   // OK - computed text
<h3><Icon /> Settings</h3>         // OK - a nested element can name it
<h4 aria-label="Filters" />        // OK - named by the attribute

Remediation

Give the heading its text. When the text arrives with the data, render the heading only once it is there rather than rendering it empty. When the heading is deliberately invisible, name it with aria-label, or point aria-labelledby at the element that already carries the text. When the element was only ever a styling hook, use a <div> — it carries no heading role to leave unlabelled.

© 2026 Xygeni. All rights reserved