How I Added Teaser and Read-more Functionality to My Jekyll Blog on GitHub Pages

For my Jekyll blog, I want to give readers a typical river of news1 list of post titles with teasers. I also want readers to be able to paginate through past posts, via a series of pages listing ten posts per page.

When readers click on a “Read more” link in a post teaser, I’d like them to go to the full post text, starting from the last point they read, which is typically not at the top of the post.

Here’s how I used Jekyll’s template system to get exactly the feature-set I want.

Pagination

Jekyll provides detailed documentation for how to paginate posts .

For my pagination feature I add these variables and values to my Jekyll _config.yml file.

paginate: 10
paginate_path: "blog/page:num"

The paginate variable set to 10 tells Jekyll to list ten posts per page.

The paginate_path tells Jekyll what URL structure to use when generating each page in the paginated series.

The settings above tells Jekyll to create URLs like: /blog/page2/, /blog/page3/, etc.

You can change these patterns to fit your own blog structure.

For example, the value posts/page-:num would generate a URL pattern like, /posts/page-2/.

Page one of my blog is my homepage, so I must tell Jekyll to render the first page in its pagination series differently from the other pages. Jekyll provides snippets to render paginated posts. In my case I needed to use the second code snippet on the page which handles the “page one edge-case.”

Teasers (AKA Excerpts)

Jekyll’s default post excerpts behavior is to use the first paragraph of a post as the post’s excerpt/teaser. It does this by grabbing the first block of text from the beginning of the post to the first excerpt_seperator it finds.

The excerpt_seperator is a Jekyll variable which may be set in the _config.yml file.

By default its value is:

excerpt_separator: "\n\n"

For my teaser feature I set the value to:

excerpt_separator: <!–break–>

The separator value could be almost anything. In order to change it from using the first line break, I chose to use the same separator as Drupal2. (Helpful because I migrated my content from Drupal.)

The change gives me two advantages right away:

  1. I control exactly where my excerpt breaks in my post (using an html comment which is not rendered directly to the reader)
  2. I can create short status-like posts which use the full post content in the post listings (by not adding the <!–break–> to the post body)

If I need anything beyond the two options above, I can always override automatic excerpts by adding excerpt to my post’s YAML Front Matter like so:

title: "How I Added Teaser and Read-more Functionality to My Jekyll Blog on GitHub Pages"
excerpt:
         <h3>Add a Custom Excerpt to Your Post</h3>
         <p>Find out how!</p>

I want to give readers the ability to:

  1. start reading a post teaser,
  2. click “Read more” at the end of the teaser,
  3. continue reading the full post right where they left off in the teaser,
  4. without having to scan down the full post past the point they already read.

Here’s how I enable this feature with Jekyll.

With the code below, I render each blog post in the paginated list set. The code is close to the snippet Jekyll provides in its documentation.

Take a look at the code, and then I’ll explain the lines I use generate my teasers with the “Read more” link.

Jekyll uses the Liquid templating language to process templates.

In lines 7 to 12 above, I use Liquid’s capture tag to capture the number of words in the post excerpt (post.excerpt) and the number of words in the full post content (post.content).

I then compare the two values using:

If the word counts are equal, then the full post content is in the excerpt and has been rendered, so there’s no need to output the “Read more” link.

When the “Read more” link is generated, as shown in line 14 above, I render the href for the link as:

When readers click the link, they go to an anchor tag with the #read-more id. The anchor is placed at the point in the post body which they read to in the teaser.

The last step is to render the anchor tag at the proper place in the body content of the full post.

This time I use the ‘replace’ Liquid filter when I render my post page content.

In the code above, I replace the excerpt_separator ( <!–break–> ) with the #read-more anchor. This works out great because posts are excerpted at the point of the separator, and the reader is taken to an anchor in the full post at the same point.

Side note: Because I use some relative positioning in my page layout, I use the .anchor CSS class to make sure the reader’s browser scrolls to the correct spot. See the CSS below.

a.anchor{display: block; position: relative; top: -99px; visibility: hidden;}

Close

Jekyll’s variable and configuration system, combined with its Liquid-based template system, let me get exactly the feature-sets I want for my blog.

I’m glad to say that I have not had to compromise on any features since my switch to Jekyll from Drupal.

I encourage to dig into Jekyll to develop the features you’d like for your blog.

Good luck.


  1. a long list of all the posts, sorted by time.

  2. You could always use the Wordpress <!--more-->as described in this post

Share or Comment via Twitter