Optimize for happiness

Life is easier with simple scripting. Grateful for everyone's encouragement and support!

View this project on GitHub

Add pages of blog posts in GitHub Pages

2023.06.19   •   9 min read

I started with a regular GitHub theme, but it has nothing to help with writing blog posts or organizing them into pages.

For pagination, the starting point would be the Jekyll doc on pagination. Except it has extra steps not needed for github. As GitHub doc explains, the jekyll-paginate plugin is already enabled and could not even be disabled. So that is not a missing link. What is needed is the following.

Essential: /index.html

I had /index.md as the main page that used the default layout (from _layouts/default.html). Pagination would not display no matter what I did. I had to rename the /index.md to /index.html for anything below to work. Ridiculous, but true.

How many blog posts per page?

You have to specify your choice in the _config.yml file. Add whatever number you like:

paginate: 5
show_excerpts: true
future: true
    # GitHub pages will publish future posts

This is an example that will create a page for every 5 blog posts, will show excerpts (we will code that choice later) and is set to show the future posts (default is false - future posts will only show when that date comes).

Show pages of your blog posts

Now on to the actual instructions to show the pages. I put that in _layouts/default.html right inside the main section and after the {{ content }} that displays the contents of the main page (and only on the main page - an if statement takes care of that).

{% if site.paginate %}
    {% assign posts = paginator.posts %}
  {% else %}
    {% assign posts = site.posts %}
{% endif %}
        
{% if posts.size > 0 %}
  
    {% for post in posts %}
      <h3>
        <a class="post-link" href="{{ post.url | relative_url }}">
          {{ post.title | escape }}
        </a>          
      </h3>
      <h6>
      <span>
        {{ post.date | date: site.date_format }} &nbsp; &bull; &nbsp;
        {% assign words = post.content | number_of_words %}
        {% if words < 360 %}
          1 min read
        {% else %}
          {{ words | divided_by:180 }} min read
        {% endif %}
      </span>
      </h6>
      {% if site.show_excerpts %}
        {{ post.excerpt }}
      {% endif %}
    {% endfor %}
    
    {% if site.paginate %}
      <span class="pagination">
          {% if paginator.previous_page %}
            <a class="pagination-item older" href="{{ paginator.previous_page_path | relative_url }}">Previous (page {{ paginator.previous_page }})</a>
          {% else %}
            <span class="pagination-item older">Previous</span>
          {% endif %}
          
          <a class="pagination-item" href="/">Main page</a>
          
          {% if paginator.next_page %}
            <a class="pagination-item newer" href="{{ paginator.next_page_path | relative_url }}">Next (page {{ paginator.next_page }})</a>
          {% else %}
            <span class="pagination-item older">Next</span>
          {% endif %}
      </span>
    {% endif %}
  
{% endif %}

The first instruction is:

{% assign posts = paginator.posts %}

So now we have “posts”. It is a good idea to check that there are any posts, done with {% if posts.size > 0 %}.

For every post we will display the post.title as a heading.

Optional: As the next heading I added the post date. Also I added an estimation on how long of a read that post is, based on word count.

If the _config.xml says show_excerpts: true then an excerpt (by default that means the first paragraph) of a post will follow. You do have options to define what an excerpt is, refer to the Jekyll doc on post excerpts.

That is it for the actual list of posts on a page.

At the bottom, add page navigation

The code above deals with links to previous, next, and back to the main page. It is useful as you browse through the pages of your blog post list.

That is all under the <span class="pagination"> section. First, check if there is such a thing as a previous page and if so, link to it. If not, just show a (grayed out) word for consistency. You could choose to show nothing at all, or some symbol.

Then the Main page link is shown, in the center.

Lastly, the same is done for the next page as for the previous. If one exists on that page.

Now, let’s make the bottom page links pretty. I used a modified version of another theme. Here is an example code in _sass/<your-main-css-code-file>.scss.

/*  
 * PAGINATION
 */

.pagination {
      overflow: hidden;
      margin-left: 0;
      margin-right: 0;
      font-family: $sans-serif;
      font-size: $base-font-size + 1px;
      color: $header-line-color;
      text-align: center;
}

/* Pagination items can be `span`s or `a`s */
.pagination-item {
      display: block;
      padding: 10px;
}
.pagination-item:first-child {
      margin-bottom: -1px;
}

/* Only provide a hover state for linked pagination items */
a.pagination-item:hover {
      background-color: #f5f5f5;
}

@media (min-width: 100px) {
      .pagination {
            margin: 0 0;
      }
      .pagination-item {
            float: left;
            width: 30%;
      }
      .pagination-item:first-child {
            margin-bottom: 0;
            border-top-left-radius:    $border-radius;
            border-bottom-left-radius: $border-radius;
      }
      .pagination-item:last-child {
            margin-left: -1px;
            border-top-right-radius:    $border-radius;
            border-bottom-right-radius: $border-radius;
      }
}

Notice there are a few definitions in the css code above (everything starting with $). This allows me to keep a list of variables on top of the file. If I change the variable on top of the whole file, the change propagates throughout. It is great for consistency. It is also great if you want to get into creating light and dark themes for your site: just assign different values for color variables and you have another color theme.

$sans-serif: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
$base-font-size: 15px;
$header-line-color: #ccc;
$border-radius: 4px;

These are the variables used in the pagination section. Showing here as an example. Well, as a starting point. How would you improve it?

Resources: