> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Shopify/horizon/llms.txt
> Use this file to discover all available pages before exploring further.

# Liquid Storefronts Features

> Modern Liquid features and APIs used in Horizon, including theme blocks, content_for, and advanced rendering patterns

## Introduction

Horizon showcases the latest **Liquid Storefronts** features, representing the future of Shopify theme development. These modern Liquid capabilities enable more flexible, maintainable, and powerful themes.

<Note>
  Liquid Storefronts is the evolution of Shopify's templating system, introducing features like theme blocks, `content_for`, section groups, and more.
</Note>

## Theme Blocks

Theme blocks are the cornerstone of Liquid Storefronts, enabling reusable, composable components.

### What are Theme Blocks?

Theme blocks are Liquid files in the `blocks/` directory that:

* Can be added to any section that accepts `{ "type": "@theme" }`
* Are prefixed with an underscore (`_heading.liquid`, `_content.liquid`)
* Include their own schema and settings
* Are fully reusable across sections

### Basic Theme Block Structure

```liquid blocks/_heading.liquid theme={null}
{%- doc -%}
  Renders a heading block.

  @param {string} text
{%- enddoc -%}

{% render 'text', width: '100%', block: block, fallback_text: text %}

{% schema %}
{
  "name": "t:names.heading",
  "tag": null,
  "settings": [
    {
      "type": "richtext",
      "id": "text",
      "label": "t:settings.text"
    },
    {
      "type": "select",
      "id": "type_preset",
      "label": "t:settings.preset",
      "options": [
        { "value": "h1", "label": "t:options.h1" },
        { "value": "h2", "label": "t:options.h2" },
        { "value": "h3", "label": "t:options.h3" }
      ],
      "default": "h2"
    },
    {
      "type": "text_alignment",
      "id": "alignment",
      "label": "t:settings.alignment",
      "default": "left"
    }
  ]
}
{% endschema %}
```

### Accepting Theme Blocks in Sections

```liquid sections/_blocks.liquid theme={null}
{% capture children %}
  {% content_for 'blocks' %}
{% endcapture %}

{% render 'section', section: section, children: children %}

{% schema %}
{
  "name": "t:names.section",
  "blocks": [
    { "type": "@theme" },  // Accept ANY theme block
    { "type": "@app" },    // Accept app blocks
    { "type": "_divider" } // Specific theme block
  ]
}
{% endschema %}
```

<Accordion title="Why type @theme?">
  The `@theme` wildcard allows merchants to add **any** theme block from your `blocks/` directory to the section. This provides maximum flexibility without hardcoding which blocks are allowed.

  Benefits:

  * Merchants can compose custom layouts
  * No need to update section schema when adding new blocks
  * Enables true composability
</Accordion>

### Nestable Theme Blocks

Horizon's `_content` block demonstrates **nested blocks**:

```liquid blocks/_content.liquid theme={null}
{% capture children %}
  {% content_for 'blocks' %}
{% endcapture %}

{% render 'group', 
  children: children, 
  settings: block.settings, 
  shopify_attributes: block.shopify_attributes 
%}

{% schema %}
{
  "name": "t:names.content",
  "tag": null,
  "blocks": [
    { "type": "@theme" },
    { "type": "@app" },
    { "type": "_divider" }
  ],
  "settings": [
    {
      "type": "select",
      "id": "horizontal_alignment_flex_direction_column",
      "options": [
        { "value": "flex-start", "label": "t:options.left" },
        { "value": "center", "label": "t:options.center" },
        { "value": "flex-end", "label": "t:options.right" }
      ]
    },
    {
      "type": "range",
      "id": "gap",
      "min": 0,
      "max": 100,
      "default": 24
    }
  ]
}
{% endschema %}
```

<Steps>
  <Step title="Content block added to section">
    Merchant adds `_content` block to a section
  </Step>

  <Step title="Nested blocks added">
    Merchant adds `_heading`, `_image`, and `button` blocks inside the `_content` block
  </Step>

  <Step title="Rendered with proper nesting">
    The `content_for 'blocks'` captures nested children, and `group` snippet renders them with proper layout
  </Step>
</Steps>

## content\_for Tag

