What is the proper application of counter-reset when utilizing CSS counters to automatically number headings?

In my quest to automatically number headings with multiple levels of hierarchy in an HTML document using CSS, I have encountered various examples online that heavily rely on counter-reset. However, despite testing it in different configurations, I haven't been able to make it work effectively.

I specifically need the h3 counter (subsection) to reset at each new h2 heading.

Here's a simple example code snippet to illustrate:

body {
  counter-reset: section subsection;
}

.countheads>h2::before {
  counter-increment: section;
  content: counter(section, upper-roman);
  counter-reset: subsection;
}

.countheads>h3::before {
  counter-increment: subsection;
  content: counter(section, upper-roman) "." counter(subsection);
}
<body>
  <div class="countheads">
    <h1>
      Main title
    </h1>

    <h2>
      Wuhhh
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>

    <h2>
      Whoa
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>


  </div>
</body>

The intended behavior is for subsections in section II to restart at 1, such as II.1, II.2.

To achieve this, changing the counter-reset statement to counter-set produces the desired outcome:

body {
  counter-reset: section subsection;
}

.countheads > h2::before {
  counter-increment: section;
  content: counter(section, upper-roman);
  counter-set: subsection;
}

.countheads > h3::before {
  counter-increment: subsection;
  content: counter(section, upper-roman) "." counter(subsection);
}
<body>
  <div class="countheads">
    <h1>
      Main title
    </h1>

    <h2>
      Wuhhh
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>

    <h2>
      Whoa
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3> 
      Third point
    </h3>


  </div>
</body>

Surprisingly, even though syntax highlighters may flag the counter-set statement as an error, it actually delivers the expected functionality. So why does counter-reset fail while counter-set succeeds in this scenario?

Answer №1

To properly reset the counter, make sure to target the h2 element and not its pseudo-element:

body {
  counter-reset: section subsection;
}

.countheads > h2::before {
  counter-increment: section;
  content: counter(section, upper-roman);
}

/* .countheads > h2 + h3: use this selector in case you have an issue with Firefox */
.countheads > h2 {
  counter-reset: subsection;
}

.countheads > h3::before {
  counter-increment: subsection;
  content: counter(section, upper-roman) "." counter(subsection);
}
<body>
  <div class="countheads">
    <h1>
      Main title
    </h1>

    <h2>
      Wuhhh
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>

    <h2>
      Whoa
    </h2>

    <h3>
      First point
    </h3>

    <h3>
      Second point
    </h3>

    <h3>
      Third point
    </h3>


  </div>
</body>

Instead of using counter-set, consider utilizing counter-reset which handles existing counters on elements without creating new ones.

The value to set the counter to on each occurrence of the element. Defaults to 0 if not specified. If there isn't currently a counter of the given name on the element, the element will create a new counter of the given name with a starting value of 0 ref

In your scenario, the counter already exists so utilizing counter-reset will suffice.


Referencing the specification:

The counter-reset property instantiates new counters on an element and sets them to the specified integer values.

Additionally,

The counter-increment and counter-set properties manipulate the value of existing counters. They only instantiate new counters if there is no counter of the given name on the element yet.

Furthermore

The scope of a counter therefore starts at the first element in the document that instantiates that counter and includes the element’s descendants and its following siblings with their descendants.

Hence, when using counter-reset, you establish an instance with a specific scope, while counter-set merely adjusts the existing counter on a higher level with a different scope.

An analogy can be drawn with programming languages

