ezomfy
All posts
June 23, 202610 min read

Shopify Section vs. Block: Master When and How to Use Them (with Code)

Shopify developers and merchants often misuse sections for everything. I'll show you why blocks are crucial for repeating content and how getting this wrong leads to unmaintainable themes in months.

A

Ashraful

Shopify Select Partner

Detailed view of code and file structure in a software development environment. — Photo by Daniil Komov on Pexels

I see it happen constantly. A new client comes to me with a Shopify theme that's barely 6 months old, and the theme editor is a nightmare. Endless scrolling, duplicate content, and a merchant who's frustrated because simple updates feel impossible. The root cause? A fundamental misunderstanding of Shopify sections vs. blocks.

Here's my thesis, direct and unapologetic: Sections are for structuring your page layout. Blocks are for repeating content within those structures. Get this wrong, and I guarantee your theme will become unmaintainable, slow, and a source of constant headaches in short order. This isn't just theory; I've built 700+ Shopify stores and audited countless others. The code doesn't lie.

The Core Difference: Shopify Section vs Block Explained

Let's get straight to what a Shopify section is. Think of a section as a large, self-contained component that defines a distinct area of your page. It’s a hero banner, a product grid, a testimonials area, a footer. Each section is typically unique in its layout and purpose on a given page, though you can use the same section multiple times. It brings its own settings, styles, and logic. A section's primary job is to provide a structural container for content.

{% schema %}
  {
    "name": "Hero banner",
    "settings": [
      {
        "type": "image_picker",
        "id": "image",
        "label": "Background image"
      },
      {
        "type": "text",
        "id": "heading",
        "label": "Heading",
        "default": "Your Brand Story"
      }
    ],
    "presets": [
      {
        "name": "Hero banner"
      }
    ]
  }
{% endschema %}

<div class="hero-banner">
  <img src="{{ section.settings.image | image_url: width: 2000 }}" alt="{{ section.settings.heading }}">
  <h1>{{ section.settings.heading }}</h1>
</div>

Now, blocks. Blocks are the atomic, repeatable units of content inside a section. If your section is a Hero Banner, blocks might be individual slides in a carousel within that banner. If your section is Testimonials, blocks are individual testimonials. They inherit some context from their parent section but have their own distinct settings. Blocks allow merchants to add, remove, reorder, and edit multiple instances of similar content without duplicating entire sections.

It’s like building a house. The Kitchen is a section, the Living Room is a section. Inside the Kitchen section, you have Cabinet blocks, Appliance blocks, and a Countertop block. You wouldn't make a whole new kitchen section just to add another cabinet, would you? You'd add another Cabinet block. This distinction is critical for scalable, maintainable themes.

Why Most Developers Get Shopify Section vs Block Wrong

Here's what nobody talks about: The mistake I see most often is developers, especially those new to Shopify 2.0 or migrating from older theme structures, using sections for everything. They need a row of three feature icons? Three separate sections. They need 10 testimonials? Ten separate testimonial sections. It "works" in the sense that the content appears on the storefront, but it utterly destroys the merchant's experience in the theme editor.

Why does this happen? Sometimes it's a lack of understanding. More often, it's about speed. It's quicker to copy-paste an entire section and change a few settings than to architect a flexible section with blocks. But this short-term gain is a long-term poison. I’ve seen themes where a merchant had to scroll for literally minutes through a single page's section list in the editor, all because simple, repeatable content was implemented as unique sections.

A Client War Story: The Testimonial Tangle

I recently took over a project for a fast-growing DTC beauty brand. They had a Shopify store built by a less experienced agency. Their product pages needed a section for customer testimonials. Instead of using blocks, the previous developers had created a Testimonial section. Every single testimonial was its own section. The client initially had three, which was fine. But as their brand grew, they wanted to add more – they aimed for 15-20 testimonials per product. The result? To add a new testimonial, the client had to click "Add Section," find "Testimonial," add it, then manually drag it into the correct order. The theme editor became a nightmare of endless, identical sections, making updates agonizingly slow and error-prone. We rebuilt that component as a single Testimonials section with individual Testimonial Item blocks, cutting their content update time by 80% and making the editor a joy to use. This isn't theoretical; this is the reality of day-to-day store management.

