Skip to main content

Live Preview

How the admin editor provides instant preview of changes.

Overview​

When editing section settings in the admin, changes appear instantly in the preview iframe. The system uses two update paths based on setting type:

  1. CSS hot-reload - For colors, fonts (save + reload section CSS)
  2. HTML re-render - For text and structural changes (server renders full section HTML)

Both paths are server-side. The difference is efficiency - CSS hot-reload only fetches new CSS, while HTML re-render fetches the entire section.

Update Paths​

Path 1: CSS Hot-Reload​

For CSS-relevant settings (color, color_alpha, font):

  1. Settings auto-save to database (150ms debounce)
  2. Server regenerates section CSS from .css.liquid template
  3. CSS link tag in iframe refreshes with cache-busting timestamp
  4. Visual update applies without touching HTML

Path 2: HTML Re-render​

For content settings (text, textarea, link, etc.) and structural settings (select, checkbox, number):

  1. Settings sent to preview endpoint (300ms debounce)
  2. Server renders complete section HTML with temporary values
  3. JavaScript replaces the section in iframe via postMessage
  4. Settings auto-save (500ms debounce)

Setting Type Categories​

// CSS-only: Save + CSS hot-reload (fastest)
const CSS_ONLY_TYPES = ["color", "color_alpha", "font"]

// HTML-only: Server re-render (fast)
const HTML_ONLY_TYPES = ["text", "textarea", "collection", "post", "tag", "link", "url", "header", "info", "icon"]

// Ambiguous: Do BOTH CSS + HTML (safe fallback)
// range, number, select, checkbox, image

CSS Variables​

For colors and images, use CSS variables with the data-css-vars attribute:

{% capture section_style %}
--bgcolor: {{ section.settings.bgcolor }};
--overlay: {{ section.settings.overlay | color_alpha_to_rgba }};
--bg-image: url('{{ section.settings.image | image_url: 'hero' }}');
{% endcapture %}

{% section_wrapper 'section' style: section_style data-css-vars: 'bgcolor,overlay,image' %}
<div style="background: var(--overlay), var(--bg-image); background-color: var(--bgcolor);">
...
</div>
{% endsection_wrapper %}

The data-css-vars attribute lists which settings should trigger CSS hot-reload.

The .attr Accessor (Optional)​

The .attr accessor outputs data attributes for element identification:

<h2 {{ section.settings.title.attr }}>{{ section.settings.title }}</h2>

Outputs:

<h2 data-setting="title" data-section-id="abc123">My Title</h2>

Note: .attr is NOT required for live preview to work. It's a convenience that:

  • Provides unique identifiers for debugging
  • May be used by future optimizations
  • Helps with CSS targeting via [data-setting="..."]

Live preview works via server re-render regardless of whether .attr is used.

Section ID​

Each section has a unique UUID (section.id) provided by section_wrapper:

<section data-section-id="abc123">
<!-- All content inherits this section context -->
</section>

This ID is used to:

  1. Target the correct section for HTML replacement
  2. Scope CSS variables to the section
  3. Trigger CSS hot-reload for the right CSS link tag

Complete Example​

{% capture section_style %}
--bgcolor: {{ section.settings.bgcolor }};
--text-color: {{ section.settings.text_color }};
--overlay: {{ section.settings.overlay | color_alpha_to_rgba }};
--bg-image: url('{{ section.settings.image | image_url: 'hero' }}');
{% endcapture %}

{% section_wrapper 'section' class: 'cta' style: section_style data-css-vars: 'bgcolor,text_color,overlay,image' %}
<div class="cta-background" style="background: var(--overlay), var(--bg-image); background-color: var(--bgcolor);">
<div class="cta-content" style="color: var(--text-color);">
{% htmltag 'h2' section.settings.title class: 'cta-title' %}
{% htmltag 'p' section.settings.body class: 'cta-body' %}

{% if section.settings.show_button %}
<a href="{{ section.settings.button | link_href }}" class="btn">
{{ section.settings.button | link_text }}
</a>
{% endif %}
</div>
</div>
{% endsection_wrapper %}

{% schema %}
{
"name": "CTA Section",
"category": "cta",
"settings": [
{
"type": "text",
"id": "title",
"label": "Title"
},
{
"type": "text",
"id": "body",
"label": "Body",
"nb_rows": 3
},
{
"type": "color",
"id": "bgcolor",
"label": "Background Color"
},
{
"type": "color",
"id": "text_color",
"label": "Text Color"
},
{
"type": "color_alpha",
"id": "overlay",
"label": "Image Overlay"
},
{
"type": "image",
"id": "image",
"label": "Background Image"
},
{
"type": "checkbox",
"id": "show_button",
"label": "Show Button"
},
{
"type": "link",
"id": "button",
"label": "Button",
"with_text": true,
"show_if": { "setting": "show_button", "eq": true }
}
],
"presets": [
{
"name": "CTA Section",
"settings": {
"title": "Ready to get started?",
"body": "",
"bgcolor": "#1F2937",
"text_color": "#FFFFFF",
"overlay": {"color": "#000000", "alpha": 50},
"image": "",
"show_button": true,
"button": { "text": "Learn More", "href": "#" }
}
}
]
}
{% endschema %}

What Updates How​

Setting TypeUpdate MethodSpeed
colorCSS hot-reload~150ms
color_alphaCSS hot-reload~150ms
fontCSS hot-reload~150ms
textServer re-render~300ms
textareaServer re-render~300ms
linkServer re-render~300ms
selectCSS + HTML (both)~300ms
numberCSS + HTML (both)~300ms
rangeCSS + HTML (both)~300ms
checkboxCSS + HTML (both)~300ms
imageCSS + HTML (both)~300ms

Tips​

  1. Use CSS variables for any style-related setting (colors, images)
  2. Use htmltag for text elements - cleaner than manual .attr
  3. Test live preview when developing new sections
  4. Use natural boolean checks for checkbox settings (if, unless)