This is the eigth part of some posts on using CSS in and with DT/DTTG. Though I wrote it as a single piece, I broke it up in smaller installments to keep the posts (barely) managable. Please let me know (preferably by a PM) if you find errors of any kind or are missing details. I’ll correct the first ones and try to help with the second ones.
Numbered headings
By default, headings appear in HTML just as you typed them in your Markdown
document. Especially in scientific publications, some kind of systematic numbering is often required. You can of course provide that by simply adding the number to your heading. However, that requires a lot of manual work and more so whenever you add, move or delete parts of the document.
CSS offers a much simpler way to render systematically numbered headlines with its concept of “counters”. You can read all about counters at MDN. The following examples are just a very limited demonstration of their abilities.
Let’s assume a Markdown document like this
# First heading
# Second heading
## First sub-heading of second heading
# Third heading
## First sub-heading of third heading
### Third heading's first sub-heading's first subheading
## Second sub-heading of third heading
# Fourth heading
Rendering that as HTML results in something like this
Adding a counter to the headings requires three steps:
- creating and initializing the counter with
counter-reset
, - incrementing it with
counter-increment
, and - displaying it with
content
andcounter()
.
For the first level headings, you’d do it like this:
body {
counter-reset: h1;
}
h1::before {
counter-increment: h1;
content: counter(h1) ". ";
}
First, you create a counter named h1
in the CSS rule for the body
element. Its value is set to 0
by default. Then comes the ::before
pseudo-element for the h1
element. It’s different from other CSS selectors in that it creates an element (a pseudo one, though) in the h1
element just before anything that is already part of this element. So the (pseudo-HTML) for the first heading would look like
<h1><before>…</before>First heading</h1>
Note that this before
element does not exist! However, you can create and style it in a stylesheet like here. The rule for h1::before
first increments the counter h1
with counter-increment
. Since it started out with 0
because of the body
rule, it will now be 1
. Then this value is prepended to the content of h1
with the content:
directive: counter(h1)
gets the value of the counter, and ". "
appends a dot and a space. After all that, the headlines look like this:
Now adding the corresponding rules for 2nd and 3rd level headings is a lot easier:
h1 {
counter-reset: h2;
}
h2 {
counter-reset: h3;
}
h2::before {
counter-increment: h2;
content: counter(h1) "." counter(h2) ". ";
}
h3::before {
counter-increment: h3;
content: counter(h1) "." counter(h2) "." counter(h3) ". ";
}
The only new things here are the content:
definitions for the level 2 and 3 headings and the counter-reset
s: Whenever a new level 1 heading appears, the h2
counter must be reset so that the next level 2 heading is numbered with 1 again. The same holds for a new level 2 heading that must reset the h3
counter.
If you now move the line “# Second Heading” down to just before “# Third heading”, you’ll get this HTML:
As you can see, the former “2.1 First sub-heading of second heading” has now become “1.1 First sub-heading of second heading”, since it’s now following the first h1
element, no longer the second one.
If you delete the line “# Second Heading” completely, the numbering for all subsequent headings will be adjusted:
CSS counters can not only be used for headings but also for lists, footnotes and
links. You’re not limited to arabic numerals but can define your own
counter-style
.