View our full Themes Developer Guide here.
Building Fluid Themes: Complete Guide
Learn how to build fast, flexible themes using Liquid templating language, JSON sections, and modern web technologies.
What Are Fluid Themes?
Fluid themes are packages of template files, building blocks, and supporting assets that define how your company's pages look and function. The theme system provides multiple levels of customization, from simple CSS variable changes to complete template overrides.
Getting Started
Quick Start Guide
- Choose a Root Theme: Select from Fluid, Vox, or Base themes
- Clone for Customization: Create a company-specific copy
- Configure Variables: Set brand colors, fonts, and spacing
- Customize Templates: Override specific page layouts as needed
- Publish: Activate your theme for all users
The theme system handles the technical implementation behind the scenes, allowing you to focus on design and customization.
Understanding Key Concepts
Theme Types
Root Themes: Platform-provided base themes (Fluid, Vox, Base) that serve as starting points
Company Themes: Your company-specific themes that clone and customize root themes
Template Inheritance: Company themes can override specific templates while inheriting others from the root theme
Available Template Types
Your theme can include templates for different content types and page layouts:
- Content Templates: product, medium, library, enrollment_pack
- Page Templates: home_page, shop_page, cart_page, page, join_page, collection_page, collection, category_page
- Layout Components: navbar, footer, layouts
- Structural Components: sections, components, config
Working with Layouts
Layouts provide the structural wrapper for your content, defining the overall page structure including navigation and footer elements.
Creating a Basic Layout
Your main layout file (theme.liquid) should include two essential variables:
<!DOCTYPE html>
<html lang="{{ request.locale.iso_code }}">
<head>
{{ content_for_header }}
<style>
:root {
--primary-color: {{ settings.primary_color }};
--font-family: {{ settings.font_family }};
}
</style>
</head>
<body>
{% section 'navbar' %}
{{ content_for_layout }}
{% section 'footer' %}
<script src="{{ 'theme.js' | asset_url }}"></script>
</body>
</html>Important: You must include {{ content_for_header }} and {{ content_for_layout }} for your theme to render correctly.
Creating Custom Layouts
You can create specialized layouts for different page types. To use a custom layout, add this tag to your template:
{% layout "minimal" %}To render without any layout:
{% layout none %}Building Templates
Templates define the structure and content for specific page types. Here's an example product template:
<article class="product-page">
<header class="product-header">
<h1>{{ product.name }}</h1>
<div class="product-price">
{{ product.price | money }}
</div>
{% if product.tags.size > 0 %}
<div class="product-tags">
{{ product.tags | join: ', ' }}
</div>
{% endif %}
</header>
<div class="product-gallery">
{% for image in product.images %}
<img src="{{ image.url | img_url: '600x400' }}"
alt="{{ image.alt }}" />
{% endfor %}
</div>
<div class="product-description">
{{ product.description }}
</div>
{% if product.available %}
<button class="btn-purchase" data-product-id="{{ product.id }}">
{{ 'products.add_to_cart' | t }}
</button>
{% endif %}
</article>Creating Reusable Sections
Sections are reusable components that can be added to templates. Each section has its own template and schema defining available settings.
Section Example
<!-- sections/product_header.liquid -->
<div class="product-header"
style="background-color: {{ section.settings.background_color }};">
<div class="product-header-content">
{% if section.settings.show_vendor and product.vendor %}
<div class="product-vendor">{{ product.vendor }}</div>
{% endif %}
<h1 class="product-title">{{ product.name }}</h1>
{% if section.settings.show_price %}
<div class="product-price">
{{ product.price | money }}
</div>
{% endif %}
</div>
</div>
{% schema %}
{
"name": "Product Header",
"settings": [
{
"type": "checkbox",
"id": "show_vendor",
"label": "Show vendor",
"default": true
},
{
"type": "checkbox",
"id": "show_price",
"label": "Show price",
"default": true
},
{
"type": "color",
"id": "background_color",
"label": "Background color",
"default": "#ffffff"
}
]
}
{% endschema %}Using Blocks for Dynamic Content
Blocks are dynamic content elements within sections that can be added, removed, and reordered. They're perfect for testimonials, image galleries, or any repeating content.
Block Implementation
<div class="testimonials">
<h2>{{ section.settings.section_title }}</h2>
{% for block in section.blocks %}
<div class="testimonial"
data-fluid-section-block-id="{{ block.id }}"
data-fluid-section-block-type="{{ block.type }}">
<blockquote>{{ block.settings.testimonial_text }}</blockquote>
<cite>{{ block.settings.customer_name }}</cite>
</div>
{% endfor %}
</div>Configuring Settings
Settings define configurable options for themes, sections, and blocks. They automatically generate form interfaces for customization.
Available Setting Types
- text: Single-line text input
- textarea: Multi-line text input
- select: Dropdown with options
- checkbox: Boolean toggle
- color: Color picker
- range: Slider with min/max
- number: Numeric input
- url: URL input with validation
- image_picker: Asset selection
Example Settings
{
"name": "Hero Section",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Hero Heading",
"default": "Welcome to Our Store"
},
{
"type": "color",
"id": "background_color",
"label": "Background Color",
"default": "#ffffff"
},
{
"type": "checkbox",
"id": "show_button",
"label": "Show Call-to-Action Button",
"default": true
}
]
}Adding Multi-Language Support
Create JSON locale files for each language you want to support:
// locales/en.json
{
"product": {
"add_to_cart": "Add to Cart",
"buy_now": "Buy Now",
"quantity": "Quantity"
},
"navbar": {
"shop": "Shop",
"enrollments": "Enrollments"
}
}Use translations in your templates:
<button>{{ 'product.add_to_cart' | t }}</button>
<a href="/shop">{{ 'navbar.shop' | t }}</a>Managing Assets
Assets are stored in your theme's assets folder and automatically processed through a CDN.
Uploading Assets
Binary Files (images, fonts, videos): Upload only through file selection
Non-Binary Files (CSS, JavaScript, JSON): Can be uploaded or created from scratch
Referencing Assets
<link rel="stylesheet" href="{{ 'custom.css' | asset_url }}">
<script src="{{ 'custom.js' | asset_url }}"></script>
<img src="{{ 'banner.jpg' | asset_url }}" alt="Banner">Useful Liquid Filters
Image Processing
{{ image.url | img_url: '300x200' }}
{{ image.url | img_url: '300x200', crop: 'center' }}Text Processing
{{ text | truncate: 150 }}
{{ text | strip_html }}
{{ text | capitalize }}Formatting
{{ price | money }}
{{ date | date: '%B %d, %Y' }}
{{ number | number }}Arrays
{{ array | join: ', ' }}
{{ array | first }}
{{ array | size }}Best Practices
Performance Optimization
Optimize Images: Use responsive images with proper sizing and lazy loading
<img src="{{ image.url | img_url: '600x400' }}"
loading="lazy"
alt="{{ image.alt }}" />Load CSS/JS Efficiently: Inline critical CSS, defer non-critical JavaScript
<script src="{{ 'theme.js' | asset_url }}" defer></script>Accessibility
Use Semantic HTML: Structure your content with proper HTML5 elements
Add ARIA Labels: Help screen readers understand your interface
<button aria-label="{{ 'products.add_to_cart' | t }}: {{ product.name }}">
{{ 'products.add_to_cart' | t }}
</button>Mobile-First Design
Design for mobile devices first, then enhance for larger screens.
Need Help?
For more detailed information about specific features or advanced customization, visit our documentation or contact support.
Comments
Article is closed for comments.