When to Use a Section: Structural Layouts

Sections are your big-picture layout tools. They define the overall architecture of a page. If you're building something that typically appears once or has a very distinct, unique purpose, it's a section. Think about the fundamental components that make up a typical e-commerce page:

  • Hero Banners: The main visual at the top of a page.
  • Featured Product Grids: A section dedicated to showcasing a collection of products.
  • Image with Text: A versatile section for marketing messages.
  • Contact Forms: A specific functional area.
  • Global Elements: Header and Footer (though these are often rendered separately in layout/theme.liquid, they function conceptually as sections).

When you're mapping out a new page template, the first thing you should be thinking about is, "What are the distinct, top-level content areas here?" Those are your sections. They usually have broad settings that affect the entire area, like background color, padding, or overall layout options (e.g., full-width vs. contained).

<!-- sections/image-with-text.liquid -->

<section class="image-with-text-section">
  <div class="container">
    <div class="image-wrapper">
      {% if section.settings.image %}
        <img src="{{ section.settings.image | image_url: width: 1000 }}" alt="{{ section.settings.image.alt | escape }}">
      {% else %}
        {{ 'image' | placeholder_svg_tag: 'placeholder-svg' }}
      {% endif %}
    </div>
    <div class="text-wrapper">
      {% if section.settings.heading != blank %}
        <h2>{{ section.settings.heading }}</h2>
      {% endif %}
      {% if section.settings.text != blank %}
        <p>{{ section.settings.text }}</p>
      {% endif %}
      {% if section.settings.button_label != blank and section.settings.button_link != blank %}
        <a href="{{ section.settings.button_link }}" class="button">{{ section.settings.button_label }}</a>
      {% endif %}
    </div>
  </div>
</section>

{% schema %}
  {
    "name": "Image with Text",
    "settings": [
      {
        "type": "image_picker",
        "id": "image",
        "label": "Image"
      },
      {
        "type": "text",
        "id": "heading",
        "label": "Heading",
        "default": "Image with text"
      },
      {
        "type": "richtext",
        "id": "text",
        "label": "Text",
        "default": "<p>Pair large text with an image to tell a story.</p>"
      },
      {
        "type": "text",
        "id": "button_label",
        "label": "Button label"
      },
      {
        "type": "url",
        "id": "button_link",
        "label": "Button link"
      }
    ],
    "presets": [
      {
        "name": "Image with Text"
      }
    ]
  }
{% endschema %}

This image-with-text is a perfect example of a section. It has a distinct purpose, a clear layout, and its settings control the entire content block. You wouldn't typically have 10 identical 'Image with Text' blocks side-by-side; you'd have one, or maybe two, strategically placed sections on a page.

When to Use a Block: Repeating Content Units

Blocks are where the magic of flexibility happens. If you find yourself needing to display a list of similar items, where each item has the same structure but different content, that's a job for blocks. This is where your theme goes from rigid to dynamic, empowering merchants to manage their content efficiently.

Consider these common use cases for blocks:

  • Slides in a Carousel/Slider Section: Each slide is a block.
  • Individual Testimonials within a Testimonials Section: Each testimonial entry is a block.
  • Feature Cards/Icons: A section for displaying key features, where each feature card is a block.
  • Column Items: A section with multiple columns, where each column's content is a block.
  • Menu Items: In a custom navigation section, each link could be a block.

Blocks thrive on repetition. They allow you to define a single content structure (e.g., testimonial_item with author, quote, image) and then let the merchant add as many of those items as they need, reorder them, and configure each one individually. This is paramount for a good merchant experience.

<!-- sections/testimonials-list.liquid -->

