Skip to content

Linter Rule: Disallow empty headings

Rule: html-no-empty-headings

Description

Disallow headings (h1, h2, etc.) with no accessible text content.

Rationale

Headings relay the structure of a webpage and provide a meaningful, hierarchical order of its content. If headings are empty or its text contents are inaccessible, this could confuse users or prevent them accessing sections of interest.

Examples

✅ Good

erb
<h*>Heading Content</h*>
Found `TOKEN_CHARACTER` when expecting `TOKEN_HTML_TAG_END` at (1:22). (`UNEXPECTED_TOKEN_ERROR`) (parser-no-errors)
Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE`, found: `TOKEN_CHARACTER`. (`UNEXPECTED_ERROR`) (parser-no-errors)
Unexpected token. Expected: `TOKEN_ERB_START, TOKEN_HTML_DOCTYPE, TOKEN_HTML_COMMENT_START, TOKEN_IDENTIFIER, TOKEN_WHITESPACE, TOKEN_NBSP, TOKEN_AT, or TOKE`, found: `TOKEN_HTML_TAG_END`. (`UNEXPECTED_ERROR`) (parser-no-errors)
erb
<h*><span>Text</span><h*>
Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE`, found: `TOKEN_CHARACTER`. (`UNEXPECTED_ERROR`) (parser-no-errors)
Opening tag `<h>` at (1:22) doesn't have a matching closing tag `</h>`. (`MISSING_CLOSING_TAG_ERROR`) (parser-no-errors)
Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE`, found: `TOKEN_CHARACTER`. (`UNEXPECTED_ERROR`) (parser-no-errors)
Opening tag `<h>` at (1:1) doesn't have a matching closing tag `</h>`. (`MISSING_CLOSING_TAG_ERROR`) (parser-no-errors)
Tag `<h>` opened at (1:1) was never closed before the end of document. (`UNCLOSED_ELEMENT_ERROR`) (parser-no-errors)
Tag `<h>` opened at (1:22) was never closed before the end of document. (`UNCLOSED_ELEMENT_ERROR`) (parser-no-errors)
erb
<div role="heading" aria-level="1">Heading Content</div>
erb
<h* aria-hidden="true">Heading Content</h*>
Found `TOKEN_CHARACTER` when expecting `TOKEN_HTML_TAG_END` at (1:41). (`UNEXPECTED_TOKEN_ERROR`) (parser-no-errors)
Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE`, found: `TOKEN_CHARACTER`. (`UNEXPECTED_ERROR`) (parser-no-errors)
Unexpected token. Expected: `TOKEN_ERB_START, TOKEN_HTML_DOCTYPE, TOKEN_HTML_COMMENT_START, TOKEN_IDENTIFIER, TOKEN_WHITESPACE, TOKEN_NBSP, TOKEN_AT, or TOKE`, found: `TOKEN_HTML_TAG_END`. (`UNEXPECTED_ERROR`) (parser-no-errors)
erb
<h* hidden>Heading Content</h*>
Found `TOKEN_CHARACTER` when expecting `TOKEN_HTML_TAG_END` at (1:29). (`UNEXPECTED_TOKEN_ERROR`) (parser-no-errors)
Unexpected Token. Expected: `TOKEN_IDENTIFIER, TOKEN_AT, TOKEN_ERB_START,TOKEN_WHITESPACE, or TOKEN_NEWLINE`, found: `TOKEN_CHARACTER`. (`UNEXPECTED_ERROR`) (parser-no-errors)
Unexpected token. Expected: `TOKEN_ERB_START, TOKEN_HTML_DOCTYPE, TOKEN_HTML_COMMENT_START, TOKEN_IDENTIFIER, TOKEN_WHITESPACE, TOKEN_NBSP, TOKEN_AT, or TOKE`, found: `TOKEN_HTML_TAG_END`. (`UNEXPECTED_ERROR`) (parser-no-errors)

🚫 Bad

erb
<h1></h1>
Heading element `<h1>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<h2></h2>
Heading element `<h2>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<h3></h3>
Heading element `<h3>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<h4></h4>
Heading element `<h4>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<h5></h5>
Heading element `<h5>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<h6></h6>
Heading element `<h6>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<div role="heading" aria-level="1"></div>
Heading element `<div role="heading">` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)
erb
<h1><span aria-hidden="true">Inaccessible text</span></h1>
Heading element `<h1>` must not be empty. Provide accessible text content for screen readers and SEO. (html-no-empty-headings)

References

Inspired by ember-template-lint

Released under the MIT License.