A simple Table Of Contents solution for Jekyll
Author: | Admin |
Title: | A simple Table Of Contents solution for Jekyll |
Language: | en-US |
Created: | 18:27 on Monday, 18. October 2021 |
Modified: | 01:35 on Thursday, 21. October 2021 |
Keywords: | jekyll, liquid, code, toc, table, contents |
Excerpt: | This is a simple but fairly useful solution to display a table of contents for a post or article on a Jekyll site. It does not use additional plugins or other 3rd party software. |
Tags: | Jekyll |
Page layout: | no_sidebar |
Description
It is one of the lesser known features of Jekyll, but very useful for those who write longer articles and the feature requires very little effort to implement. We’re talking about a Table of Contents that will automatically collect all headers in an article and use them to build a hierarchical list aka ToC.
Requirements
The only requirement is to use the Kramdown markdown processor which is the default anyway and there are generally few reasons to change this. Should you need to use a different Markdown implementation for whatever reason, there are third-party plugins to implement ToC functionality. However, the method presented here will not work without Kramdown.
The implementation here requires JavaScript and the following things for optional features. The ToC itself does work without scripts though.
- jQuery
- JavaScript Cookie
The HTML / Markdown part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="toc-container" markdown="1">
<h4><span id="toc-header">Table of Contents</span>
<a href="#toc-skipped"><span title="Skip Table of Contents" class="down_symbol"></span></a>
<span style="cursor: pointer; float:right;" title="Click to show or hide ToC" id="toc-toggle" class="plusminus_symbol">
</span></h4>
{:.no_toc .clickable}
* TOC
{:toc}
</div>
<script>
if ( Cookies.get('toc-hidden', { path: _slug }) == 'true') {
$('ul#markdown-toc').hide();
$('span#toc-header').hide();
}
</script>
<div id="toc-skipped"></div>
Ideally, you should place this fragment under _includes
and include that file at the beginning of
your post or article. You can find the markdown „magic” in lines 9 and 10 of the code above. This
will generate the Table of contents by pulling all headings (there are 6 levels of headings in
kramdown) and generate an unordered list from them. The HTML code for the ToC will then replace the
* TOC
sequence. Assigning the no_toc
CSS class to a heading line will prevent that heading from
appearing in the index.
In order to spice it up a bit, I’ve added some optional stuff. First, there is a down arrow next to the header that will skip the ToC. This is useful for long articles when the Table of Contents may contain many entries and thus grows to considerable size. Second, the ToC can be hidden with a toggle button and its visibility status will be saved to a per document Cookie. Lines 12 to 17 in the code above check for the Cookie and hide the ToC before the page is loaded. This feature requires JavaScript and jQuery.
The CSS
Formatting the ToC is up to you, this is just a simple example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ul#markdown-toc, ul#markdown-toc ul {
margin-bottom: 5px !important;
}
ul#markdown-toc {
margin-bottom: 20px !important;
}
ul#markdown-toc a {
font-size: 90% !important;
}
span#toc-header {
color: orange !important;
}
/* CSS for the symbols */
/* NOTE: requires Font Awesome web font */
span.plusminus_symbol, span.down_symbol {
font: normal normal normal 18px/1 FontAwesome !important;
color: $accent_color;
margin: 0 4px 0 4px;
}
span.plusminus_symbol:before {
content: "\e43c";
}
span.down_symbol:before {
content: "\f13a";
}
JavaScript for the toggle button
This little jQuery fragment is needed to allow the ToC to be toggled visible / invisible. It also
remembers the setting in a per document cookie using the unique URL of the current document. It
should go to your $(document).ready()
function. This is optional though, the ToC generation will
work without it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// NOTE: _slug contains the page url (page.slug) and is defined elsewhere
// like: var _slug = ...
$('span#toc-toggle').on('click', function(event) {
if( $('ul#markdown-toc').is(':hidden') ) {
$('ul#markdown-toc').fadeIn();
$('span#toc-header').fadeIn();
Cookies.set('toc-hidden', 'false', { path: _slug, expires: 1350 });
} else {
$('ul#markdown-toc').fadeOut();
$('span#toc-header').fadeOut();
Cookies.set('toc-hidden', 'true', { path: _slug, expires: 1350 });
}
return false;
});
Conclusion
While there are probably more powerful solutions out there in form of Jekyll plugins, this is a very simple method of creating a Table of Contents. It’s minimalistic in design and if you skip the optional part (the toggle button) requires very little effort and has almost no dependencies.