Skip to main content

Liquid Filters

Filters modify the output of variables. They are applied using the pipe character |.

{{ "hello world" | capitalize | append: "!" }}
<!-- Output: Hello world! -->
Standard Liquid

OQO extends Liquid, the templating language created by Shopify. All standard Liquid filters work in OQO themes, plus the custom filters documented below.


URL Filters

Generate URLs for models and assets.

post_url

Generate URL for a post.

<a href="{{ post | post_url }}">{{ post.title }}</a>
<!-- Output: /post/my-article-slug -->

tag_url

Generate URL for a tag.

<a href="{{ tag | tag_url }}">{{ tag.name }}</a>
<!-- Output: /tag/technology -->

<!-- In a loop -->
{% for tag in post.tags %}
<a href="{{ tag | tag_url }}">{{ tag.name }}</a>
{% endfor %}

collection_url

Generate URL for a collection.

<a href="{{ collection | collection_url }}">{{ collection.title }}</a>
<!-- Output: /collection/featured-stories -->

user_url

Generate URL for a user profile.

<a href="{{ post.author | user_url }}">{{ post.author.name }}</a>
<!-- Output: /author/john-doe -->

absolute_url

Convert relative path to absolute URL.

{{ post.url | absolute_url }}
<!-- Output: https://yoursite.com/post/my-article -->

asset_url

Generate URL for a non-image asset (PDF, file, etc.).

{{ 'styles.css' | asset_url }}
{{ section.settings.pdf_file | asset_url }}

download_url

Generate download URL that forces browser download.

<a href="{{ section.settings.file | download_url }}">Download PDF</a>

Filters for navigating between posts within a collection. Useful for building prev/next post navigation.

next_post

Get the next post in a collection (ordered by publication date).

{% assign next = collection | next_post: post %}
{% if next %}
<a href="{{ next | post_url }}">Next: {{ next.title }}</a>
{% endif %}

prev_post

Get the previous post in a collection.

{% assign prev = collection | prev_post: post %}
{% if prev %}
<a href="{{ prev | post_url }}">Previous: {{ prev.title }}</a>
{% endif %}

first_post

Get the first post in a collection.

{% assign first = collection | first_post %}
{% if first %}
<a href="{{ first | post_url }}">Start reading</a>
{% endif %}

last_post

Get the last post in a collection.

{% assign last = collection | last_post %}
{% if last %}
<a href="{{ last | post_url }}">Latest post</a>
{% endif %}

Complete Prev/Next Navigation Example

Build a full post navigation bar for a post detail page:

{% if collection %}
<nav class="post-navigation">
{% assign prev = collection | prev_post: post %}
{% assign next = collection | next_post: post %}

{% if prev %}
<a href="{{ prev | post_url }}" class="nav-prev">
&larr; {{ prev.title }}
</a>
{% endif %}

{% if next %}
<a href="{{ next | post_url }}" class="nav-next">
{{ next.title }} &rarr;
</a>
{% endif %}
</nav>
{% endif %}

Image Filters

All image filters work with ImageDrop objects from posts, collections, users, elements, or settings.

image_url

Get URL for an image with a specific size preset or custom geometry.

<!-- Presets -->
{{ post.image | image_url: 'thumb' }} <!-- 100x100 -->
{{ post.image | image_url: 'small' }} <!-- 320x240 -->
{{ post.image | image_url: 'medium' }} <!-- 640x480 -->
{{ post.image | image_url: 'large' }} <!-- 1024x768 -->
{{ post.image | image_url: 'hero' }} <!-- 1920x1080 -->
{{ post.image | image_url: 'avatar' }} <!-- 100x100 cropped -->
{{ post.image | image_url: 'square' }} <!-- 400x400 cropped -->
{{ post.image | image_url: 'og' }} <!-- 1200x630 for social -->

