Setting Up Shopify Sections and Blocks
Sections and Blocks are the architectural foundation of Online Store 2.0. Proper setup lets your content team independently assemble pages without involving developers. Improper setup turns Theme Editor into a pain source with unpredictable behavior.
How Sections Work
A section is a file in /sections/ with a Liquid template and JSON schema in one file. The schema describes section settings and the types of blocks it accepts.
Minimal section:
{%- comment -%} sections/text-banner.liquid {%- endcomment -%}
<div class="text-banner text-banner--{{ section.settings.alignment }}">
<div class="container">
{% if section.settings.heading != blank %}
<h2>{{ section.settings.heading }}</h2>
{% endif %}
{% if section.settings.text != blank %}
<div class="text-banner__body">{{ section.settings.text }}</div>
{% endif %}
</div>
</div>
{% schema %}
{
"name": "Text Banner",
"tag": "section",
"class": "section-text-banner",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Section heading"
},
{
"type": "richtext",
"id": "text",
"label": "Text"
},
{
"type": "select",
"id": "alignment",
"label": "Alignment",
"options": [
{ "value": "left", "label": "Left aligned" },
{ "value": "center", "label": "Center aligned" },
{ "value": "right", "label": "Right aligned" }
],
"default": "center"
}
],
"presets": [
{
"name": "Text Banner"
}
]
}
{% endschema %}
Key field — presets: the section appears in the "Add section" list in Theme Editor only if it has presets.
Settings Types
| Type | Use |
|---|---|
text |
Short string |
textarea |
Multiline text |
richtext |
Text with formatting (bold, italic, links) |
html |
Arbitrary HTML |
image_picker |
Image selection from media library |
url |
Link (internal or external) |
link_list |
Navigation menu |
color |
Color |
color_scheme |
Color scheme (from config/settings_schema.json) |
font_picker |
Font from Google Fonts |
select |
Dropdown |
radio |
Radio button |
checkbox |
Checkbox |
range |
Slider with number |
collection |
Link to collection |
product |
Link to product |
blog |
Link to blog |
page |
Link to page |
video |
Video from media library |
video_url |
YouTube / Vimeo URL |
number |
Number |
paragraph |
Non-editable hint text in UI |
header |
Divider-header in UI (no content output) |
Blocks Inside a Section
Blocks are dynamic repeatable elements of a section. Example — "Benefits Grid" section:
{%- comment -%} sections/features-grid.liquid {%- endcomment -%}
<div class="features-grid features-grid--cols-{{ section.settings.columns }}">
{%- for block in section.blocks -%}
{%- case block.type -%}
{%- when 'feature_card' -%}
<div class="feature-card" {{ block.shopify_attributes }}>
{%- if block.settings.icon != blank -%}
<img
src="{{ block.settings.icon | image_url: width: 80 }}"
alt="{{ block.settings.icon.alt | escape }}"
width="80"
height="80"
loading="lazy"
>
{%- endif -%}
<h3>{{ block.settings.title }}</h3>
<p>{{ block.settings.description }}</p>
</div>
{%- endcase -%}
{%- endfor -%}
</div>
{% schema %}
{
"name": "Benefits Grid",
"tag": "section",
"settings": [
{
"type": "range",
"id": "columns",
"min": 2,
"max": 4,
"step": 1,
"label": "Number of columns",
"default": 3
}
],
"blocks": [
{
"type": "feature_card",
"name": "Benefit Card",
"settings": [
{
"type": "image_picker",
"id": "icon",
"label": "Icon"
},
{
"type": "text",
"id": "title",
"label": "Heading",
"default": "Benefit"
},
{
"type": "textarea",
"id": "description",
"label": "Description"
}
]
}
],
"max_blocks": 12,
"presets": [
{
"name": "Benefits Grid",
"blocks": [
{ "type": "feature_card" },
{ "type": "feature_card" },
{ "type": "feature_card" }
]
}
]
}
{% endschema %}
The {{ block.shopify_attributes }} attribute is required — it adds data-attributes for inline editing in Theme Editor.
Static and Dynamic Sections
Static section — hardcoded in layout/theme.liquid via {% section 'header' %}. Cannot be moved or deleted in Theme Editor.
Dynamic section — managed via page JSON template. These are added via the "Add section" button:
// templates/index.json
{
"sections": {
"main-banner": {
"type": "hero-banner",
"settings": {
"heading": "Welcome",
"subheading": "Best products at best prices"
}
},
"features": {
"type": "features-grid",
"block_order": ["block-1", "block-2", "block-3"],
"blocks": {
"block-1": { "type": "feature_card", "settings": { "title": "Fast Shipping" } },
"block-2": { "type": "feature_card", "settings": { "title": "Quality Guarantee" } },
"block-3": { "type": "feature_card", "settings": { "title": "30-Day Return" } }
}
}
},
"order": ["main-banner", "features"]
}
Color Schemes
Global color schemes are set in config/settings_schema.json and reused in any section:
{
"name": "Color Schemes",
"settings": [
{
"type": "color_scheme_group",
"id": "color_schemes",
"definition": [
{
"type": "color",
"id": "background",
"label": "Background"
},
{
"type": "color",
"id": "foreground",
"label": "Text"
},
{
"type": "color",
"id": "button",
"label": "Buttons"
}
],
"role": {
"background": "background",
"text": "foreground"
}
}
]
}
Used in a section via "type": "color_scheme".
Limits for Protection
"limit" in section or block config prevents adding extra elements:
// Prevent duplicating hero section
{ "type": "hero-banner", "limit": 1 }
// No more than 6 blocks in slider
"max_blocks": 6
Timeline
Developing 5–8 custom sections with blocks for a specific project: 3–5 days. Refactoring an existing theme moving hardcoded content to editable sections: 1–2 weeks.







