shopify developmentShopify Development

How to Create a Custom Shopify Section With Liquid and Schema

Learn how to create a custom Shopify section using Liquid and schema. Build a responsive section with text, images, buttons, settings, blocks, and Shopify theme editor controls.

16 min read
Shopify LiquidShopify SectionsShopify SchemaShopify Theme DevelopmentShopify Online Store 2.0Shopify Custom Section
How to Create a Custom Shopify Section With Liquid and Schema — Built by Saurav
How to Create a Custom Shopify Section With Liquid and Schema

One of the most useful skills in Shopify theme development is learning how to create your own custom sections.

Shopify themes already provide many built-in sections, but real projects often require custom layouts and functionality that aren't available in the default theme.

This is where Liquid and Shopify section schema become especially useful.

In this tutorial, we'll build a complete custom Shopify section from scratch. You'll learn how to create the Liquid file, add schema settings, display dynamic content, add an image picker, create a configurable button, make the section responsive, and add reusable blocks.

By the end, you'll understand not only how to create one section, but also how to approach custom section development in real Shopify projects.

Why Shopify Store Speed Matters

What Is a Shopify Custom Section?

A Shopify section is a reusable theme component that can contain Liquid, HTML, CSS, JavaScript, settings, and blocks.

A custom section allows you to create a component that store owners can configure through the Shopify theme editor instead of requiring them to edit Liquid code every time they want to change content.

For example, you might create custom sections for:

  • Hero banners
  • Image-with-text layouts
  • Testimonials
  • Feature lists
  • Promotional banners
  • FAQ sections
  • Custom product grids
  • Brand logos
  • Call-to-action sections
  • Custom content blocks

Why Shopify Store Speed Matters

What Is Shopify Section Schema?

A section's schema defines how the section can be configured in Shopify's theme editor.

Schema can define settings such as:

  • Text
  • Rich text
  • Images
  • Colors
  • Links
  • Checkboxes
  • Dropdowns
  • Ranges
  • Product selection
  • Collection selection
  • Blocks

For example, instead of hard-coding a heading:

<h2>Welcome to Our Store</h2>

you can create a setting:

{% raw %}{
    "type": "text",
    "id": "heading",
    "label": "Heading"
}{% endraw %}

and then output it using:

{% raw %}{{ section.settings.heading }}{% endraw %}

This makes the content editable from the Shopify theme editor.

Why Shopify Store Speed Matters

What We're Going to Build

For this tutorial, we'll create a responsive image and content section.

It will include:

  • Section heading
  • Description
  • Image picker
  • Button text
  • Button link
  • Text alignment
  • Color settings
  • Desktop/mobile layout
  • Optional content blocks

The final structure will look approximately like:

Custom Section
│
├── Image
│
└── Content
    ├── Heading
    ├── Description
    └── Button

Why Shopify Store Speed Matters

Step 1: Create the Section File

Shopify custom sections are normally created inside the sections directory.

Create a new file such as:

sections/custom-image-content.liquid

The filename can be different, but use a clear name that describes what the section does.

Why Shopify Store Speed Matters

Step 2: Create the Basic HTML Structure

Start with a simple section wrapper:

{% raw %}
{% endraw %}

Notice that we're using component-specific class names instead of generic classes such as .container or .content.

This is especially useful when working on an existing Shopify theme where other sections may already use similar class names.

Why Shopify Store Speed Matters

Step 3: Add a Dynamic Heading

Instead of hard-coding the heading, we'll create a section setting.

First, add the schema at the bottom of the section:

{% raw %}{% schema %}
{
    "name": "Custom Image Content",
    "settings": [
        {
            "type": "text",
            "id": "heading",
            "label": "Heading",
            "default": "Build a better shopping experience"
        }
    ],
    "presets": [
        {
            "name": "Custom Image Content"
        }
    ]
}
{% endschema %}{% endraw %}

Now you can access the setting inside the section:

{% raw %}

Why Shopify Store Speed Matters

{{ section.settings.heading }} {% endraw %}

The important relationship is:

Schema Setting
      ↓
section.settings.heading
      ↓
HTML Output

Why Shopify Store Speed Matters

