QUANTM7 Docs

Section Templates

Build complete sections with templates, scoped styles, and JavaScript.

A section template is a self-contained file that brings together HTML, Quill code, CSS, JavaScript, and a schema. Each section handles one part of the page, like a hero banner, a product grid, or a footer.

Anatomy of a section

A section template has up to four parts:

  1. Template code at the top (HTML and Quill tags)
  2. Scoped CSS inside {% stylesheet %}
  3. Scoped JavaScript inside {% javascript %}
  4. Schema inside {% schema %}

Here is a minimal section with all four:

<div class="announcement" data-section-id="{{ section.id }}">
  <p>{{ section.settings.text }}</p>
</div>

{% stylesheet %}
  .announcement {
    background: var(--color-accent);
    color: white;
    text-align: center;
    padding: 0.75rem 1rem;
  }
{% endstylesheet %}

{% javascript %}
  const el = document.querySelector('[data-section-id="{{ section.id }}"]');
  el.addEventListener('click', () => el.remove());
{% endjavascript %}

{% schema %}
{
  "name": "Announcement Bar",
  "settings": [
    {
      "type": "text",
      "id": "text",
      "label": "Message",
      "default": "Free shipping on all orders"
    }
  ]
}
{% endschema %}

The data-section-id attribute

Always add data-section-id="{{ section.id }}" to the outermost element of your section. This serves two purposes:

  • The scoped CSS uses it to keep styles from leaking into other sections.
  • The visual editor uses it to highlight the section when the merchant selects it.

Scoped styles

CSS inside {% stylesheet %} only affects elements within the current section. You can write plain class names without worrying about conflicts:

{% stylesheet %}
  .hero { min-height: 500px; }
  .hero__title { font-size: 2.5rem; }
  .hero__subtitle { font-size: 1.25rem; opacity: 0.8; }
{% endstylesheet %}

These class names will not clash with .hero in a different section. The scoping is handled for you.

Using settings in styles

You can use Quill output tags inside your stylesheet to make styles dynamic:

{% stylesheet %}
  .hero {
    background-color: {{ section.settings.bg_color }};
    color: {{ section.settings.text_color }};
    min-height: {{ section.settings.height }}px;
  }
{% endstylesheet %}

Scoped JavaScript

Code inside {% javascript %} runs only on the published storefront. It does not run in the editor preview. It is wrapped in an isolated scope so it cannot interfere with other sections or with the theme's main scripts.

{% javascript %}
  const section = document.querySelector('[data-section-id="{{ section.id }}"]');
  const slides = section.querySelectorAll('.slide');
  let current = 0;

  function next() {
    slides[current].classList.remove('active');
    current = (current + 1) % slides.length;
    slides[current].classList.add('active');
  }

  setInterval(next, 5000);
{% endjavascript %}

Use data-section-id to scope your DOM queries. This way your code only touches elements inside its own section.

Including snippets

Use render to include reusable template fragments:

<div class="product-grid">
  {% for product in section.settings.collection.products %}
    {% render 'product-card' with product, show_price: section.settings.show_prices %}
  {% endfor %}
</div>

Snippets have isolated scope. They cannot see variables from the parent template unless you pass them explicitly.

Static vs dynamic sections

Dynamic sections have presets. Merchants can add them anywhere on a page through the visual editor. They appear in the "Add section" menu.

Static sections have no presets. They are placed in the layout file and appear on every page. Use static sections for things like the header and footer.

Load a static section in the layout:

{% section 'header' %}

{{ content_for_layout }}

{% section 'footer' %}

Best practices

  • Put the schema at the very end of the file. It keeps the template code at the top where it is easy to read.
  • Keep sections focused. One section should do one thing. A hero banner section should not also contain a product grid.
  • Use meaningful data-block-id attributes on block wrappers so the editor can highlight individual blocks.
  • Give every setting a default value. The section should look complete before the merchant makes changes.
  • Test your section with no blocks, one block, and many blocks. It should handle all three cases without breaking.
  • Use CSS custom properties for colours and spacing. This makes it easy for the theme to stay consistent.

On this page