<!-- Custom geometry -->
{{ post.image | image_url: '400x300' }} <!-- Fit within bounds -->
{{ post.image | image_url: '400x300#' }} <!-- Crop to exact size -->
{{ post.image | image_url: '400x300>' }} <!-- Only shrink if larger -->
{{ post.image | image_url: '400x' }} <!-- Width only, auto height -->

Image Presets:

PresetSizeDescription
thumb100x100Tiny thumbnail
thumbnail150x150Standard thumbnail
small320x240Small images
medium640x480Cards
large1024x768Featured images
hero1920x1080Hero sections
og1200x630Open Graph social
square400x400 (fill)Square crop
avatar100x100 (fill)User avatars

Works with any ImageDrop:

{{ post.image | image_url: 'medium' }}
{{ collection.image | image_url: 'hero' }}
{{ post.author.image | image_url: 'avatar' }}
{{ section.settings.background_image | image_url: 'hero' }}

image_srcset

Generate srcset attribute for responsive images.

<img src="{{ post.image | image_url: 'medium' }}"
srcset="{{ post.image | image_srcset }}"
sizes="(max-width: 640px) 100vw, 50vw"
alt="{{ post.image.alt | default: post.title }}">

image_tag

Generate a complete <img> tag.

{{ post.image | image_tag: 'medium', 'Alt text', 'my-class' }}
<!-- Output: <img src="..." alt="Alt text" class="my-class"> -->

Color Filters

Shopify-style color manipulation for dynamic theming.

color_lighten

Lighten a color by percentage.

{{ '#333333' | color_lighten: 20 }}
<!-- Output: #666666 (lighter) -->

color_darken

Darken a color by percentage.

{{ '#ffffff' | color_darken: 15 }}
<!-- Output: #d9d9d9 (darker) -->

color_saturate / color_desaturate

Adjust color saturation.

{{ theme.settings.primary_color | color_saturate: 30 }}
{{ theme.settings.primary_color | color_desaturate: 30 }}

color_mix

Mix two colors together.

{{ '#ff0000' | color_mix: '#0000ff', 50 }}
<!-- Output: purple (50% red, 50% blue) -->

color_brightness

Get perceived brightness value (0-255).

{{ section.settings.bg_color | color_brightness }}
<!-- Output: 128 (mid-range) -->

color_brightness_class

Returns 'light' or 'dark' based on brightness.

<div class="bg-{{ section.settings.bg_color | color_brightness_class }}">
<!-- Adds class="bg-light" or class="bg-dark" -->
</div>

color_contrast

Get contrasting text color (black or white).

<span style="color: {{ section.settings.bg_color | color_contrast }}">
Readable text on any background
</span>

color_to_rgba

Convert hex color to rgba() CSS value.

{{ '#ff0000' | color_to_rgba: 0.5 }}
<!-- Output: rgba(255, 0, 0, 0.5) -->

color_to_hsl

Convert hex color to hsl() CSS value.

{{ '#ff0000' | color_to_hsl }}
<!-- Output: hsl(0, 100%, 50%) -->

color_alpha_to_rgba

Convert color_alpha setting (color + opacity) to rgba().

{{ section.settings.overlay_color | color_alpha_to_rgba }}
<!-- Input: {"color": "#000000", "alpha": 50} -->
<!-- Output: rgba(0, 0, 0, 0.5) -->

Usage in CSS variables:

{% capture section_style %}
--overlay-color: {{ section.settings.overlay | color_alpha_to_rgba }};
--bg-color: {{ section.settings.bg_color | color_to_rgba: 0.9 }};
{% endcapture %}

{% section_wrapper 'section' style: section_style %}
<div style="background: var(--overlay-color);">...</div>
{% endsection_wrapper %}

Text Filters

Text manipulation and formatting.

pluralize

Pluralize a word based on count (includes count in output).

{{ 1 | pluralize: 'item' }}
<!-- Output: 1 item -->

{{ 5 | pluralize: 'item' }}
<!-- Output: 5 items -->