<section class="testimonials-section">
  <div class="container">
    <h2 class="section-heading">{{ section.settings.heading }}</h2>
    <div class="testimonials-grid">
      {% for block in section.blocks %}
        <div class="testimonial-item">
          {% if block.settings.image %}
            <img src="{{ block.settings.image | image_url: width: 100 }}" alt="{{ block.settings.author | escape }}">
          {% endif %}
          <blockquote class="testimonial-quote">{{ block.settings.quote }}</blockquote>
          <p class="testimonial-author">- {{ block.settings.author }}</p>
        </div>
      {% endfor %}
    </div>
  </div>
</section>

{% schema %}
  {
    "name": "Testimonials List",
    "settings": [
      {
        "type": "text",
        "id": "heading",
        "label": "Heading",
        "default": "What Our Customers Say"
      }
    ],
    "blocks": [
      {
        "type": "testimonial_item",
        "name": "Testimonial",
        "settings": [
          {
            "type": "image_picker",
            "id": "image",
            "label": "Author Image"
          },
          {
            "type": "text",
            "id": "author",
            "label": "Author Name",
            "default": "Jane Doe"
          },
          {
            "type": "textarea",
            "id": "quote",
            "label": "Quote",
            "default": "This product changed my life! Highly recommend."
          }
        ]
      }
    ],
    "max_blocks": 10,
    "presets": [
      {
        "name": "Testimonials List",
        "blocks": [
          {
            "type": "testimonial_item"
          },
          {
            "type": "testimonial_item"
          },
          {
            "type": "testimonial_item"
          }
        ]
      }
    ]
  }
{% endschema %}

In this example, the Testimonials List is the section. It has a heading setting for the overall section. Inside, it defines a testimonial_item block type. Each block has its own settings for image, author, and quote. The max_blocks setting is crucial here, preventing the merchant from adding an excessive number of blocks that might break the layout or editor performance. This separation is clean, efficient, and intuitive for anyone managing the store.

Code in Practice: Building a Flexible Feature Section

Let's apply this to another common scenario: a 'Features' section where you want to highlight several key benefits of your product or service. Each feature will have an icon, a title, and a short description. This is a perfect candidate for a section with blocks.

First, the Liquid code for how the section renders the blocks:

<!-- sections/feature-highlight.liquid -->

