counter-increment on parent, but content on child

Issue

I am strugling a little bit with the css ‘counter-increment’ and ‘counter-reset’ properties. I got it working perfectly with lists already, but when it comes to header tags for example, things get a little less clear for me.

Imagine the following layout:

<div id="root">
    <div class="section">
        <h1 class="header">Header</h1>
        
        <div class="section">
            <h2 class="header">Header</h2>
            <!-- can be nested multiple times -->
        </div>
    </div>
    <div class="section">
        <h1 class="header">Header</h1>
        <!-- content -->
    </div>
</div>

I would like the header tags to be numbered (including nested counting!) but since the header tags themselves don’t embed, but their parents I can’t get it working properly. So this is what I got so far (based on logic, but not closest solution towards what I want to achieve! I tried every possible combination I could think of)

#root
{
    /* root should reset counter */
    counter-reset: section_header;
}

#root .section
{
    /* since every section has a header tag, we should count sections-divs, as they wrap children as well */
    counter-increment: section_header;
}

.section .header::before
{
    /* This would take care of the display, but I suspect it doesn't obtain the correct value since the scope of the counter is not available? */
    content: counters(section_header, ".") " ";
}

I would appreciate any direction towards a solution (if one exist).

ps. I should mention I mainly test this on Chrome, but I found this one on other browsers as well.

Edit

The format I am looking for is ‘1.1’, ‘1.2’, ‘1.2.1’ etc.. Every nested section should append another counter layer, although I can get this to work without layering (single depth), the dynamic multi-layering is kind of tricky to achieve apperently.

Solution

Update: I saw the MDN example that you probably used for inspiration in creating this. The confusing part of translating that into your markup is that they use <ol> and <li> tags which encompass child elements. This doesn’t make as much sense in the context of header <h_> elements, but it seems you have to keep the child elements within them to accomplish the same thing. I added the after elements and some light css to show where each element ends. Hope this helps.

.section {
  counter-reset: section;                /* Creates a new instance of the
                                            section counter with each ol
                                            element */
  list-style-type: none;
}

.header::before {
  counter-increment: section;            /* Increments only this instance
                                            of the section counter */
  content: counters(section, ".") " ";   /* Combines the values of all instances
                                            of the section counter, separated
                                            by a period */
}

.section{
  font-size: 16px;
  margin: 10px 0;
}
h1::after {
  content: ' (end h1)';
}

h2 {
  margin-left: 10px;
}
h2::after {
  content: ' (end h2)';
}

h3 {
  margin-left: 20px;
}
h3::after {
  content: ' (end h3)';
}
<div id="root">
  <div class="section">
    <h1 class="header">item</h1>          <!-- 1     -->
    <h1 class="header">item               <!-- 2     -->
      <div class="section">
        <h2 class="header">item</h2>      <!-- 2.1   -->
        <h2 class="header">item</h2>      <!-- 2.2   -->
        <h2 class="header">item           <!-- 2.3   -->
          <div class="section">
            <h3 class="header">item</h3>  <!-- 2.3.1 -->
            <h3 class="header">item</h3>  <!-- 2.3.2 -->
          </div>
         </h2>
         <h2 class="header">item 
          <div class="section">
            <h3 class="header">item</h3>  <!-- 2.4.1 -->
            <h3 class="header">item</h3>  <!-- 2.4.2 -->
            <h3 class="header">item</h3>  <!-- 2.4.3 -->
          </div>
        </h2>
        <h2 class="header">item</h2>      <!-- 2.5   -->
      </div>
    </h1>
    <h1 class="header">item</h1>          <!-- 3     -->
    <h1 class="header">item</h1>          <!-- 4     -->
  </div>
</div>

Answered By – git-e-up

Answer Checked By – David Marino (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.