Step 4: Add a Description Setting

We can add another setting for the section description.

{% raw %}{
    "type": "textarea",
    "id": "description",
    "label": "Description",
    "default": "Create flexible Shopify storefronts with reusable theme components."
}{% endraw %}

Then display it:

{% raw %}{% if section.settings.description != blank %}
    
{{ section.settings.description }}
{% endif %}{% endraw %}

Checking for blank is useful because the merchant may choose not to provide a description.

Why Shopify Store Speed Matters

Step 5: Add an Image Picker

Shopify's image_picker setting allows the merchant to select an image through the theme editor.

{% raw %}{
    "type": "image_picker",
    "id": "image",
    "label": "Image"
}{% endraw %}

You can then render the selected image:

{% raw %}{% if section.settings.image != blank %}
    {{
        section.settings.image
        | image_url: width: 1200
        | image_tag:
            loading: 'lazy',
            class: 'custom-image-content__image'
    }}
{% endif %}{% endraw %}

This is preferable to hard-coding an image URL because the store owner can change the image directly from the theme editor.

Why Shopify Store Speed Matters

Step 6: Add Button Settings

Let's make the button editable as well.

Add two settings:

{% raw %}{
    "type": "text",
    "id": "button_label",
    "label": "Button label",
    "default": "Explore Collection"
},
{
    "type": "url",
    "id": "button_link",
    "label": "Button link"
}{% endraw %}

Then render the button:

{% raw %}{% if section.settings.button_label != blank %}

    
        {{ section.settings.button_label | escape }}
    

{% endif %}{% endraw %}

You can also check that the link exists before rendering it:

{% raw %}{% if section.settings.button_label != blank
    and section.settings.button_link != blank %}

    
        {{ section.settings.button_label | escape }}
    

{% endif %}{% endraw %}

Why Shopify Store Speed Matters

Step 7: Add a Text Alignment Setting

Shopify schema can provide selectable options through a select setting.

{% raw %}{
    "type": "select",
    "id": "text_alignment",
    "label": "Text alignment",
    "options": [
        {
            "value": "left",
            "label": "Left"
        },
        {
            "value": "center",
            "label": "Center"
        },
        {
            "value": "right",
            "label": "Right"
        }
    ],
    "default": "left"
}{% endraw %}

You can then add the selected value to your class:

{% raw %}
{% endraw %}

Your CSS can then control each alignment:

.custom-image-content__content--left {
    text-align: left;
}

.custom-image-content__content--center {
    text-align: center;
}

.custom-image-content__content--right {
    text-align: right;
}

Why Shopify Store Speed Matters

Step 8: Add Color Settings

Shopify also supports color settings.

For example:

{% raw %}{
    "type": "color",
    "id": "background_color",
    "label": "Background color",
    "default": "#f5f5f5"
}{% endraw %}

You can use the selected color in the section:

{% raw %}
{% endraw %}

For larger production projects, you may prefer CSS custom properties or theme-level variables instead of placing many inline styles.

Why Shopify Store Speed Matters

Step 9: Add Responsive CSS

A custom Shopify section should not be considered finished just because it works on desktop.

Your section should also work on mobile devices.

A basic responsive layout could use CSS Grid:

.custom-image-content__container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 60px 24px;

    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 48px;

    align-items: center;
}

.custom-image-content__image {
    width: 100%;
    height: auto;
    display: block;
}

@media screen and (max-width: 749px) {
    .custom-image-content__container {
        grid-template-columns: 1fr;
        gap: 28px;
        padding: 40px 20px;
    }
}

On desktop, the image and content appear next to each other. On smaller screens, they stack vertically.

Why Shopify Store Speed Matters

Step 10: Add Mobile-Specific Controls

Sometimes a merchant needs different spacing or layout behavior on mobile.

You can expose additional settings where appropriate, but don't create a setting for every CSS property.

A good section should provide useful design controls without overwhelming the merchant with dozens of settings.

Why Shopify Store Speed Matters

Step 11: Add Blocks to the Section

Now let's make the section more flexible by adding blocks.

Imagine that the content area should support multiple features:

