Jekyll/Liquid Templating: How to group blog posts by year?

It can be done with much, much less Liquid code than in the existing answers:

{% for post in site.posts %}
  {% assign currentdate = post.date | date: "%Y" %}
  {% if currentdate != date %}
    <li id="y{{currentdate}}">{{ currentdate }}</li>
    {% assign date = currentdate %} 
  {% endif %}
    <li><a href="https://stackoverflow.com/questions/19086284/{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}

This will return exactly the HTML specified in your question:

<li id="y2013">2013</li>
<li><a href="https://stackoverflow.com/2013/01/01/foo/">foo</a></li>
<li id="y2012">2012</li>
<li><a href="http://stackoverflow.com/2012/02/01/bar/">bar</a></li>
<li><a href="http://stackoverflow.com/2012/01/01/baz/">baz</a></li>

However, this is not the optimal solution, because the year numbers are “only” list items as well.
It’s not much more Liquid code to put the year into a headline and to begin a new <ul> for each year’s posts:

{% for post in site.posts %}
  {% assign currentdate = post.date | date: "%Y" %}
  {% if currentdate != date %}
    {% unless forloop.first %}</ul>{% endunless %}
    <h1 id="y{{post.date | date: "%Y"}}">{{ currentdate }}</h1>
    <ul>
    {% assign date = currentdate %}
  {% endif %}
    <li><a href="https://stackoverflow.com/questions/19086284/{{ post.url }}">{{ post.title }}</a></li>
  {% if forloop.last %}</ul>{% endif %}
{% endfor %}

The generated HTML:

<h1 id="y2013">2013</h1>
<ul>
<li><a href="https://stackoverflow.com/2013/01/01/foo/">foo</a></li>
</ul>
<h1 id="y2012">2012</h1>
<ul>
<li><a href="http://stackoverflow.com/2012/02/01/bar/">bar</a></li>
<li><a href="http://stackoverflow.com/2012/01/01/baz/">baz</a></li>
</ul>

You can also group by month and year instead (so that the headlines are February 2012, January 2012 and so on).

To do this, you just need to replace date: "%Y" (in the second line of both above examples) by date: "%B %Y".
(%B is the full month name, see the documentation)

Leave a Comment