{{ 3 | pluralize: 'category', 'categories' }}
<!-- Output: 3 categories -->

pluralize_word

Pluralize without including the count.

{{ collection.posts_count }} {{ collection.posts_count | pluralize_word: 'post' }}
<!-- Output: 12 posts -->

excerpt

Extract plain text excerpt from HTML content.

{{ post.content | excerpt: 200 }}
{{ post.content | excerpt: 100, '...' }}

titlecase

Convert to title case.

{{ 'hello world' | titlecase }}
<!-- Output: Hello World -->

sentencecase

Convert to sentence case.

{{ 'hello world' | sentencecase }}
<!-- Output: Hello world -->

highlight

Highlight search terms in text.

{{ post.title | highlight: 'search term' }}
<!-- Output: My <mark>Search Term</mark> Article -->

{{ post.title | highlight: 'term', 'strong' }}
<!-- Output: My <strong>term</strong> Article -->

parameterize

Convert text to URL-safe slug.

{{ 'Hello World!' | parameterize }}
<!-- Output: hello-world -->

Date Filters

Date formatting and relative time display.

date_format

Format a date with presets or custom format.

{{ post.published_at | date_format: 'short' }}
<!-- Output: Jan 15 -->

{{ post.published_at | date_format: 'medium' }}
<!-- Output: January 15, 2025 -->

{{ post.published_at | date_format: 'long' }}
<!-- Output: Wednesday, January 15, 2025 -->

{{ post.published_at | date_format: 'iso' }}
<!-- Output: 2025-01-15 -->

{{ post.published_at | date_format: '%B %Y' }}
<!-- Custom strftime format -->

Date Format Presets:

PresetOutput
shortJan 15
mediumJanuary 15, 2025
longWednesday, January 15, 2025
fullWednesday, January 15, 2025 at 03:30 PM
iso2025-01-15
time03:30 PM
time_2415:30
datetime2025-01-15 15:30
rssWed, 15 Jan 2025 15:30:00 +0000
year2025
monthJanuary 2025
day15

time_ago

Get relative time description.

{{ post.published_at | time_ago }}
<!-- Output: 2 days ago, about 1 hour ago, just now, etc. -->

relative_date

Get relative date with smart formatting.

{{ post.published_at | relative_date }}
<!-- Output: Today, Yesterday, 3 days ago, or January 15, 2025 -->

past? / future?

Check if date is in past or future.

{% if event.date | past? %}
<span class="badge">Event has passed</span>
{% endif %}

{% if event.date | future? %}
<span class="badge">Upcoming</span>
{% endif %}

year / month_name

Extract date parts.

{{ post.published_at | year }}
<!-- Output: 2025 -->

{{ post.published_at | month_name }}
<!-- Output: January -->

Work with link settings from section schemas.

Extract URL from link setting.

<a href="{{ section.settings.button | link_href }}">
Click here
</a>

Extract text from link setting.

<a href="{{ section.settings.button | link_href }}">
{{ section.settings.button | link_text }}
</a>

Get target attribute for link.

<a href="{{ section.settings.link | link_href }}"
target="{{ section.settings.link | link_target }}">
{{ section.settings.link | link_text }}
</a>

opens_new_window

Check if link opens in new window.

<a href="{{ section.settings.link | link_href }}"
{% if section.settings.link | opens_new_window %}target="_blank" rel="noopener"{% endif %}>
{{ section.settings.link | link_text }}
</a>

Utility Filters

Common utilities for settings and CSS.

true? / false?

Boolean checks for non-boolean setting values (strings, objects).

<!-- For boolean settings (checkboxes), use natural boolean checks -->
{% if section.settings.show_title %}
<h1>{{ section.settings.title }}</h1>
{% endif %}

{% unless section.settings.hide_image %}
<img src="{{ post.image | image_url: 'medium' }}">
{% endunless %}