Custom Image Content
│
├── Heading
├── Description
├── Feature Block
├── Feature Block
└── Button

Define a block in the schema:

{% raw %}"blocks": [
    {
        "type": "feature",
        "name": "Feature",
        "settings": [
            {
                "type": "text",
                "id": "title",
                "label": "Title"
            },
            {
                "type": "textarea",
                "id": "text",
                "label": "Description"
            }
        ]
    }
]{% endraw %}

Then loop through the blocks:

{% raw %}{% for block in section.blocks %}

    

{{ block.settings.title | escape }}

{% if block.settings.text != blank %}

{{ block.settings.text }}

{% endif %}
{% endfor %}{% endraw %}

The block.shopify_attributes attribute is important when working with blocks in the Shopify theme editor because it helps Shopify identify the block within the editor.

Why Shopify Store Speed Matters

Step 12: Add Block Limits

You can control how many blocks the merchant can add.

{% raw %}"limit": 4{% endraw %}

For example:

{% raw %}"blocks": [
    {
        "type": "feature",
        "name": "Feature",
        "limit": 4,
        "settings": [
            {
                "type": "text",
                "id": "title",
                "label": "Title"
            }
        ]
    }
]{% endraw %}

Use limits when the design has a practical maximum. For example, allowing 20 feature cards might create a poor user experience even if the Liquid code technically supports it.

Why Shopify Store Speed Matters

Step 13: Add a Preset

A preset allows the section to be added to the theme editor with a predefined configuration.

{% raw %}"presets": [
    {
        "name": "Custom Image Content"
    }
]{% endraw %}

Without a useful preset, the merchant may not see the section in the same convenient way when adding sections through the theme editor.

Why Shopify Store Speed Matters

Complete Custom Section Example

Now let's put the main concepts together.

The following example creates a responsive image-and-content section with heading, description, image, button, alignment, and feature blocks.

{% raw %}
{% if section.settings.image != blank %}
{{ section.settings.image | image_url: width: 1200 | image_tag: loading: 'lazy', class: 'custom-image-content__image' }}
{% endif %}
{% if section.settings.heading != blank %}

Why Shopify Store Speed Matters

{{ section.settings.heading | escape }} {% endif %} {% if section.settings.description != blank %}
{{ section.settings.description }}
{% endif %} {% if section.blocks.size > 0 %}
{% for block in section.blocks %}
{% if block.settings.title != blank %}

{{ block.settings.title | escape }}

{% endif %} {% if block.settings.text != blank %}

{{ block.settings.text }}

{% endif %}
{% endfor %}
{% endif %} {% if section.settings.button_label != blank and section.settings.button_link != blank %} {{ section.settings.button_label | escape }} {% endif %}
{% schema %} { "name": "Custom Image Content", "settings": [ { "type": "image_picker", "id": "image", "label": "Image" }, { "type": "text", "id": "heading", "label": "Heading", "default": "Build a better shopping experience" }, { "type": "textarea", "id": "description", "label": "Description", "default": "Create flexible Shopify storefronts with reusable theme components." }, { "type": "text", "id": "button_label", "label": "Button label", "default": "Explore Collection" }, { "type": "url", "id": "button_link", "label": "Button link" }, { "type": "select", "id": "text_alignment", "label": "Text alignment", "options": [ { "value": "left", "label": "Left" }, { "value": "center", "label": "Center" }, { "value": "right", "label": "Right" } ], "default": "left" }, { "type": "color", "id": "background_color", "label": "Background color", "default": "#f5f5f5" } ], "blocks": [ { "type": "feature", "name": "Feature", "limit": 4, "settings": [ { "type": "text", "id": "title", "label": "Title" }, { "type": "textarea", "id": "text", "label": "Description" } ] } ], "presets": [ { "name": "Custom Image Content" } ] } {% endschema %}{% endraw %}

Why Shopify Store Speed Matters

Step 14: Add the CSS

You can keep the styling in a dedicated CSS file instead of placing a large style block directly inside the section.

.custom-image-content {
    width: 100%;
}

.custom-image-content__container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 64px 24px;

    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 48px;

    align-items: center;
}

.custom-image-content__media {
    width: 100%;
}

