Skip to content

Category Template

The category template renders pages that display all posts within a specific category. It provides a filtered view of blog content organized by category.

└── theme
└── templates
└── category.liquid

Category pages are accessible at:

  • /categories/:slug

For example: /categories/news, /categories/announcements

The category template receives these variables:

PropertyTypeDescription
idstringUnique identifier
titlestringCategory name
slugstringURL-safe identifier

An array of all published posts in this category:

PropertyTypeDescription
postsarrayPosts belonging to this category

Each post in the array has access to all standard post properties (title, description, publishDate, authors, image, etc.).

{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}
<div class="category-page">
<header class="category-header">
<h1>{{ category.title }}</h1>
<p class="post-count">{{ posts.size }} {% if posts.size == 1 %}post{% else %}posts{% endif %}</p>
</header>
<div class="posts-list">
{% if posts.size > 0 %}
{% for post in posts %}
<article class="post-card">
{% if post.image %}
<img
src="{{ post.image | image_url: width: 400, height: 250 }}"
alt="{{ post.title }}"
loading="lazy"
>
{% endif %}
<div class="post-card__content">
<h2>
<a href="/posts/{{ post.slug }}">{{ post.title }}</a>
</h2>
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%B %d, %Y' }}
</time>
{% endif %}
{% if post.description %}
<p>{{ post.description | truncate: 150 }}</p>
{% endif %}
</div>
</article>
{% endfor %}
{% else %}
<p class="no-posts">No posts in this category yet.</p>
{% endif %}
</div>
</div>
{% endcapture %}
{% for post in posts %}
<article class="post-item">
<h2><a href="/posts/{{ post.slug }}">{{ post.title }}</a></h2>
<div class="post-meta">
{% if post.authors.size > 0 %}
<span class="author">
By {{ post.authors.first.name }}
</span>
{% endif %}
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%b %d, %Y' }}
</time>
{% endif %}
</div>
</article>
{% endfor %}
{% for post in posts %}
<article class="post-card">
{% if post.image %}
<img
src="{{ post.image | image_url: width: 400, height: 250 }}"
alt="{{ post.title }}"
class="post-card__image"
loading="lazy"
>
{% elsif settings.global.fallbackImage %}
<img
src="{{ settings.global.fallbackImage | image_url: width: 400, height: 250 }}"
alt=""
class="post-card__image post-card__image--fallback"
loading="lazy"
>
{% endif %}
<h3>{{ post.title }}</h3>
</article>
{% endfor %}
{% assign current_month = '' %}
{% for post in posts %}
{% assign post_month = post.publishDate | date: '%B %Y' %}
{% if post_month != current_month %}
{% unless current_month == '' %}
</div>
{% endunless %}
<h3 class="month-header">{{ post_month }}</h3>
<div class="month-posts">
{% assign current_month = post_month %}
{% endif %}
<article class="post-item">
<a href="/posts/{{ post.slug }}">{{ post.title }}</a>
<time>{{ post.publishDate | date: '%d' }}</time>
</article>
{% if forloop.last %}</div>{% endif %}
{% endfor %}
{% layout 'layouts/default.liquid' %}
{% capture content_for_layout %}
<div class="category-page">
{# Breadcrumb navigation #}
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/blog">Blog</a></li>
<li aria-current="page">{{ category.title }}</li>
</ol>
</nav>
{# Category header #}
<header class="category-header">
<h1>{{ category.title }}</h1>
<p class="category-meta">
{{ posts.size }} {% if posts.size == 1 %}article{% else %}articles{% endif %}
</p>
</header>
{# Posts listing #}
{% if posts.size > 0 %}
<section class="category-posts">
{# Featured post (first/latest) #}
{% assign featured = posts.first %}
<article class="featured-post">
{% if featured.image %}
<a href="/posts/{{ featured.slug }}" class="featured-post__image-link">
<img
src="{{ featured.image | image_url: width: 1200, height: 500 }}"
alt="{{ featured.title }}"
>
</a>
{% endif %}
<div class="featured-post__content">
<h2>
<a href="/posts/{{ featured.slug }}">{{ featured.title }}</a>
</h2>
<div class="featured-post__meta">
{% if featured.publishDate %}
<time datetime="{{ featured.publishDate }}">
{{ featured.publishDate | date: '%B %d, %Y' }}
</time>
{% endif %}
{% if featured.authors.size > 0 %}
<span class="author">by {{ featured.authors.first.name }}</span>
{% endif %}
</div>
{% if featured.description %}
<p class="featured-post__excerpt">{{ featured.description }}</p>
{% endif %}
<a href="/posts/{{ featured.slug }}" class="btn">Read Article</a>
</div>
</article>
{# Remaining posts grid #}
{% if posts.size > 1 %}
<div class="post-grid">
{% for post in posts offset: 1 %}
<article class="post-card">
<a href="/posts/{{ post.slug }}" class="post-card__link">
{% if post.image %}
<img
src="{{ post.image | image_url: width: 400, height: 250 }}"
alt="{{ post.title }}"
class="post-card__image"
loading="lazy"
>
{% endif %}
<div class="post-card__content">
<h3 class="post-card__title">{{ post.title }}</h3>
<div class="post-card__meta">
{% if post.publishDate %}
<time datetime="{{ post.publishDate }}">
{{ post.publishDate | date: '%b %d, %Y' }}
</time>
{% endif %}
</div>
{% if post.description %}
<p class="post-card__excerpt">
{{ post.description | truncate: 100 }}
</p>
{% endif %}
</div>
</a>
</article>
{% endfor %}
</div>
{% endif %}
</section>
{% else %}
<div class="category-empty">
<h2>No Articles Yet</h2>
<p>There are no posts in the "{{ category.title }}" category yet. Check back soon!</p>
<a href="/blog" class="btn btn--secondary">Browse All Posts</a>
</div>
{% endif %}
{# Navigation #}
<nav class="category-nav">
<a href="/blog" class="back-link">
&larr; Back to Blog
</a>
</nav>
</div>
{% endcapture %}
{% schema %}
{
"name": "category",
"settings": [
{
"type": "checkbox",
"name": "show_featured",
"label": "Feature Latest Post",
"defaultValue": true
},
{
"type": "select",
"name": "layout",
"label": "Posts Layout",
"options": [
{ "value": "grid", "label": "Grid" },
{ "value": "list", "label": "List" }
],
"defaultValue": "grid"
}
]
}
{% endschema %}
{# In post.liquid template #}
{% if post.categories.size > 0 %}
<div class="post-categories">
{% for category_name in post.categories %}
<a href="/categories/{{ category_name | handleize }}" class="category-link">
{{ category_name }}
</a>
{% endfor %}
</div>
{% endif %}
{# Display all categories #}
{% if all_categories.size > 0 %}
<nav class="category-nav">
<h3>Categories</h3>
<ul>
{% for cat in all_categories %}
<li>
<a href="/categories/{{ cat.slug }}">{{ cat.title }}</a>
</li>
{% endfor %}
</ul>
</nav>
{% endif %}

Create variations for different category presentations:

templates/
├── category.liquid # Default category template
├── category.featured.liquid # Hero-style featured layout
├── category.compact.liquid # Compact list view
└── category.archive.liquid # Archive-style chronological