The `{% content_for %}` tag is a powerful Liquid Storefronts feature for rendering dynamic content.

### Basic Usage

```liquid theme={null}
{% capture children %}
  {% content_for 'blocks' %}
{% endcapture %}

{{ children }}
```

### Advanced: content\_for with Static Blocks

```liquid sections/carousel.liquid theme={null}
<div class="section-carousel">
  {%- comment -%} Static header block {%- endcomment -%}
  {% content_for 'block', type: 'group', id: 'static-header' %}

  {%- comment -%} Static carousel content {%- endcomment -%}
  {% content_for 'block', type: '_carousel-content', id: 'static-carousel-content' %}
</div>
```

<Note>
  Static blocks are defined in the section schema with `"static": true` and always render in the same position.
</Note>

### content\_for with Context

Pass additional context to blocks:

```liquid theme={null}
{% content_for 'block', 
  type: '_product-card', 
  id: 'static-product-card',
  closest.product: product,
  closest.collection: collection 
%}
```

Blocks can access context via `closest` object:

```liquid blocks/_product-card.liquid theme={null}
<div class="product-card">
  <h3>{{ closest.product.title }}</h3>
  <p>{{ closest.product.price | money }}</p>
</div>
```

## Section Groups

Section groups allow multiple sections to be rendered as a cohesive unit.

### Header Group

```liquid layout/theme.liquid theme={null}
<div id="header-group">
  {% sections 'header-group' %}
</div>
```

```json sections/header-group.json theme={null}
{
  "type": "header",
  "name": "t:names.header",
  "sections": {
    "header_announcements": {
      "type": "header-announcements",
      "blocks": {
        "announcement": {
          "type": "_announcement",
          "settings": { "text": "Welcome to our store" }
        }
      }
    },
    "header_section": {
      "type": "header",
      "blocks": {
        "header-logo": { "type": "_header-logo", "static": true },
        "header-menu": { "type": "_header-menu", "static": true }
      },
      "settings": {
        "logo_position": "left",
        "enable_sticky_header": "always"
      }
    }
  },
  "order": ["header_announcements", "header_section"]
}
```

<CardGroup cols={2}>
  <Card title="Benefits" icon="check">
    * Logical grouping of related sections
    * Independent customization
    * Better performance (grouped rendering)
    * Cleaner template files
  </Card>

  <Card title="Use Cases" icon="lightbulb">
    * Header (announcements + navigation)
    * Footer (links + newsletter + social)
    * Product page (details + recommendations)
  </Card>
</CardGroup>

## Static vs Dynamic Blocks

### Static Blocks

Static blocks always appear and cannot be removed by merchants:

```json theme={null}
{
  "blocks": {
    "header-logo": {
      "type": "_header-logo",
      "static": true,
      "settings": { "hide_logo_on_home_page": false }
    }
  }
}
```

### Dynamic Blocks

Dynamic blocks can be added, removed, and reordered:

```json theme={null}
{
  "blocks": {
    "text_123": {
      "type": "_heading",
      "settings": { "text": "<h2>Welcome</h2>" }
    },
    "image_456": {
      "type": "_image",
      "settings": { "image": "shopify://shop_images/hero.jpg" }
    }
  },
  "block_order": ["text_123", "image_456"]
}
```

## Documentation Tags

Horizon uses `{%- doc -%}` tags for inline documentation:

```liquid theme={null}
{%- doc -%}
  Renders a wrapper section

  @param {section} section - The section object
  @param {string} children - The children of the section
  @param {boolean} [apply_overlay] - Optional overlay flag

  @example
  {% render 'section', section: section, children: children %}
{%- enddoc -%}
```

<Tabs>
  <Tab title="Benefits">
    * Self-documenting code
    * Better developer experience
    * Clear parameter expectations
    * Usage examples embedded in code
  </Tab>

  <Tab title="Best Practices">
    * Document all snippets and blocks
    * Include parameter types
    * Mark optional parameters with `[]`
    * Provide usage examples
  </Tab>
</Tabs>

## Visible\_if Conditions

Conditionally show/hide settings in the theme editor:

```json theme={null}
{
  "settings": [
    {
      "type": "checkbox",
      "id": "toggle_overlay",
      "label": "t:settings.background_overlay"
    },
    {
      "type": "color",
      "id": "overlay_color",
      "label": "t:settings.overlay_color",
      "visible_if": "{{ section.settings.toggle_overlay }}"
    },
    {
      "type": "select",
      "id": "overlay_style",
      "options": [
        { "value": "solid", "label": "t:options.solid" },
        { "value": "gradient", "label": "t:options.gradient" }
      ],
      "visible_if": "{{ section.settings.toggle_overlay }}"
    },
    {
      "type": "select",
      "id": "gradient_direction",
      "options": [
        { "value": "to top", "label": "t:options.up" },
        { "value": "to bottom", "label": "t:options.down" }
      ],
      "visible_if": "{{ section.settings.toggle_overlay and section.settings.overlay_style == 'gradient' }}"
    }
  ]
}
```

<Note>
  `visible_if` creates dynamic, contextual settings that only appear when relevant, improving the merchant experience.
</Note>

## Advanced Liquid Patterns

### Liquid Tag

The `{% liquid %}` tag allows multi-line Liquid without repetitive delimiters:

```liquid theme={null}
{% liquid
  assign media_count = 0
  assign media_1 = 'none'
  assign media_2 = 'none'
  
  if section.settings.image_1 != blank and section.settings.media_type_1 == 'image'
    assign media_1 = 'image'
    assign media_count = media_count | plus: 1
  endif
  
  if section.settings.video_1 != blank and section.settings.media_type_1 == 'video'
    assign media_1 = 'video'
    assign media_count = media_count | plus: 1
  endif
%}
```

Vs. traditional syntax:

```liquid theme={null}
{% assign media_count = 0 %}
{% assign media_1 = 'none' %}
{% if section.settings.image_1 != blank %}
  {% assign media_1 = 'image' %}
{% endif %}
```

### Inline Stylesheets

Scope CSS to specific components:

```liquid snippets/bento-grid.liquid theme={null}
{% for item in items %}
  <div class="bento-box__item">
    {{ item }}
  </div>
{% endfor %}

{% stylesheet %}
  .bento-box {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    column-gap: var(--bento-gap);
  }

  .bento-box__item:nth-child(1) {
    grid-area: A;
  }
{% endstylesheet %}
```

<Accordion title="Benefits of Inline Stylesheets">
  * **Scoped styles**: CSS only loads when the snippet is used
  * **Co-location**: Styles live with markup
  * **Performance**: Automatic critical CSS extraction
  * **Maintainability**: Easier to update components
</Accordion>

## Translation Integration

Horizon uses `t:` prefixes for all translatable strings:

```json theme={null}
{
  "name": "t:names.heading",
  "settings": [
    {
      "type": "text",
      "label": "t:settings.text",
      "info": "t:info.heading_guidelines"
    }
  ]
}
```

Translation files in `locales/`:

```json locales/en.default.json theme={null}
{
  "names": {
    "heading": "Heading",
    "section": "Custom Section"
  },
  "settings": {
    "text": "Text content",
    "alignment": "Alignment"
  },
  "options": {
    "left": "Left",
    "center": "Center",
    "right": "Right"
  }
}
```

## Color Schemes

Horizon uses the color scheme system:

```json theme={null}
{
  "type": "color_scheme",
  "id": "color_scheme",
  "label": "t:settings.color_scheme",
  "default": "scheme-1"
}
```

Applied via CSS classes:

```liquid theme={null}
<div class="section color-{{ section.settings.color_scheme }}">
  <!-- Content -->
</div>
```

Color scheme CSS variables:

```css theme={null}
.color-scheme-1 {
  --color-background: #ffffff;
  --color-foreground: #121212;
  --color-primary: #007ace;
}
```

## Request Object Enhancements

### Visual Preview Mode

```liquid theme={null}
<div
  class="section"
  {% if request.visual_preview_mode %}
    data-shopify-visual-preview
  {% endif %}
>
```

### Design Mode Detection

```liquid theme={null}
<html
  {% if request.design_mode %}
    class="shopify-design-mode"
  {% endif %}
>
```

```liquid theme={null}
{% if request.design_mode %}
  {%- render 'theme-editor' -%}
{% endif %}
```