.custom-image-content__image {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 12px;
}

.custom-image-content__content {
    width: 100%;
}

.custom-image-content__content--left {
    text-align: left;
}

.custom-image-content__content--center {
    text-align: center;
}

.custom-image-content__content--right {
    text-align: right;
}

.custom-image-content__description {
    margin-top: 16px;
}

.custom-image-content__features {
    display: grid;
    gap: 16px;
    margin-top: 24px;
}

.custom-image-content__feature {
    padding: 16px;
}

.custom-image-content__button {
    display: inline-block;
    margin-top: 28px;
    padding: 14px 24px;
    text-decoration: none;
}

@media screen and (max-width: 749px) {

    .custom-image-content__container {
        grid-template-columns: 1fr;
        gap: 28px;
        padding: 40px 20px;
    }

    .custom-image-content__content--left,
    .custom-image-content__content--center,
    .custom-image-content__content--right {
        text-align: left;
    }

    .custom-image-content__button {
        width: 100%;
        text-align: center;
    }
}

The exact design can obviously be adapted to match the theme. The important part is that the section remains responsive and doesn't depend on fixed desktop dimensions.

Why Shopify Store Speed Matters

How to Add the Custom Section to a Shopify Theme

After creating and saving the section, open the Shopify theme editor.

Navigate to the page where you want to use the section and choose Add section.

Your section should appear using the name defined in the schema:

"name": "Custom Image Content"

After adding it, the settings you defined in the schema should be available in the theme editor.

Why Shopify Store Speed Matters

Why Use Schema Instead of Hard-Coded Content?

Hard-coded content can be acceptable for certain developer-only functionality, but most merchant-facing sections should expose appropriate settings.

Compare:

<h2>Summer Collection</h2>

with:

{% raw %}{{ section.settings.heading }}{% endraw %}

The second approach allows the merchant to change the heading without touching the theme code.

This is one of the biggest advantages of Shopify's theme editor.

Why Shopify Store Speed Matters

Common Shopify Section Development Mistakes

1. Forgetting the Schema

A section without a valid schema may not behave as expected in the theme editor.

Always validate the schema structure and make sure the JSON is properly formatted.

2. Using Duplicate IDs

Every setting inside a section should have an appropriate unique id.

For example:

"id": "heading"
"id": "description"
"id": "image"

Avoid defining multiple settings with the same ID.

3. Forgetting to Check for Empty Values

Merchants don't always fill every setting.

Instead of blindly rendering an optional element:

{% raw %}{{ section.settings.button_label }}{% endraw %}

check whether the value exists:

{% raw %}{% if section.settings.button_label != blank %}
    {{ section.settings.button_label }}
{% endif %}{% endraw %}

4. Making the Section Desktop-Only

A section should be tested on mobile devices before it is considered complete.

Pay attention to:

  • Image dimensions
  • Text wrapping
  • Button width
  • Spacing
  • Column stacking
  • Font sizes
  • Overflow

5. Using Generic CSS Classes

Classes such as .title, .container, or .button can conflict with existing theme styles.

Use component-specific naming:

.custom-image-content__title
.custom-image-content__button
.custom-image-content__container

6. Putting Everything in One File

Small sections can be self-contained, but larger projects benefit from separating reusable components into snippets and keeping CSS and JavaScript organized.

Why Shopify Store Speed Matters

Section vs Snippet: Which Should You Use?

A section and a snippet serve different purposes.

Requirement Use
Merchant-configurable page component Section
Reusable small Liquid component Snippet
Multiple configurable items Blocks inside a section
Reusable product card Snippet
Hero banner Section

If you want a deeper explanation of this distinction, see our guide on Shopify Sections vs Snippets vs Blocks .

Why Shopify Store Speed Matters

How to Make Custom Sections Easier to Maintain

Creating a section that works is only the first step. A professional Shopify developer should also think about future maintenance.

Use Clear Naming

Give the section and its settings meaningful names.

Keep Schema Organized

Group related settings together instead of creating a long, unstructured list.

Avoid Unnecessary Settings

Don't expose every possible CSS property as a theme setting. Provide controls that are actually useful to the merchant.

