Customizing Jekyll theme
- Override theme defaults
- Pagination of the home page
- Links to the previous and next pages
- Categories and tags
Jekyll supports a lot of themes, which work quite well out of the box. A theme is a pre-defined set of styles, templates, and template variables. My site is based on the default Jekyll theme: minima. I had to do some customizations to make it work as I wish. Luckily, Jekyll allows customizations of almost everything of the theme. This post shows some of the customizations this site applies on top of minima.
Override theme defaults
bundle show minima can be used to find the location where the theme
artifacts are installed, e.g.:
[ouyi.github.io]$ tree $(bundle show minima) /home/ouyi/ouyi.github.io/.bundle/gems/minima-2.1.1 |-- LICENSE.txt |-- README.md |-- _includes | |-- disqus_comments.html | |-- footer.html | |-- google-analytics.html | |-- head.html | |-- header.html | |-- icon-github.html | |-- icon-github.svg | |-- icon-twitter.html | `-- icon-twitter.svg |-- _layouts | |-- default.html | |-- home.html | |-- page.html | `-- post.html |-- _sass | |-- minima | | |-- _base.scss | | |-- _layout.scss | | `-- _syntax-highlighting.scss | `-- minima.scss `-- assets `-- main.scss 5 directories, 20 files
To override the theme defaults, simply copy the related file from the theme installation location to your project, under the same folder. For example, the following customization adds feed link in the header:
[ouyi.github.io]$ diff .bundle/gems/minima-2.1.1/_includes/header.html _includes/header.html 27a28 > <a class="page-link" href="/feed.xml"><i class="fa fa-rss" aria-hidden="true"></i></a>
As another example, to include custom styles, make a copy of the main.scss file and add lines to import from any custom style sheets.
[ouyi.github.io]$ diff .bundle/gems/minima-2.1.1/assets/main.scss assets/main.scss 5a6 > @import "custom"; [ouyi.github.io]$ ls _sass/ custom.scss
By default, bundler installs gems in a central location shared by all ruby
projects. To change that, set
BUNDLE_DISABLE_SHARED_GEMS to true in the
bundler config file, e.g.:
cat .bundle/config --- BUNDLE_DISABLE_SHARED_GEMS: "true"
Pagination of the home page
By default, the minima’s home page shows the complete list of posts, which is not nice. What I would prefer are:
- split the home page into multiple pages, if that list become long
- control the number of posts displayed per page
- link from each page to the previous and next pages
It turns out that Jekyll already has some support for
pagination. To enable it, one has to
add a line to the
_config.yml file, specifying the number of items per page,
paginator: 8. With pagination enabled, Jekyll populates a
The following diff shows my changes to the default home layout, demonstrating the use of the paginator object:
Basically, instead of iterating over
site.posts, one has to loop over
paginator.posts. In addition, pagination only works with the index.html file, which references the
home layout. I also had to rename the file index.md (default) to
index.html to fix this error:
Pagination: Pagination is enabled, but I couldn't find an index.html page to use as the pagination template. Skipping pagination.
Links to the previous and next pages
The links to the previous and next pages are implemented as a macro in the
The macro requires four named parameters:
next_text. This line includes the macro and passes the required
The same macro is reused by the post layout to render the links to the previous and next posts.
As a side note, Jekyll pagination automatically generates the
rel="prev" attributes as recommended by
Those tags reside in the
<head> section of of the HTML page. They are not to
be mixed up with the hyperlinks generated by the above macro.
Categories and tags
Categories and tags are two largely overlapping concepts in Jekyll. From a
product perspective, I doubt the necessity of having both implemented, which do
not provide added value instead of confusing the users. The only difference
seems to be that categories become a part of the post URL. That means, a post
category: hadoop in the front matter would have a URL like
hadoop is the
category. That also means, posts published on the same date (or in the same
month or year) will be put into different folders, if they are of different
categories. I do not like that. One could also customize the permalink pattern
in Jekyll to remove the categories from the URL. But I chose to set the
categories of all posts to
post, e.g., the front matter of this post is:
--- layout: post title: "Customizing Jekyll theme" date: 2017-12-23 07:56:11 +0000 last_modified_at: 2017-12-31 14:05:16 category: post tags: [Blogging, Jekyll] ---
This way all posts go to the post category, which is simple and clear. The tags are used to generate a tags page, where all the posts are indexed by tags. The page generation code can be found here.
This post showed how to customize a theme in Jekyll, how to paginate the home page, how to generate links to navigate to the neighbouring pages, and discussed a bit about categories and tags. A separate post covers how to automatically generate the table of contents in Jekyll.