I am trying to create multiple levels of counters in a html table, but this is not working as I expected. The first counter works ok, but the next counters do not work. Some
CSS is designed to take advantage of the hierarchical nature of HTML, hence the "cascading" style sheets. The element structure of your table is linear and as such defeats the efficiency of the cascade. I understand that there are circumstances when you might not have control over the HTML structure of the document in which case a CSS kluge might be in order. Otherwise, I would suggest restructuring your elements to match the same hierarchy of the layout you're trying to achieve. MUCH simpler and more scalable code.
HTML:
<ul>
<li class='taskstep'>Step 1</li>
<li class='taskstep'>Step 2
<ul>
<li class='risk'>Risk 1</li>
<li class='risk'>Risk 2</li>
</ul>
</li>
<li class='taskstep'>Step 3
<ul>
<li class='risk'>Risk 3</li>
</ul>
</li>
<li class='taskstep'>Step 4
<ul>
<li class='risk'>Risk 4</li>
<li class='risk'>Risk 5</li>
<ul>
<li class='measure'>Measure 1</li>
<li class='measure'>Measure 2</li>
<li class='measure'>Measure 3</li>
<li class='measure'>Measure 4</li>
</ul>
<li class='risk'>Risk 6</li>
<li class='risk'>Risk 7</li>
</ul>
</li>
</ul>
CSS:
ul{
list-style-type: none;
counter-reset: foo;
}
li:before{
counter-increment: foo;
content: counters(foo,".") ". ";
}
Demo
There are 2 problems here:
The direct parent of the first counted element should contain all the other counted elements. In your case, the first counted element is a td
in a row, so its parent is a tr
but all the other counted elements have their own parents of tr
(which are siblings of the parent of the first counted element). So to fix this I think you have to set the class on the tr
and count it there.
The counter-reset
and counter-increment
can be overridden, that means if at one tr
, you need to use counter-reset
and counter-increment
for more than 1 counter variable, you need to put them on the same declaration (space-separated) for counter-reset
and counter-increment
.
From 2 points above, here is the code it should be:
HTML:
<table class="tasksteps">
<thead>
<tr>
<td>TaakStep</td>
<td>Risk</td>
<td>Measure</td>
</tr>
</thead>
<tbody>
<tr class="taskstep">
<td class="taskstep t1">Step 1</td>
<td></td>
<td></td>
</tr>
<tr class="taskstep risk">
<td class="taskstep t2">Step 2</td>
<td class="risk">Risk 1</td>
<td></td>
</tr>
<tr class="risk">
<td class="t3"></td>
<td class="risk">Risk 2</td>
<td></td>
</tr>
<tr class="taskstep risk">
<td class="taskstep t2">Step 3</td>
<td class="risk">Risk 3</td>
<td></td>
</tr>
<tr class="taskstep risk">
<td class="taskstep t2">Step 4</td>
<td class="risk">Risk 4</td>
<td></td>
</tr>
<tr class="risk">
<td class="t4"></td>
<td class="risk">Risk 5</td>
<td class="measure">Measure 1</td>
</tr>
<tr>
<td class="t5"></td>
<td></td>
<td class="measure">Measure 2</td>
</tr>
<tr>
<td class="t5"></td>
<td></td>
<td class="measure">Measure 3</td>
</tr>
<tr>
<td class="t5"></td>
<td></td>
<td class="measure">Measure 4</td>
</tr>
<tr class="risk">
<td class="t3"></td>
<td class="risk">Risk 6</td>
<td></td>
</tr>
<tr class="risk">
<td class="t4"></td>
<td class="risk">Risk 7</td>
<td class="measure">Measure 5</td>
</tr>
</tbody>
</table>
CSS:
table.tasksteps {
counter-reset: tasksteps;
}
tr.taskstep {
counter-reset: risks;
counter-increment: tasksteps;
}
tr.risk {
counter-reset: measures;
counter-increment: risks;
}
tr.taskstep.risk {
counter-reset: risks measures;
counter-increment: tasksteps risks;
}
td.measure {
counter-increment: measures;
}
td.taskstep:before {
content: counter(tasksteps) '. ';
}
td.risk:before {
content: counter(tasksteps) '.' counter(risks) '. ';
}
td.measure:before {
content: counter(tasksteps) '.' counter(risks) '.' counter(measures) '. ';
}
I played a bit, and it seems the issue was resetting all the counters on the same line in the body.
Here's the FIDDLE.
CSS
body {
counter-reset: tasksteps risks measures;
}
table td {
width: 120px;
border: 1px solid black;
}
td.taskstep {
counter-increment: tasksteps;
}
td.risk {
counter-increment: risks;
}
td.measure {
counter-increment: measures;
}
td.taskstep:before {
content: counter(tasksteps) '. ';
}
td.risk:before {
content: counter(tasksteps) '.' counter(risks) '. ';
}
td.measure:before {
content: counter(tasksteps) '.' counter(risks) '.' counter(measures) '. ';
}