int i = 0;
function a() {
   i = 0; /* this is counter-set */
}
function b() {
   int i = 0; /* this is counter-reset */
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Python Webscraping using Selenium

I'm experiencing difficulties webscraping the list of DAOs from masari.io due to some errors that I encountered: DeprecationWarning: executable_path has been deprecated, please pass in a Service object driver = webdriver.Chrome(options=options, exec ...

Uncovering Twig's Power: Navigating JSON Key Values

In my current project, I am utilizing OctoberCMS and Twig to fetch dynamic data and translations from JSON files for the front end. Here is an example snippet of code: <div class="wrapper items"> <div class="items"> {% for suggestion in ...

When should the preloader be placed within the DOMContentLoaded or load event?

I'm looking to implement a preloader on my website to ensure everything is fully loaded - images, JavaScript, fonts, etc. However, I'm unsure whether to use the following: window.addEventListener('DOMContentLoaded', () => { // code ...

Rendering the page using ReactDOM.render

Just started with ReactJS, I'm struggling to figure out why my page isn't displaying anything - <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> ...

Exploring jQuery Mobile | Moving Seamlessly between Pages

I'm relatively new to JQM and I'm working on creating a mobile application using jQuery Mobile. Here's the goal I'm aiming for: I have multiple HTML pages, each with its own CSS, JavaScript, and JQM components. What I want is to be ab ...

"Term" symbols from the Unicode Range

I have been curious about how PCRE detects word characters from any language. In my testing, I used this string: "間違つ" The PHP file is UTF-8 encoded and properly tagged with Charset=UTF-8 in the Content type tag. <?php $string="&b ...

Consolidate radio group in Vuetify platform

I'm having trouble centering the v-radio-group. Here's my current setup: <v-container grid-list-md text-xs-center> <v-form ref="form"> <div v-if="question.question_type == 'YESNO' "> <v-radio-group ...

What is the best way to utilize d3.domain for extracting both d3.min and d3.max values from various columns within a JSON dataset?

I have a JSON file that contains data from different years for "male," "female," and "both" categories. I want to set the minimum value in my domain to be the lowest value across all three columns and do the same for the maximum value. Is there a way for ...

Unable to expand or collapse rows in ng-table

Looking to implement an expand and collapse feature for ng-table, where clicking on a row should expand it to show more detail. However, currently all rows expand on click. Any ideas on how to achieve this? Any assistance would be greatly appreciated, tha ...

When you hover, there is no writing cursor in sight

I'm looking for a way to display a label on an input field and have a writing cursor show up when hovering over the label. I am not interested in using a placeholder label. Do you have any simple solutions for this? See the code snippet below: JSFiddl ...

Revolutionize iPad user experience with seamless HTML5 video integration

What is the most effective method for dynamically embedding HTML5 video to ensure compatibility with the iPad? (using pure Javascript) I'm having difficulty getting this approach to work: <div id="placeholder"><script type="text/javascript" ...

What is the best way to vertically align a Material UI component to occupy the remaining space within a container

Issue with Material UI/Grids for Login Page As a newcomer to Material UI/Grids, I am currently working on creating a login page where the layout is split into two parts. The left side occupies 5 column spaces while the right side takes up 7 column spaces. ...

An anomaly where a mysterious symbol appears in front of every dollar sign in an HTML document

I have a code written in AngularJS to display the amount in dollars. However, there is an unwanted " Â " character appearing before every " $ " character in the HTML. I am looking for a way to remove this character. Your help is greatly appreciated. Thank ...

Gulp fails to generate a CSS file after compiling Sass to CSS

Recently, I've been having trouble compiling my sass file to css. Even though it was working fine before and I haven't made any changes, now my CSS file is empty. Below is the task I am trying to accomplish: gulp.task('sass', function ...

Is it possible to eliminate the *:after effect for specific elements in my CSS?

I struggle with CSS, so I decided to use a library that includes the following CSS code: *, *:before, *:after { box-sizing: inherit ; } While this code works well for some views, it messes up others and is unnecessary for some. For instance, in this b ...

Unable to successfully change the Span Class

My webpage has the code snippet below, but it's not functioning as expected. I have tried two methods to change the span's class attribute, but they aren't working. Could someone please help me identify where the issue lies? :) <script l ...

What is the best method to ensure a TALL table header is repeated on every page in Chrome?

First time poster =) I am currently facing an issue while trying to print a long table and have the table header repeat on each page. The problem arises when the height of the <thead> reaches a certain threshold, specifically 242px in Chrome 87.0.42 ...

Utilizing Bootstrap 4: The Use of an anchor tag in a button element

I am facing a situation where I have an icon represented by the HTML code <a>, which acts as a link redirecting to a different page. This <a> is nested inside a collapsible button, meaning that clicking on the icon expands the menu before actua ...

Discover the two words before and after a span element using jQuery

data-color="red"I am looking for 2 words before and after the span tags. Here is the html code: <p>This pathway has an inner and an outer wall. The pressure <span data-color="red" class="highlight">inside the</span> eye closes the tun ...

Issues with iOS 7's absolute positioning not functioning properly within a table-responsive container

I successfully implemented fixing the first two left columns in my tables by following the instructions on . The columns are only fixed when the screen size is less than 768px, making the table scrollable (check it out on jsFiddle). This functionality work ...