DEV Community

Cover image for Style :headings
Alvaro Montoro
Alvaro Montoro Subscriber

Posted on • Originally published at alvaromontoro.com

Style :headings

Find an interactive version of this article on my website

Currently, if we want to select all the headings in an HTML document, we can do it by concatenating all the selectors in a single rule:

h1, h2, h3, h4, h5, h6 {
  /* code here */
}
Enter fullscreen mode Exit fullscreen mode

This is clunky and limited. And if we want to select only certain heading levels, we have to write something even messier and clunkier.

There are two new features in CSS that can help with this task:

  • :heading pseudo-class.
  • :heading() pseudo-class function.

NOTE: These features are still experimental and not widely supported. At the time of writing this article (September 2025), only Firefox Nightly has implemented them, so you'll need that browser to test them.

Let's check each of them separately.

:heading

 
:heading is a pseudo-class that will select all headings within the scope (by default, the whole document). That means any h1, h2, h3, h4, h5, or h6 tag.

Notice how there are two restrictions:
 

  • It will select ALL the headings, independently of their level. It doesn't distinguish between h1 and h2, h3 or h6, etc. It's all or nothing.
  • It will only select h? tags, ignoring elements identified as headings using the heading ARIA role.

Here's a quick example:

:heading {
  color: red;
}
Enter fullscreen mode Exit fullscreen mode
<h1>Page Title</h1>
<h2>Chapter Title</h2>
<p>Some text</p>
<h3>Section title</h3>
Enter fullscreen mode Exit fullscreen mode

Page Title (in red), Chapter Title (in red), Some text (in black), Section title (in red)

As mentioned above, :heading is a pseudo-class, and it will have the same specificity weight as a class (0-1-0).


:heading()

:heading() is a pseudo-class function that provides more flexibility than :heading as it takes a list of one or more levels to select. For example, :heading(2, 3) will select all the h2 and h3, but not an h1.

You might ask, "But, Álvaro, why not just use the selector h2, h3? It would be easier and shorter!"

Great question. While a heading level is usually indicated by the number in the tag (h1 is level 1, h2 is level 2, etc.), there are ways reset and update a heading level. For example, using the HTML attributes headingoffset or headingreset (not fully supported either, but that's other story).

Unfortunately, just as elements with role="heading" are not recognized as headings by :heading, using aria-level is also not enough for CSS to recognize a new heading level.

:heading(2, 3) {
  color: red;
}
Enter fullscreen mode Exit fullscreen mode
<h1>Page Title</h1>
<h2>Chapter Title</h2>
<p>Some text</p>
<h3>Section title</h3>
Enter fullscreen mode Exit fullscreen mode

Page Title (in black), Chapter Title (in blue), Some text (in black), Section title (in blue)

A trick when using :heading(): the arguments don't have to be strictly numeric. We can use An + B functional notation (e.g., 2n + 1), or keywords like odd and even to select the heading we want.


Bibliography and Links

The new CSS heading pseudo-classes and functions are easy, simple and powerful. They are a convenient and clean way to style headings.

If you want to learn more, visit these sites:

Top comments (0)