<!-- These filters are for checking string/object values -->
{% if some_string_value | true? %}
<!-- Checks if string equals "true" -->
{% endif %}

Note: Checkbox settings now return raw true/false values, so you can use natural boolean checks (if, unless). The .true? and .false? filters are still available for checking string values.

setting_value

Extract raw value from setting object.

{{ section.settings.theme | setting_value }}

background_style

Build CSS background-image style.

<div style="{{ section.settings.image | image_url: 'hero' | background_style }}">
</div>
<!-- Output: background-image: url(...); -->

gradient_overlay

Build CSS gradient overlay style.

<div style="{{ section.settings.color1 | gradient_overlay: section.settings.color2 }}">
</div>

add_class

Join CSS classes together.

{% assign base_class = 'card' %}
{% assign extra_class = 'featured' %}
<div class="{{ base_class | add_class: extra_class }}">
<!-- Output: class="card featured" -->

class_if

Conditionally add a class based on a boolean.

<div class="article {{ section.settings.featured | class_if: 'is-featured' }}">
<!-- Output: class="article is-featured" (if featured is true) -->

<div class="grid {{ section.settings.reverse | class_if: 'order-reverse' }}">

Filter Chaining

Filters can be chained together for powerful transformations:

<!-- Responsive image with fallback alt -->
<img src="{{ post.image | image_url: 'medium' }}"
srcset="{{ post.image | image_srcset }}"
alt="{{ post.image.alt | default: post.title | escape }}">

<!-- Excerpt with word limit -->
{{ post.content | strip_html | truncate_words: 30 }}

<!-- Dynamic text color based on background -->
<div style="
background: {{ section.settings.bg_color }};
color: {{ section.settings.bg_color | color_contrast }};
">

<!-- Relative date with fallback -->
<time>{{ post.published_at | relative_date | default: 'Unpublished' }}</time>

<!-- Conditional class with color-based modifier -->
<section class="hero bg-{{ section.settings.bg_color | color_brightness_class }}">

Standard Liquid Filters

These commonly-used filters are built into Liquid:

String Filters

{{ "hello" | capitalize }}        <!-- Hello -->
{{ "HELLO" | downcase }} <!-- hello -->
{{ "hello" | upcase }} <!-- HELLO -->
{{ "hello world" | truncate: 8 }} <!-- hello... -->
{{ " hello " | strip }} <!-- hello -->
{{ "hello" | append: " world" }} <!-- hello world -->
{{ "hello" | prepend: "say " }} <!-- say hello -->
{{ "hello" | replace: "l", "L" }} <!-- heLLo -->

Array Filters

{{ array | first }}               <!-- First item -->
{{ array | last }} <!-- Last item -->
{{ array | size }} <!-- Number of items -->
{{ array | join: ", " }} <!-- Comma-separated -->
{{ array | sort }} <!-- Sorted -->
{{ array | reverse }} <!-- Reversed -->
{{ array | uniq }} <!-- Unique only -->
{{ posts | map: 'title' }} <!-- Extract property -->
{{ posts | where: 'featured' }} <!-- Filter by property -->

Number Filters

{{ 4.5 | ceil }}                  <!-- 5 -->
{{ 4.5 | floor }} <!-- 4 -->
{{ 4.5 | round }} <!-- 5 -->
{{ 1000 | plus: 500 }} <!-- 1500 -->
{{ 1000 | minus: 500 }} <!-- 500 -->

Date Filter

{{ post.published_at | date: "%B %d, %Y" }}  <!-- January 15, 2025 -->
{{ post.published_at | date: "%Y-%m-%d" }} <!-- 2025-01-15 -->

Default Filter

{{ section.settings.title | default: 'Untitled' }}
{{ post.excerpt | default: post.title }}

  • Liquid Objects - Data objects like post, collection, section, member
  • Liquid Tags - Control flow and custom tags including zone, extends, style, post
  • Settings System - Defining section and theme settings