- 2025-10-22 *
How to generate and insert a table of contents into your bearblog posts and some responsive styling for it.
A Table of Contents is one of the first things I made and styled when I started using Bearblog so I could insert it into my weekly digest posts. I have tweaked it a lot of times since then, and probably will continue to tweak it. It is simply a div with a header and a nested list.
The styling features:
- Responsive margins and padding that makes the list more compact on smaller screen sizes.
- Different markers for different levels of nested lists, e.g. 1. i. a.
- Takes up about half the body width on wide screens, but takes up the whole width of the body on smaller screens (responsive margin-right...
- 2025-10-22 *
How to generate and insert a table of contents into your bearblog posts and some responsive styling for it.
A Table of Contents is one of the first things I made and styled when I started using Bearblog so I could insert it into my weekly digest posts. I have tweaked it a lot of times since then, and probably will continue to tweak it. It is simply a div with a header and a nested list.
The styling features:
- Responsive margins and padding that makes the list more compact on smaller screen sizes.
- Different markers for different levels of nested lists, e.g. 1. i. a.
- Takes up about half the body width on wide screens, but takes up the whole width of the body on smaller screens (responsive margin-right).
- Hover effect with a floating down arrow on links.
After a post I made about my laborious process for generating a ToC fellow Bearblogger Reed (ReedyBear) made a javascript plug-in that you can drop into your bearblog dashboard customize page. It will place a button on your post editor page that when pressed will generate a ToC from the Markdown in the post and put it in your clipboard. You can then paste it into your post wherever you want it. It’s magic! Everyone say “thank you Reed”.
It is important that you use headings in order in your posts for this to work, and in general for accessibility reasons. H1 is reserved for the post title, so your section headers within a post should start at H2 i.e. ## Heading 2
and sub-sections should be H3 ### Heading 3
and so on.
As always, if you use any of my code leave me an upvote and/or send me an email! I love to see other people’s customizations.
Contents:
HTML
I’ve made a more elaborate than usual ToC and put in a bunch of unnecessary tabbing and multiple levels so you can see clearly what’s going on with the nested lists. You can mix and match ordered and unordered lists, but I haven’t done styling for every possible combination thereof. The ToC in general is H2: ordered, H3+: unordered.
<div class="toc">
<h2>Contents:</h2>
<ol>
<li><a href="#heading-2-numbered-section">Heading 2: Numbered Section</a>
<ol>
<li><a href="#heading-3-numbered-sub-section">Heading 3 - Numbered Sub-section</a>
<ol>
<li><a href="#heading-4-numbered-sub-sub-section">Heading 4 + Numbered Sub-sub-section</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#heading-2-unnumbered-section">Heading 2: Unnumbered Section</a>
<ul>
<li><a href="#heading-3-unnumbered-sub-section">Heading 3 - Unnumbered Sub-section</a>
<ul>
<li><a href="#heading-4-unnumbered-sub-sub-section">Heading 4 + Unnumbered Sub-sub-section</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#heading-2-final-section">Heading 2: Final Section</a></li>
</ol>
</div>
CSS
I use variables for colours and font sizes in my theme. Variables are defined at the very top of your CSS under :root
. I have included all the CSS required to get pretty much exactly the same thing as I have in a codepen, but I’ll include the basic CSS here.
Nested Lists
A lot of the table of contents styling is dependent on general list styling, for example the fancy markers. You can see a full list of markers available from base HTML on MDN, and there are more than you might think, but you can also just put in your own unicode character. Bear in mind not all characters are available on all fonts. The clamp on the padding-inline
causes the padding to reduce on smaller screens to make it more compact.
/* lists and nested lists */
ol, ul {
list-style-position: outside;
line-height: 1.2em;
padding-inline: clamp(0.625rem, calc(0.339rem + 1.429vw), 1.625rem) 0;
margin: 1rem;
}
li {
margin: 0 clamp(0.25em, calc(0.068em + 0.909vw), 0.75em);
}
ol {
list-style-type: decimal;
}
ol li::marker {
font-weight: 800;
}
ol li > ol {
list-style-type: lower-roman;
padding: unset;
margin: 0 0 0 1.2em;
}
ol li > ol li > ol {
list-style-type: lower-alpha;
}
ul {
list-style-type: square;
}
ul li > ul {
list-style-type: '\2023 '; /* small right pointing triangle */
padding: unset;
margin: 0 0 0 1.2em;
}
ul li > ul li > ul {
list-style-type: circle;
}
Table of Contents
The clamp margin on the .toc
div are what allows it to be about half the size of the body (~326px) on wider screens but take up the whole width of the body on smaller screens. It also reduces the padding on smaller screens to make it more compact, even moreso than in the default list style. You can use a clamp calculator to adjust these properties. My font sizes also reduce based on screen size with a clamp using this other calculator.
To prevent the browser fallback stylesheet from adding unwanted padding and margins I have used many instances of unset
. It doesn’t look like much, but it took me a really long time to figure out where my lists were getting random padding and margins from.
/* table of contents */
.toc {
display: block;
padding: clamp(0.375em, calc(0.268em + 0.536vw), 0.75em);
margin: 0 clamp(0.5em, calc(-4.768em + 26.339vw), 18.938em) 0 0;
border: 2px dotted #9674cc; /* dark mode: #8439d */
border-radius: 4px;
}
.toc a {
text-decoration: none;
}
.toc a:hover:after {
content: ' \2193'; /* down pointing arrow */
vertical-align: top;
font-size: clamp(1rem, 0.973rem + 0.182vw, 1.1rem);
font-weight: 600;
}
.toc h2 {
font-size: clamp(1.2rem, 1.152rem + 0.32vw, 1.4rem);
font-weight: 500; /* this may not work for all fonts, many only have normal=400 or bold=600 */
margin: unset;
padding: unset;
border: none;
line-height: 1em;
}
.toc :is(ol, ul) {
font-size: clamp(1rem, 0.973rem + 0.182vw, 1.1rem);
margin: unset;
padding-top: 0.05em;
padding-inline: clamp(1rem, calc(0.821rem + 0.893vw), 1.625rem) 0;
line-height: 1.2;
}
.toc ol li,
.toc ul li,
.toc ol li > ul,
.toc ol li > ol,
.toc ul li > ul {
padding: unset;
}
Live Codepen
See the Pen Bearblog Table of Contents by anarchaeopteryx (@anarchaeopteryx) on CodePen.
And that’s it! Happy ToCing.