2

I need to have text formatted in table where second column contains the text, some rows contains heading H1 - H5. I would like to use auto numbering for the heading but the increment does not work within table.

Problem is that the H2 level counter is not increasing there is always 1.1 as the heading number.

Can you please help, where is the problem?

body {
  counter-reset: h1counter;
}

h1 {
  counter-reset: h2counter;
}

h2 {
  counter-reset: h3counter;
}

h1:before {
  counter-increment: h1counter;
  content: counter(h1counter) ". ";
}

h2:before {
  counter-increment: h2counter;
  content: counter(h1counter) "."counter(h2counter) ". ";
}

h3:before {
  counter-increment: h3counter;
  content: counter(h1counter) "."counter(h2counter) "."counter(h3counter) ". ";
}
<table>
  <tbody>
    <tr>
      <td>1</td>
      <td>
        <h1>Heading 1</h1>
      </td>
    </tr>
    <tr>
      <td>2</td>
      <td>
        <h2>Heading 1.1</h2>
      </td>
    </tr>
    <tr>
      <td>3</td>
      <td>
        <h2>Heading 1.2</h2>
      </td>
    </tr>
    <tr>
      <td>4</td>
      <td>
        <h1>Heading 2.</h1>
      </td>
    </tr>
  </tbody>
</table>
isherwood
  • 58,414
  • 16
  • 114
  • 157
Marek
  • 23
  • 3
  • 1
    Not sure this is possible as the counters are based on the parent. *Maybe* you could do something by incrementing on the `tr` but I doubt it. – Paulie_D Jan 25 '22 at 17:52
  • 1
    Frankly, this does not look like something suitable for a `table` at all, – Paulie_D Jan 25 '22 at 17:55
  • Yes, tables should not be used for layout. They're almost exclusively for data presentation. – isherwood Jan 25 '22 at 20:57

1 Answers1

1

Solution #1. This task can be solved using the counter-set CSS property. Example below:

body {
  counter-reset: h1counter h2counter h3counter;
}

body h1 {
  counter-set: h2counter 0;
}

body h2 {
  counter-set: h3counter 0;
}

h1:before {
  counter-increment: h1counter;
  content: counter(h1counter) ". ";
}

h2:before {
  counter-increment: h2counter;
  content: counter(h1counter) "."counter(h2counter) ". ";
}

h3:before {
  counter-reset: h3counter;

  counter-increment: h3counter;
  content: counter(h1counter) "."counter(h2counter) "."counter(h3counter) ". ";
}
<table>
  <tbody>
    <tr>
      <td>1</td>
      <td>
        <h1>Heading 1</h1>
      </td>
    </tr>
    <tr>
      <td>2</td>
      <td>
        <h2>Heading 1.1</h2>
      </td>
    </tr>
    <tr>
      <td>3</td>
      <td>
        <h2>Heading 1.2</h2>
      </td>
    </tr>
    <tr>
      <td>4</td>
      <td>
        <h1>Heading 2.</h1>
      </td>
    </tr>
    <tr>
      <td>5</td>
      <td>
        <h2>Heading 2.1</h2>
      </td>
    </tr>
    <tr>
      <td>6</td>
      <td>
        <h2>Heading 2.2</h2>
      </td>
    </tr>
  </tbody>
</table>

Unfortunately, counter-set is a new property and is only supported by newer browsers and it doesn't work in Safari.

Solution #2. Also, this problem can be solved with the help of JS and data attributes. Example below:

let h1Counter = 0,
  h2Counter = 0,
  h3Counter = 0;

document.querySelectorAll('h1, h2, h3').forEach((el) => {
  if (el.matches('h1')) {
    h1Counter++;
    h2Counter = 0;
    el.dataset.counter = `${h1Counter}`;
  } else if (el.matches('h2')) {
    h2Counter++;
    h3Counter = 0;
    el.dataset.counter = `${h1Counter}.${h2Counter}`;
  } else { // h3
    h3Counter++;
    el.dataset.counter = `${h1Counter}.${h2Counter}. ${h3Counter}`;
  }
})
h1:before,
h2:before,
h3:before {
  content: attr(data-counter) ". ";
}
<table>
  <tbody>
    <tr>
      <td>1</td>
      <td>
        <h1>Heading 1</h1>
      </td>
    </tr>
    <tr>
      <td>2</td>
      <td>
        <h2>Heading 1.1</h2>
      </td>
    </tr>
    <tr>
      <td>3</td>
      <td>
        <h2>Heading 1.2</h2>
      </td>
    </tr>
    <tr>
      <td>4</td>
      <td>
        <h1>Heading 2.</h1>
      </td>
    </tr>
    <tr>
      <td>5</td>
      <td>
        <h2>Heading 2.1</h2>
      </td>
    </tr>
    <tr>
      <td>6</td>
      <td>
        <h2>Heading 2.2</h2>
      </td>
    </tr>
  </tbody>
</table>
Oleg Barabanov
  • 2,468
  • 2
  • 8
  • 17