Reuse Components

If the same markup appears in several sections, consider extracting it into a snippet.

Test Multiple Screen Sizes

Test desktop, tablet, and mobile layouts before considering the section complete.

Why Shopify Store Speed Matters

Performance Considerations

A custom section should also be developed with performance in mind.

Avoid adding unnecessary JavaScript libraries or loading assets that aren't required by the section.

For images, use Shopify's image URL and image rendering capabilities appropriately and avoid serving unnecessarily large images.

If a section contains JavaScript, consider whether that code needs to run on every page or only when the section is actually present.

A flexible section shouldn't become a performance problem simply because it contains too many features.

Why Shopify Store Speed Matters

SEO Considerations for Custom Shopify Sections

Custom sections can also affect SEO if they contain important content.

Keep these points in mind:

  • Use semantic HTML where appropriate.
  • Use meaningful headings instead of styling random elements as headings.
  • Provide useful image alt text.
  • Don't hide important content unnecessarily.
  • Make links descriptive and accessible.
  • Keep the section responsive and usable on mobile.

SEO should not mean filling every section with keywords. The goal is to create useful content and a good experience while keeping the markup understandable.

Why Shopify Store Speed Matters

Custom Section Development Workflow

A practical workflow for creating a custom Shopify section is:

  1. Define the design and functionality.
  2. Create the section file.
  3. Build the basic HTML structure.
  4. Add Liquid objects and dynamic content.
  5. Define schema settings.
  6. Add blocks if repeated content is required.
  7. Add responsive CSS.
  8. Add JavaScript only when necessary.
  9. Test the section in the theme editor.
  10. Test desktop and mobile layouts.
  11. Check accessibility and semantic HTML.
  12. Review performance before deployment.

Why Shopify Store Speed Matters

Frequently Asked Questions

What is a Shopify custom section?

A Shopify custom section is a reusable theme component created with Liquid and a section schema. It can expose configurable settings and blocks that merchants can manage through the Shopify theme editor.

Where do I create a Shopify section?

Shopify theme sections are created inside the theme's sections directory. A section is usually a Liquid file containing the component markup and its schema.

What is Shopify section schema?

Section schema defines the settings, blocks, presets, and other configuration information used by Shopify's theme editor.

How do I make a Shopify section editable?

Add appropriate settings to the section schema and access those values through objects such as section.settings.heading.

Can a Shopify section have multiple blocks?

Yes. A section can define one or more block types in its schema and loop through them using section.blocks.

How do I make a custom Shopify section responsive?

Use responsive CSS with flexible layouts such as CSS Grid or Flexbox, appropriate image sizing, mobile breakpoints, and testing across different screen sizes. Avoid fixed desktop-only dimensions.

Can I use JavaScript inside a Shopify section?

Yes. JavaScript can be used for interactive functionality such as sliders, tabs, accordions, modals, and dynamic UI behavior. Keep the JavaScript organized and avoid loading unnecessary code globally.

Should CSS be inside the Shopify section file?

It can be for small, self-contained components, but larger Shopify projects are generally easier to maintain when CSS is organized in dedicated asset files or another consistent styling system.

Why Shopify Store Speed Matters

Final Thoughts

Creating a custom Shopify section is one of the most useful skills you can learn as a Shopify theme developer.

The basic process is straightforward: create a section file, build the Liquid and HTML structure, define the schema, connect settings through section.settings, add blocks when necessary, and make the component responsive.

The real challenge is creating sections that are not only functional but also flexible, maintainable, accessible, performant, and easy for a merchant to manage.

Avoid hard-coding content that the store owner will need to change. Use schema settings for merchant-controlled values, blocks for repeated configurable content, and snippets for reusable Liquid components.

Once you become comfortable with this workflow, you can create almost any custom Shopify component—from simple promotional banners to complex product sections and fully customized storefront experiences.

The best Shopify sections are not simply sections that look good. They are components that make the store easier to manage while keeping the underlying theme code clean and reliable.

About the author

Saurav Prajapati

Shopify & Frontend Developer sharing practical experience with Shopify, Liquid, React, Next.js, APIs, and modern web development.

Share this article