If you take a look at my website and click on a category (for example this one is categorized as jekyll) it will take you to a new page /categories/jekyll/
and you will be able to see all the 'jekyll' posts.
This is actually quite simple to set up. I'll show you step by step how to use a plugin so that a page like /category/:category
(where :category
is the chosen category) gets automatically generated.
Step 1
Create a plugin directory in the root of your project and name it _plugins
.
Step 2
Inside this directory create a file and name it categories.rb
. Copy and paste the following code into the file. (The code comes straight from Jekyll documentation on generators)
module Jekyll
class CategoryPageGenerator < Generator
safe true
def generate(site)
if site.layouts.key? 'category_index'
dir = site.config['category_dir'] || 'categories'
site.categories.each_key do |category|
site.pages << CategoryPage.new(site, site.source, File.join(dir, category), category)
end
end
end
end
# A Page subclass used in the `CategoryPageGenerator`
class CategoryPage < Page
def initialize(site, base, dir, category)
@site = site
@base = base
@dir = dir
@name = 'index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'category_index.html')
self.data['category'] = category
category_title_prefix = site.config['category_title_prefix'] || 'Category: '
self.data['title'] = "#{category_title_prefix}#{category}"
end
end
end
The above is what is called a generator. Generators need to implement the generate
method. This generator is what is going to allow us to have a page for each of our categories without us having to manually create this.
Step 3
Now we need a layout for our categories pages. Inside your _layouts
folder create one called category_index.html
. You can create this layout yourself to fit your site design but the following is an example of mine
---
layout: default
---
<section class="small-intro">
<div class="container">
<h2>
{{page.category | capitalize}}
</h2>
</div>
</section>
<section class="blog">
<div class="container">
{% for post in site.posts %} {% if post.categories contains page.category %}
<div class="blog-container">
<div class="title-excerpt">
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
</div>
<div class="date-categories">
<div class="categories">
{% for category in post.categories%}
<div class="category">
<a href="/categories/{{category}}">{{ category }}</a>
</div>
{% endfor %}
</div>
<div class="date">
<p>{{ post.date | date_to_string }}</p>
</div>
</div>
</div>
{% endif %} {% endfor %}
</div>
</section>
As you can see we are getting the page.category
which is the category you clicked on or are searching for.
Then we loop through our posts and if the post category matches the category in the page we will display the post.
That's it! To summarize, the generator plugin from step 2 will run after Jekyll knows all the categories for the site but before the site is generated.
Don't forget to update the links in the places you are cycling through your categories to link to
<a href="/categories/{{category}}">{{ category }}</a>
Bonus
We can also make a /category
like I have here. To do this create a categories
directory in the root directory. Inside create an index.html
page.
Aside from just listing each category I am also listing the count for each category.
Your /category/index.html
should look like this:
---
layout: default
title: Ed Ruiz - Categories
---
<section class="small-intro">
<div class="container">
<h2>
All categories
</h2>
</div>
</section>
<section class="blog">
<div id="categories">
<div class="container">
{% for cat in site.categories %}
<div class="category">
{% for inner in cat%} {% if forloop.first == true %}
<span class="span-cat">
<a href="/categories/{{cat[0]}}">{{cat[0]}}</a></span
>
-
<span class="span-count">
<a href="/categories/{{cat[0]}}"
>{{site.categories[inner].size}}</a
></span
>
{% endif %} {% endfor %}
</div>
{% endfor %}
</div>
</div>
</section>
Now if you head over to /category
you should see all the categories and the amount of posts.
I hope this helps you set up the dynamic categories and category pages like I have set up on my site.