## Performance Features

### SVH Units

Horizon uses `svh` (small viewport height) for better mobile support:

```liquid theme={null}
style="
  {% if section.settings.section_height == 'custom' %}
    --section-min-height: {{ section.settings.section_height_custom }}svh;
  {% elsif section.settings.section_height == 'full-screen' %}
    --section-min-height: 100svh;
  {% endif %}
"
```

### Lazy Loading

```liquid theme={null}
{{ image | image_url: width: 800 | image_tag: loading: 'lazy' }}
```

### Preloading Critical Assets

```liquid theme={null}
<link rel="preload" as="image" href="{{ section.settings.image | image_url: width: 1200 }}">
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use theme blocks for reusability">
    Create small, focused theme blocks that do one thing well. Compose complex layouts by combining multiple blocks.
  </Accordion>

  <Accordion title="Leverage content_for for flexibility">
    Use `content_for 'blocks'` to capture dynamic content and `content_for 'block'` for static blocks.
  </Accordion>

  <Accordion title="Document with {%- doc -%} tags">
    Always document snippets and complex blocks with parameter descriptions and examples.
  </Accordion>

  <Accordion title="Use visible_if for conditional settings">
    Hide irrelevant settings to create a better merchant experience.
  </Accordion>

  <Accordion title="Embrace the {% liquid %} tag">
    Use `{% liquid %}` for complex logic to improve readability.
  </Accordion>

  <Accordion title="Scope CSS with {% stylesheet %}">
    Keep CSS co-located with components using inline stylesheet tags.
  </Accordion>
</AccordionGroup>

## Examples from Horizon

### Complete Section Example

```liquid sections/_blocks.liquid theme={null}
{% capture children %}
  {% content_for 'blocks' %}
{% endcapture %}

{% render 'section', section: section, children: children %}

{% schema %}
{
  "name": "t:names.section",
  "class": "section-wrapper",
  "blocks": [
    { "type": "@theme" },
    { "type": "@app" },
    { "type": "_divider" }
  ],
  "settings": [
    {
      "type": "select",
      "id": "content_direction",
      "label": "t:settings.direction",
      "options": [
        { "value": "column", "label": "t:options.vertical" },
        { "value": "row", "label": "t:options.horizontal" }
      ],
      "default": "column"
    },
    {
      "type": "range",
      "id": "gap",
      "label": "t:settings.gap",
      "min": 0,
      "max": 100,
      "default": 12
    },
    {
      "type": "color_scheme",
      "id": "color_scheme",
      "label": "t:settings.color_scheme",
      "default": "scheme-1"
    }
  ],
  "presets": [
    {
      "name": "t:names.custom_section",
      "category": "t:categories.layout"
    }
  ]
}
{% endschema %}
```

## Migration from Legacy Patterns

<Tabs>
  <Tab title="Before (Legacy)">
    ```liquid theme={null}
    {%- section 'header' -%}

    {% for block in section.blocks %}
      {% case block.type %}
        {% when 'heading' %}
          <h2>{{ block.settings.text }}</h2>
        {% when 'image' %}
          {{ block.settings.image | image_url: width: 800 | image_tag }}
      {% endcase %}
    {% endfor %}
    ```
  </Tab>

  <Tab title="After (Liquid Storefronts)">
    ```liquid theme={null}
    {% sections 'header-group' %}

    {% capture children %}
      {% content_for 'blocks' %}
    {% endcapture %}

    {{ children }}
    ```

    With theme blocks:

    * `blocks/_heading.liquid`
    * `blocks/_image.liquid`
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="Theme Blocks Deep Dive" icon="cube" href="/architecture/theme-blocks">
    Learn advanced theme blocks patterns
  </Card>

  <Card title="Theme Structure" icon="folder-tree" href="/architecture/theme-structure">
    Understand sections, blocks, and snippets
  </Card>

  <Card title="Development Guide" icon="code" href="/development/workflow">
    Start building with Liquid Storefronts
  </Card>

  <Card title="API Reference" icon="book" href="https://shopify.dev/docs/storefronts/themes/architecture/blocks/theme-blocks">
    Official Shopify documentation
  </Card>
</CardGroup>
