CSS :heading() Pseudo-Class
The CSS :heading() pseudo-class selects heading elements based on their heading levels. It accepts one or more heading level numbers, allowing developers to style specific headings without writing separate selectors for each HTML heading element.
:heading() Syntax
:heading(level) {
property: value;
}
The :heading() pseudo-class accepts one or more comma-separated positive integers representing heading levels.
Single Heading Level
:heading(2) {
color: #0088cc;
}
This rule selects second-level headings, including HTML <h2> elements.
Multiple Heading Levels
:heading(2, 3) {
color: #003366;
}
This rule selects second- and third-level headings.
Combining with Other Selectors
article :heading(2, 3) {
margin-bottom: 12px;
}
This selector targets second- and third-level headings inside an <article> element.
How :heading() Works
The :heading() pseudo-class matches elements that the document language identifies as headings at the specified levels.
In HTML, the standard heading elements are <h1> through <h6>. Each element has a corresponding heading level.
Matching Heading Levels
<h1>Main Heading</h1>
<h2>Section Heading</h2>
<h3>Subsection Heading</h3>
:heading(2) {
color: #0088cc;
}
Only the <h2> matches this selector in a browser that supports :heading().
Based on Heading Level
The selector uses an element's heading level rather than its appearance. Changing the font size of a heading does not change which :heading() selector matches it.
Not Based on Document Position
The number inside :heading() represents a heading level, not the position of a heading among its siblings.
For example, :heading(2) does not mean the second heading on a webpage.
Selecting Heading Levels
HTML defines six standard heading levels, numbered from 1 through 6.
HTML Heading Levels
| Selector | HTML Element | Heading Level |
|---|---|---|
:heading(1) |
<h1> |
1 |
:heading(2) |
<h2> |
2 |
:heading(3) |
<h3> |
3 |
:heading(4) |
<h4> |
4 |
:heading(5) |
<h5> |
5 |
:heading(6) |
<h6> |
6 |
Selecting First-Level Headings
:heading(1) {
font-size: 2rem;
color: #003366;
}
This rule styles first-level headings.
Selecting Lower-Level Headings
:heading(4, 5, 6) {
font-weight: bold;
color: #666;
}
This rule applies shared styles to fourth-, fifth-, and sixth-level headings.
Multiple Heading Levels
Multiple heading levels can be included in a single :heading() selector by separating the level numbers with commas.
Selecting Two Levels
:heading(2, 3) {
border-bottom: 1px solid #ccc;
padding-bottom: 8px;
}
Second- and third-level headings receive the same border and padding.
Selecting Several Levels
:heading(2, 3, 4) {
margin-top: 20px;
margin-bottom: 10px;
}
This rule applies consistent spacing to heading levels 2, 3, and 4.
Selecting Nonconsecutive Levels
:heading(1, 3, 5) {
color: #006699;
}
The heading levels do not need to be consecutive.
No Heading Range Syntax
The function does not use a numeric range to select several heading levels. Each desired level must be listed explicitly.
:heading() vs. :heading
The functional and nonfunctional forms are related but match different sets of headings.
Comparison
| Selector | Matching Behavior |
|---|---|
:heading |
Matches headings at any level. |
:heading(1) |
Matches first-level headings. |
:heading(2, 3) |
Matches second- and third-level headings. |
:heading(4, 5, 6) |
Matches fourth-, fifth-, and sixth-level headings. |
Styling All Headings
:heading {
font-family: Arial, sans-serif;
}
Styling Selected Heading Levels
:heading(2, 3) {
color: #0088cc;
}
Use :heading for shared styles across all heading levels and :heading() when only particular levels should match.
:heading() vs. :is()
The :is() pseudo-class can group ordinary HTML heading selectors and provides a broadly supported alternative.
Using :heading()
:heading(2, 3) {
color: #0088cc;
}
Using :is()
:is(h2, h3) {
color: #0088cc;
}
For standard HTML headings, these selectors match the same elements when :heading() is supported.
Key Differences
| Feature | :heading(2, 3) | :is(h2, h3) |
|---|---|---|
| Matches HTML h2 and h3 | Yes | Yes |
| Uses heading level numbers | Yes | No |
| Specificity | 0-1-0 |
0-0-1 |
| Browser availability | Limited | Widely available |
Use :is() when consistent styling across older and current browsers is required.
:heading() Specificity
The :heading() pseudo-class contributes a specificity of 0-1-0, regardless of how many heading levels are included in its argument list.
Specificity Examples
| Selector | Specificity |
|---|---|
:heading(2) |
0-1-0 |
:heading(2, 3) |
0-1-0 |
article :heading(2) |
0-1-1 |
:heading(2).featured |
0-2-0 |
h2 |
0-0-1 |
:is(h2, h3) |
0-0-1 |
Specificity Example
h2 {
color: #333;
}
:heading(2) {
color: #0088cc;
}
When both selectors match and other cascade factors are equal, the :heading(2) declaration takes precedence because the pseudo-class has greater specificity.
Reducing Specificity
:where(:heading(2, 3)) {
margin-bottom: 12px;
}
The :where() pseudo-class reduces the specificity contribution of the entire selector to zero.
Practical Uses
The :heading() pseudo-class can group heading levels that share common visual styles.
Section Heading Colors
:heading(2, 3) {
color: #003366;
}
Second- and third-level headings share a text color.
Smaller Heading Styles
:heading(4, 5, 6) {
font-size: 0.875rem;
font-weight: bold;
}
Lower-level headings receive a consistent font size and weight.
Article Heading Spacing
article :heading(2, 3, 4) {
margin-top: 20px;
margin-bottom: 10px;
}
Selected headings inside an article receive consistent spacing.
Headings with Classes
:heading(2, 3).featured {
border-left: 4px solid #0088cc;
padding-left: 10px;
}
This rule styles second- and third-level headings that also have the featured class.
Limitations
The :heading() pseudo-class is intended for semantic heading levels, but its browser availability remains limited.
Limited Browser Support
Browsers that do not recognize :heading() ignore CSS rules using the selector.
Requires Heading Levels
The function requires heading level numbers. Unlike :heading, the functional form does not select all heading levels when its parentheses are empty.
Not a Position Selector
The selector does not select the first, second, or third heading according to document order. It matches semantic heading levels.
Does Not Change HTML Semantics
Using :heading(2) does not convert another element into an <h2> or change its accessibility semantics.
Compatibility Fallback
:is(h2, h3) {
color: #003366;
}
This alternative matches the corresponding standard HTML heading elements in browsers that support :is().
Accessibility
HTML headings organize webpage content into a meaningful structure that helps users navigate and understand the document.
Use Appropriate Heading Levels
Choose heading levels according to the document hierarchy rather than their default visual appearance.
Maintain Heading Order
Use a logical heading sequence. Avoid skipping levels solely to achieve a preferred font size.
Readable Heading Styles
Maintain sufficient contrast, readable font sizes, and clear spacing between headings and surrounding content.
CSS and Semantics
CSS changes visual presentation but does not change the semantic heading level exposed to assistive technologies.
Best Practices
- Use
:heading()when several specific heading levels need shared styling. - List each desired heading level explicitly.
- Use
:headingwhen styles should apply to headings at every level. - Provide a compatible fallback using standard heading selectors or
:is(). - Remember that heading numbers represent levels, not document positions.
- Consider specificity when combining heading selectors with classes.
- Preserve semantic HTML and a logical heading hierarchy.
- Test heading styles across browsers.
:heading() Example
This example styles second- and third-level headings using :heading(2, 3). A compatible fallback ensures that the headings remain styled in browsers without support for the functional pseudo-class.
HTML
<div class="heading-demo">
<h1>Heading Level 1</h1>
<h2>Heading Level 2</h2>
<h3>Heading Level 3</h3>
<h4>Heading Level 4</h4>
<p>This paragraph is not a heading.</p>
</div>
CSS
.heading-demo :is(h2, h3) {
color: #003366;
border-bottom: 1px solid #ccc;
padding-bottom: 6px;
}
.heading-demo :heading(2, 3) {
color: #0088cc;
border-bottom-color: #0088cc;
}
.heading-demo h1 { font-size: 1.375rem; }
.heading-demo h2 { font-size: 1.25rem; }
.heading-demo h3 { font-size: 1.125rem; }
.heading-demo h4 { font-size: 1rem; }
In browsers supporting :heading(), the second- and third-level headings appear in a brighter blue. Other browsers use the darker blue fallback. The first- and fourth-level headings are not selected by either rule.
Browser Result
Note: The fallback uses :is(h2, h3). The brighter blue styling indicates whether the browser applies the :heading(2, 3) rule.
Browser Support
Baseline: Limited availability. The :heading() pseudo-class is not consistently supported across major browsers. Standard heading selectors and :is() provide more broadly compatible alternatives.
For current compatibility information, visit Can I Use? and search for :heading().
Specifications
The :heading() pseudo-class is defined in CSS Selectors Level 4 as part of the heading pseudo-classes. It allows heading levels to be specified using a comma-separated list of positive integers.