<section class="feature-highlight-section">
  <div class="container">
    {% if section.settings.heading != blank %}
      <h2 class="section-heading">{{ section.settings.heading }}</h2>
    {% endif %}
    {% if section.settings.subheading != blank %}
      <p class="section-subheading">{{ section.settings.subheading }}</p>
    {% endif %}
    <div class="features-grid">
      {% for block in section.blocks %}
        <div class="feature-item">
          {% if block.settings.icon_name != blank %}
            <span class="icon {{ block.settings.icon_name }}"></span> {# Assuming you have a CSS icon library #}
          {% endif %}
          {% if block.settings.title != blank %}
            <h3>{{ block.settings.title }}</h3>
          {% endif %}
          {% if block.settings.description != blank %}
            <p>{{ block.settings.description }}</p>
          {% endif %}
          {% if block.settings.link_label != blank and block.settings.link_url != blank %}
            <a href="{{ block.settings.link_url }}" class="feature-link">{{ block.settings.link_label }}</a>
          {% endif %}
        </div>
      {% endfor %}
    </div>
  </div>
</section>

Next, the schema that defines the section's overall settings and the structure of each feature_item block. This is where you empower the merchant.

{% schema %}
  {
    "name": "Feature Highlight",
    "settings": [
      {
        "type": "text",
        "id": "heading",
        "label": "Section Heading",
        "default": "Key Features"
      },
      {
        "type": "textarea",
        "id": "subheading",
        "label": "Section Subheading"
      }
    ],
    "blocks": [
      {
        "type": "feature_item",
        "name": "Feature Item",
        "settings": [
          {
            "type": "text",
            "id": "icon_name",
            "label": "Icon Class (e.g., icon-star)",
            "info": "Use a CSS class name for your icon library"
          },
          {
            "type": "text",
            "id": "title",
            "label": "Feature Title",
            "default": "Feature Title"
          },
          {
            "type": "richtext",
            "id": "description",
            "label": "Description",
            "default": "<p>Briefly describe this amazing feature.</p>"
          },
          {
            "type": "text",
            "id": "link_label",
            "label": "Link Label"
          },
          {
            "type": "url",
            "id": "link_url",
            "label": "Link URL"
          }
        ]
      }
    ],
    "presets": [
      {
        "name": "Feature Highlight",
        "blocks": [
          {
            "type": "feature_item"
          },
          {
            "type": "feature_item"
          },
          {
            "type": "feature_item"
          }
        ]
      }
    ]
  }
{% endschema %}

This architecture ensures that the merchant can easily add a new feature, reorder existing ones, or update content for any single feature without touching other parts of the section or creating redundant sections. It’s clean, efficient, and scales perfectly as their business evolves.

Performance and Maintainability: The Real Cost of Misuse

Implementing repeatable content with individual sections might seem harmless at first, but it quickly leads to serious issues. I've seen merchants struggle with themes that become virtually unmanageable because of this basic architectural flaw. The impact is felt in two critical areas:

Theme Editor Performance

Every time you load the Shopify theme editor, it has to process and render the settings for every single section on the page. If you've got 20 "testimonial" sections instead of one "testimonials" section with 20 blocks, the editor becomes sluggish. Imagine trying to drag and drop sections when there are hundreds of them on a single page. It's a frustrating, time-consuming experience that directly impacts a merchant's productivity and their perception of their store's usability. This isn't just about aesthetics; it's about real business efficiency.

Long-Term Maintainability

From a developer's perspective, a theme built with misused sections is a nightmare to maintain. If you need to update the styling or add a new setting to your "testimonial" component, you have to modify 20 different section files or risk inconsistent implementations. With blocks, you modify one section file and one block definition, and the changes propagate to all instances. This drastically reduces development time, prevents bugs, and makes future updates significantly easier. It’s why I always prioritize solid theme architecture in my Shopify theme development services and for products like Verso Theme.

When I audit themes, this is one of the first things I look for. It's a tell-tale sign of hurried development or a lack of understanding of Shopify's powerful architecture. A well-structured theme isn't just a nicety; it's a strategic asset for any e-commerce business.

Avoiding the Pitfalls: Best Practices for Shopify Theme Architecture

To ensure you're building robust, future-proof Shopify themes, adopt these principles:

  1. Component Thinking: Break down your designs into truly reusable components. Ask yourself: "Does this content element repeat?" If yes, it's a block. If it defines a unique layout area, it's a section.
  2. Schema First: Before writing a single line of Liquid for rendering, plan your {% schema %}. Define your section settings and block settings. This forces you to think about the merchant's experience and how they'll interact with the content.
  3. Prioritize Merchant Experience (MX): Always put yourself in the merchant's shoes. Will they easily understand how to update this content? Will the editor be responsive? A technically elegant solution that's a pain to use is a bad solution.
  4. Embrace min_blocks and max_blocks: Use these settings in your section schema to provide guardrails. You can ensure a minimum number of elements are present (e.g., at least 3 features) or prevent an overwhelming number of blocks that could hurt performance or layout.
  5. Small and Focused: Keep your sections and blocks focused on a single responsibility. Don't try to cram too many disparate functionalities or settings into one component.

By following these practices, you'll build themes that are not only performant and maintainable but also genuinely enjoyable for your clients to use. This elevates the entire store management experience and ultimately contributes to their success.

If your Shopify theme editor feels like a maze or you're constantly fighting with your content, it’s time for a change. Let's talk about how to optimize your store's architecture for long-term success. I offer free 30-minute consultation calls to diagnose common issues and chart a path forward for your Shopify store.

A

About the author

Ashraful

Shopify Select Partner, Top Rated Plus on Upwork. 700+ Shopify projects shipped over 7+ years — themes, apps, migrations, speed, Hydrogen. Solo shop, no agency middlemen.

Read the full story

Working on a Shopify project?

That's what I do every day. Pick whichever feels lower-friction.