58

scratching my head over this - help much appreciated.

I want to display a list of all my Jekyll posts, organised by category. I know Line 3 isn't correct but I can't figure out what it should be. Any ideas? Thanks!

{% for category in site.categories %}
    <h3>{{ category | first }}</h3>
    {% for post in page.categories.category %}
      {{ post.title }}<br>
    {% endfor %}            
{% endfor %}

6 Answers 6

76

Got it! Needed an intermediate posts loop before listing out individual posts

<ul>
{% for category in site.categories %}
  <li><a name="{{ category | first }}">{{ category | first }}</a>
    <ul>
    {% for post in category.last %}
      <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
    </ul>
  </li>
{% endfor %}
</ul>
2
  • 24
    I have test in my local and found the first of {{ posts }} is the category name and will be a empty line in html, so I add {% if post.url %} ahead <li><a href="{{ post.url }}">{{ post.title }}</a></li> to remove category line
    – Tanky Woo
    Commented Mar 11, 2014 at 5:49
  • hey, thanks for this, it works great! I have a question though (sorry, total jekyll noob) and probably would help improving your answer: do you know (if possible) how to put this code in a page that sits in /category/<name>, reads the <name> from the url and pulls the list of posts accordingly? (edit) my question dups here: stackoverflow.com/questions/25958652/…
    – gru
    Commented May 3, 2015 at 18:08
28

fyi, if anyone wants to just list the posts in one category, this works (differs from above example as the category returns a list of posts...

<p>Posts in category "basic" are:</p>

<ul>
  {% for post in site.categories.basic %}
    {% if post.url %}
        <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endif %}
  {% endfor %}
</ul>
2
  • 1
    This is a better answer and avoids the suggested hack that the accepted answer makes necessary. Commented Jan 30, 2018 at 5:41
  • How can I do this for a category name that contains white space such as 'foo bar'? Commented Jul 30, 2020 at 12:45
7

Now there is an official plugin available for this. jekyll-archives.

In order to make use of it,

Add jekyll-archives to your Gemfile and _config.yml file.

add a configuration something similar to the below as per your need.

jekyll-archives:
  enabled: all
  layouts:
    year: archive/year
    month: archive/month
    day: archive/day
    tag: archive/tag
    category: archive/category
  permalinks:
    year: '/:year/'
    month: '/:year/:month/'
    day: '/:year/:month/:day/'
    tag: '/tags/:name/'
    category: '/category/:name/'

The layouts can make use of the following page attributes depending on the archive type.

  • page.type - (Any one fo the following. year, month, day, tag, category)
  • page.title - (Only available for the type tag and category. Nil otherwise.)
  • page.date - (Depending on page.type you should parse out the date and month field )
  • page.posts - (List of posts for this archive)

Here is a sample layout for archive based on years

<h1>Archive of posts from {{ page.date | date: "%Y" }}</h1>
<ul class="posts">
{% for post in page.posts %}
  <li>
    <span class="post-date">{{ post.date | date: "%b %-d, %Y" }}</span>
    <a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
  </li>
{% endfor %}
</ul>
2
<h5>Categories</h5>
{% for category in site.categories %}
    {% assign cat = category[0] %}
    <h6><a href="#">{{ cat }}</a></h6>
    {% for post in site.categories[cat] %}
        <a href="{{ post.url }}">{{ post.title }}</a> <small>{{ post.date }}</small>
    {% endfor %}
{% endfor %}
0

I can't recall the exact syntax off-hand but something like the following code should retrieve the category names to allow your to retrieve posts for each category...

{% for category in site.categories %}

   {% assign cat_name = category[0] %}

  {% for post in site.categories.cat_name %}

       ...

  {% endfor%}

 {% endfor %}
1
  • Not working. Reads {% for post in site.categories[cat_name] %} Commented Oct 25, 2018 at 7:00
0

Here's an answer that uses sorting (useful!):

{% comment %}
#
#  Change date order by adding '| reversed'
#  To sort by title or other variables use {% assign sorted_posts = category[1] | sort: 'title' %}
#
{% endcomment %}
{% assign sorted_cats = site.categories | sort %}
{% for category in sorted_cats %}
{% assign sorted_posts = category[1] | reversed %}
<h2 id="{{category[0] | uri_escape | downcase }}">{{category[0] | capitalize}}</H2>
<ul>
  {% for post in sorted_posts %}
    <li><a href="{{ site.url }}{{ site.baseurl }}{{  post.url }}">{{  post.title }}</a></li>
  {% endfor %}
</ul>
{% endfor %}

This is not mine, it's taken from here.

Not the answer you're looking for? Browse other questions tagged or ask your own question.