Themes: A Developers Guide

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

  1. Choose a Root Theme: Select from Fluid, Vox, or Base themes
  2. Clone for Customization: Create a company-specific copy
  3. Configure Variables: Set brand colors, fonts, and spacing
  4. Customize Templates: Override specific page layouts as needed
  5. 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:

 
liquid
<!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:

 
liquid
{% layout "minimal" %}

To render without any layout:

 
liquid
{% layout none %}

Building Templates

Templates define the structure and content for specific page types. Here's an example product template:

 
liquid
<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

 
liquid
<!-- 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

 
liquid
<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

 
json
{
  "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:

 
json
// 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:

 
liquid
<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

 
liquid
<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

 
liquid
{{ image.url | img_url: '300x200' }}
{{ image.url | img_url: '300x200', crop: 'center' }}

Text Processing

 
liquid
{{ text | truncate: 150 }}
{{ text | strip_html }}
{{ text | capitalize }}

Formatting

 
liquid
{{ price | money }}
{{ date | date: '%B %d, %Y' }}
{{ number | number }}

Arrays

 
liquid
{{ array | join: ', ' }}
{{ array | first }}
{{ array | size }}

Best Practices

Performance Optimization

Optimize Images: Use responsive images with proper sizing and lazy loading

 
liquid
<img src="{{ image.url | img_url: '600x400' }}" 
     loading="lazy"
     alt="{{ image.alt }}" />

Load CSS/JS Efficiently: Inline critical CSS, defer non-critical JavaScript

 
liquid
<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

 
liquid
<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.

Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Article is closed for comments.