Using Filters
Assets & CDN Filters
Generate asset URLs, process images with CDN, and create HTML tags for resources
Nimbu provides powerful CDN integration for assets, with automatic image processing, optimization, and responsive image generation.
Asset URLs
asset_url
Generate URL for theme assets:
{{ 'style.css' | asset_url }}
<!-- Output: /assets/themes/theme-slug/style.css -->
<link rel="stylesheet" href="{{ 'main.css' | asset_url }}">
<script src="{{ 'app.js' | asset_url }}"></script>theme_image_url
Get theme image URL:
{{ 'logo.png' | theme_image_url }}
<img src="{{ 'banner.jpg' | theme_image_url }}" alt="Banner">global_asset_url
Access global site assets:
{{ 'shared-logo.png' | global_asset_url }}
<img src="{{ 'favicon.ico' | global_asset_url }}">Image Processing with CDN
filter
Apply comprehensive image transformations:
{{ image.url | filter, width: '800px', height: '600px' }}
{{ product.image.url | filter, width: '400px', cropping: 'fill' }}
{{ photo.url | filter, width: '1200px', height: '800px', gravity: 'face', quality: 85 }}Parameters:
| Parameter | Description | Values |
|---|---|---|
width | Target width | '300px', '1200px' |
height | Target height | '400px', '800px' |
cropping | Crop mode | 'fill', 'fit', 'limit', 'pad', 'scale' |
gravity | Crop focus | 'center', 'face', 'north', 'south', 'east', 'west' |
effect | Visual effect | 'grayscale', 'sepia', 'blur', 'sharpen' |
quality | JPEG quality | 1-100 (default: 80) |
format | Output format | 'jpg', 'png', 'webp', 'avif' |
alpha | Transparency | 0-100 |
Cropping Modes:
fill- Resize and crop to exact dimensionsfit- Fit within dimensions, maintain aspect ratiolimit- Only downscale, never upscalepad- Fit and add padding to match dimensionsscale- Resize to dimensions, ignore aspect ratio
Gravity Options:
center- Center of imageface- Detected facesnorth,south,east,west- Directionalnorth_east,north_west,south_east,south_west- Corners
grayscale
Convert image to grayscale:
{{ image.url | grayscale }}
<img src="{{ product.image.url | grayscale }}" alt="B&W {{ product.name }}">Image Tag Helpers
image_tag
Generate complete image tag:
{{ 'logo.png' | theme_image_url | image_tag }}
<!-- Output: <img src="/assets/.../logo.png" alt="Logo"> -->
{{ image.url | image_tag, alt: product.name, class: 'product-image' }}
{{ photo | image_tag, alt: "Team photo", width: 800, height: 600 }}With Lazy Loading:
{{ image.url | image_tag, loading: 'lazy', class: 'lazy-image' }}Responsive Images
Srcset Generation
Create responsive image sets:
{% assign image_400 = product.image.url | filter, width: '400px' %}
{% assign image_800 = product.image.url | filter, width: '800px' %}
{% assign image_1200 = product.image.url | filter, width: '1200px' %}
<img
src="{{ image_800 }}"
srcset="{{ image_400 }} 400w,
{{ image_800 }} 800w,
{{ image_1200 }} 1200w"
sizes="(max-width: 600px) 400px,
(max-width: 1200px) 800px,
1200px"
alt="{{ product.name }}"
loading="lazy">Picture Element
Art direction with different crops:
<picture>
<source
media="(max-width: 600px)"
srcset="{{ image.url | filter, width: '600px', height: '400px', cropping: 'fill', gravity: 'face' }}">
<source
media="(max-width: 1200px)"
srcset="{{ image.url | filter, width: '1200px', height: '600px', cropping: 'fill' }}">
<img
src="{{ image.url | filter, width: '1920px', height: '800px', cropping: 'fill' }}"
alt="{{ image.title }}">
</picture>Stylesheet and Script Tags
stylesheet_tag
Generate stylesheet link:
{{ 'theme.css' | asset_url | stylesheet_tag }}
<!-- Output: <link href="/assets/.../theme.css" rel="stylesheet"> -->
{{ 'custom.css' | asset_url | stylesheet_tag, media: 'print' }}script_tag
Generate script tag:
{{ 'app.js' | asset_url | script_tag }}
<!-- Output: <script src="/assets/.../app.js"></script> -->
{{ 'analytics.js' | asset_url | script_tag, defer: true }}
{{ 'polyfill.js' | asset_url | script_tag, async: true }}Practical Examples
Product Images with Variants
<div class="product-gallery">
<!-- Main image -->
<div class="main-image">
{% if product.images.first %}
{% assign main_image = product.images.first.url %}
<img
src="{{ main_image | filter, width: '800px', height: '800px', cropping: 'fill' }}"
srcset="{{ main_image | filter, width: '400px', height: '400px', cropping: 'fill' }} 400w,
{{ main_image | filter, width: '800px', height: '800px', cropping: 'fill' }} 800w,
{{ main_image | filter, width: '1200px', height: '1200px', cropping: 'fill' }} 1200w"
sizes="(max-width: 768px) 400px, 800px"
alt="{{ product.name }}"
loading="eager">
{% endif %}
</div>
<!-- Thumbnails -->
<div class="thumbnails">
{% for image in product.images %}
<button class="thumbnail" data-index="{{ forloop.index0 }}">
<img
src="{{ image.url | filter, width: '100px', height: '100px', cropping: 'fill' }}"
alt="{{ product.name }} - Image {{ forloop.index }}"
loading="lazy">
</button>
{% endfor %}
</div>
</div>Hero Banner with Optimizations
<section class="hero">
{% if page.hero_image %}
<picture>
<!-- Mobile: Portrait crop -->
<source
media="(max-width: 768px)"
srcset="{{ page.hero_image.url | filter, width: '768px', height: '1024px', cropping: 'fill', gravity: 'center', format: 'webp' }} 768w"
type="image/webp">
<!-- Tablet: Landscape -->
<source
media="(max-width: 1200px)"
srcset="{{ page.hero_image.url | filter, width: '1200px', height: '600px', cropping: 'fill', format: 'webp' }} 1200w"
type="image/webp">
<!-- Desktop: Full width -->
<source
srcset="{{ page.hero_image.url | filter, width: '1920px', height: '800px', cropping: 'fill', format: 'webp', quality: 85 }} 1920w"
type="image/webp">
<!-- Fallback JPG -->
<img
src="{{ page.hero_image.url | filter, width: '1920px', height: '800px', cropping: 'fill', quality: 85 }}"
alt="{{ page.hero_title }}"
loading="eager">
</picture>
{% endif %}
<div class="hero-content">
<h1>{{ page.hero_title }}</h1>
<p>{{ page.hero_subtitle }}</p>
</div>
</section>Team Member Cards
<div class="team-grid">
{% for member in channels.team.all %}
<div class="team-card">
{% if member.photo %}
<div class="photo">
<img
src="{{ member.photo.url | filter, width: '300px', height: '300px', cropping: 'fill', gravity: 'face' }}"
alt="{{ member.name }}"
loading="lazy">
</div>
{% else %}
<div class="photo placeholder">
<img src="{{ 'team-placeholder.png' | theme_image_url }}" alt="{{ member.name }}">
</div>
{% endif %}
<h3>{{ member.name }}</h3>
<p class="role">{{ member.role }}</p>
</div>
{% endfor %}
</div>Background Images
<section
class="cta-section"
style="background-image: url('{{ page.background.url | filter, width: '1920px', quality: 75, effect: 'blur' }}')">
<div class="cta-content">
<h2>{{ page.cta_title }}</h2>
<a href="{{ page.cta_link }}" class="btn">{{ page.cta_text }}</a>
</div>
</section>Asset Preloading
<head>
<!-- Preload critical images -->
<link
rel="preload"
as="image"
href="{{ page.hero_image.url | filter, width: '1920px', format: 'webp' }}"
type="image/webp">
<!-- Preload fonts -->
<link
rel="preload"
as="font"
href="{{ 'Inter-Regular.woff2' | asset_url }}"
type="font/woff2"
crossorigin>
<!-- Stylesheets -->
{{ 'theme.css' | asset_url | stylesheet_tag }}
<!-- Critical JS -->
{{ 'critical.js' | asset_url | script_tag }}
</head>Image Gallery with Lightbox
<div class="image-gallery">
{% for image in page.gallery %}
<a
href="{{ image.url | filter, width: '1920px', quality: 90 }}"
class="gallery-item"
data-lightbox="gallery">
<img
src="{{ image.url | filter, width: '400px', height: '300px', cropping: 'fill' }}"
alt="{{ image.title }}"
loading="lazy">
</a>
{% endfor %}
</div>Performance Best Practices
1. Use Appropriate Image Formats
<!-- ✅ Good: Modern formats with fallback -->
<picture>
<source srcset="{{ image.url | filter, width: '800px', format: 'webp' }}" type="image/webp">
<source srcset="{{ image.url | filter, width: '800px', format: 'jpg' }}" type="image/jpeg">
<img src="{{ image.url | filter, width: '800px' }}" alt="...">
</picture>
<!-- ⚠️ Acceptable for simple cases -->
<img src="{{ image.url | filter, width: '800px' }}" alt="...">2. Optimize Quality Settings
<!-- ✅ Good: Optimized quality -->
{{ image.url | filter, width: '1200px', quality: 80 }}
<!-- ❌ Bad: Unnecessarily high quality -->
{{ image.url | filter, width: '1200px', quality: 100 }}3. Lazy Load Below the Fold
<!-- Above the fold: Eager loading -->
<img src="{{ hero.url | filter, width: '1920px' }}" loading="eager" alt="Hero">
<!-- Below the fold: Lazy loading -->
<img src="{{ image.url | filter, width: '800px' }}" loading="lazy" alt="...">4. Use Face Detection for People Photos
<!-- ✅ Good: Face-aware cropping -->
{{ member.photo.url | filter, width: '300px', height: '300px', cropping: 'fill', gravity: 'face' }}
<!-- ❌ Bad: Might crop out faces -->
{{ member.photo.url | filter, width: '300px', height: '300px', cropping: 'fill' }}Next Steps
- Commerce - Shopping cart and product helpers
- Special Purpose - QR codes, analytics, utilities
- Pages - Working with page images
- Performance - Optimization strategies
Optimize and deliver assets effectively with Nimbu's CDN filters!