Liquid Filters
Filters modify the output of variables. They are applied using the pipe character |.
{{ "hello world" | capitalize | append: "!" }}
<!-- Output: Hello world! -->
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>
Navigation Filters
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">
← {{ prev.title }}
</a>
{% endif %}
{% if next %}
<a href="{{ next | post_url }}" class="nav-next">
{{ next.title }} →
</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:
| Preset | Size | Description |
|---|---|---|
thumb | 100x100 | Tiny thumbnail |
thumbnail | 150x150 | Standard thumbnail |
small | 320x240 | Small images |
medium | 640x480 | Cards |
large | 1024x768 | Featured images |
hero | 1920x1080 | Hero sections |
og | 1200x630 | Open Graph social |
square | 400x400 (fill) | Square crop |
avatar | 100x100 (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:
| Preset | Output |
|---|---|
short | Jan 15 |
medium | January 15, 2025 |
long | Wednesday, January 15, 2025 |
full | Wednesday, January 15, 2025 at 03:30 PM |
iso | 2025-01-15 |
time | 03:30 PM |
time_24 | 15:30 |
datetime | 2025-01-15 15:30 |
rss | Wed, 15 Jan 2025 15:30:00 +0000 |
year | 2025 |
month | January 2025 |
day | 15 |
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 -->
Link Filters
Work with link settings from section schemas.
link_href
Extract URL from link setting.
<a href="{{ section.settings.button | link_href }}">
Click here
</a>
link_text
Extract text from link setting.
<a href="{{ section.settings.button | link_href }}">
{{ section.settings.button | link_text }}
</a>
link_target
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 }}
Related Documentation
- 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