---
title: Twig blocks | Shopware Community Hub
description: >-
  Understand how Twig blocks work in Shopware and learn to identify the right
  block to override or extend while keeping the original content.
canonical_url: 'https://hub.shopware.com/learn/unit/twig-blocks'
---

# Twig blocks

<LearningObjectives>

- Get an overview of the block structure in Shopware.
- Find the right block to override.
- Extend or include templates.

</LearningObjectives>

# Twig blocks

Twig blocks are sections of a template that can be overridden or extended. This unit shows how to **find** the right block and extend it without losing core markup.

Use the [AcademyFrontendEssentials](https://github.com/ShopwareAcademy/AcademyFrontendEssentials) plugin from the previous unit, or clone it:

```shell
git clone https://github.com/ShopwareAcademy/AcademyFrontendEssentials.git custom/plugins/AcademyFrontendEssentials
bin/console plugin:install AcademyFrontendEssentials --activate --clearCache
```

## Finding Your Block

In Shopware 6, templates are organized via blocks. Blocks are sections of a template that can be overridden or extended by other templates. When you want to customize the appearance of your Shopware shop, you need to find the right block to override.

### Search for a CSS Class or ID

One practical way to find the right block is to start in the browser. Open the page you want to change, inspect the element with DevTools, and look for a nearby CSS class or ID.

After that, search for this class or ID in the storefront template files. In a local Shopware project, these templates are usually located under `vendor/shopware/storefront/Resources/views`. This helps you find the template and block that render the HTML you saw in the browser.

The workflow is:

1. Open the page in the browser and inspect the element with DevTools.
2. Note a nearby CSS class or ID.
3. Search for that class or ID in the storefront template files.
4. Confirm that the template and block you found actually render the page you want to change.

<Callout title="Validate Correct Block" type="warning">

Blocks can appear in multiple templates. Confirm you are editing the template that renders on your page.

</Callout>

<Callout title="Use Custom Class Names" type="info">

It's a good practice to add **custom class names** in your own templates. This way it makes it easier for you to verify your changes, avoids conflicts with other plugins, themes or the core, and helps you find the right block more easily during development. Adding custom styles with SCSS also becomes much simpler since you can target your unique class names.

</Callout>

### Optional: FroshDevelopmentHelper

The [FroshDevelopmentHelper](https://github.com/FriendsOfShopware/FroshDevelopmentHelper) plugin adds HTML comments that name Twig blocks in page source—useful when DevTools search is slow.

![Find block](assets/images/block-finder.jpg)

<Callout title="Use Only in Development Environments" type="warning">

FroshDevelopmentHelper is a development helper. Use it only in local development, test, or staging environments where you intentionally inspect templates and debugging output.

Do not install or activate this plugin in production. It can expose internal template information in the rendered HTML and is not meant for customer-facing storefronts.

</Callout>

If you want to use it in your local project, you can install it via the Shopware Store or require it via Composer in your development setup.

```shell
composer require frosh/development-helper --dev
bin/console plugin:refresh
bin/console plugin:install FroshDevelopmentHelper --activate --clearCache
```

The `--dev` flag keeps the package in your development dependencies. This matches the plugin's purpose as a debugging and template-inspection tool instead of a production dependency.

## Extend or Include Storefront Templates

In Shopware 6, you can extend or include templates from other templates using the `sw_extends` and `sw_include` tags. This is useful when you want to reuse parts of a template or extend a template with additional content.

### The `sw_extends` Tag

The `sw_extends` tag is used to extend a template with additional content. It is similar to the `extends` tag in Twig, but it is specific to Shopware templates.

Here is an example of how to use the `sw_extends` tag:

```twig
{% sw_extends '@Storefront/storefront/element/cms-element-product-name.html.twig' %}
```

In this example, we extend the `cms-element-product-name.html.twig` template from the product detail page in the Storefront theme.

Let's check out the git tag to see how it works.

```shell
git checkout LU-02-twig-blocks
```

As you see in the sw_extends tag, we need to create a file in the following path:

```txt
└── AcademyFrontendEssentials
    ├── src
    │   │── Resources
    │   │   └── views
    │   │       └── storefront
    │   │           └── element
    │   │               └── cms-element-product-name.html.twig
    │   └── AcademyFrontendEssentials.php
    └── composer.json
```

This file should contain the following content:

```twig
{% sw_extends '@Storefront/storefront/element/cms-element-product-name.html.twig' %}

{% block element_product_name_inner %}
  <h2>Is an awesome product! &#127881;</h2>
{% endblock %}
```

After reloading your Storefront, the product name will be replaced with your custom text:

![Overwrite template](assets/images/product-detail-block-overwrite.jpg)

This completely **overrides** the product name block. But what if you want to keep the original content and add your own content? Let's see how to do that.

## Parent and Child Blocks

Templates can have parent and child blocks. When you override a block in a template, you can call the parent block to include the original content. This allows you to customize the appearance of the block without having to rewrite the entire block.

If we apply the `parent()` function in the block, we can include the original content of the block, in our case the product name.

```twig
{% sw_extends '@Storefront/storefront/element/cms-element-product-name.html.twig' %}

{% block element_product_name_inner %}
  {{ parent() }}

  <h2>Is an awesome product! &#127881;</h2>
{% endblock %}
```

After reloading your storefront, the original product name is still shown, followed by your custom text:

![Extend template with parent](assets/images/product-detail-block.jpg)

This way, you **extend** the block instead of fully replacing it.

### The `sw_include` Tag

The `sw_include` tag is used to render one template inside another template. It is similar to Twig's regular `include` tag, but it uses Shopware's template loading behavior.

<Callout title="Note" type="info">

Use `sw_include` when you want to move reusable markup into a separate template file and render it from another template. This helps you keep templates maintainable because you do not need to copy the same markup into multiple places.

</Callout>

Here is an example of how to use the `sw_include` tag:

```twig
{% sw_include '@Storefront/storefront/frontend-essentials/color.html.twig' %}
```

This includes the `color.html.twig` template from the `frontend-essentials` directory exactly where the `sw_include` tag is placed.

In our example, we use this inside the product detail page tabs. The tab markup is only the surrounding example. The important part for this section is that the separate `color.html.twig` template is rendered inside the custom tab content.

Think of a tab as two connected parts:

- A tab navigation item that users can click.
- A tab content panel that becomes visible when that item is active.

Both parts need to reference each other with matching ids. The navigation item points to the content panel, and the content panel points back to the navigation item.

Check out the git tag to see the complete example:

```shell
git checkout LU-02-twig-blocks-swinclude
```

The folder structure looks like this now:

```txt
└── AcademyFrontendEssentials
    ├── src
    │   │── Resources
    │   │   └── views
    │   │       └── storefront
    │   │           ├── element
    │   │           │    ├── cms-element-product-name.html.twig
    │   │           │    └── cms-element-product-description-reviews.html.twig // <-- This file is created
    │   │           └── frontend-essentials // <-- This directory is created for custom templates
    │   │               └── color.html.twig // <-- This file is created
    │   └── AcademyFrontendEssentials.php
    └── composer.json
```

And the content of the `cms-element-product-description-reviews.html.twig` file:

```twig
{% sw_extends '@Storefront/storefront/element/cms-element-product-description-reviews.html.twig' %}

{% block element_product_description_reviews_tabs_navigation_review %}
    {{ parent() }}

    {% block frontend_essentials_custom_tabs_navigation %}
        <li class="nav-item">
            <a class="nav-link"
               id="custom-review-tab"
               data-bs-toggle="tab"
               href="#custom-review-content"
               role="tab"
               aria-controls="custom-review-content"
               aria-selected="false"
            >
                Colorful div tab
            </a>
        </li>
    {% endblock %}
{% endblock %}

{% block element_product_description_reviews_tabs_content %}
    {{ parent() }}

    {% block frontend_essentials_custom_tabs_content %}
        <div class="tab-pane fade"
             id="custom-review-content"
             role="tabpanel"
             aria-labelledby="custom-review-tab"
        >
            {% sw_include '@Storefront/storefront/frontend-essentials/color.html.twig' %} {# <-- Include template #}
        </div>
    {% endblock %}
{% endblock %}
```

**Explanation**

The first block, `element_product_description_reviews_tabs_navigation_review`, extends the original tab navigation. The `parent()` call keeps the existing review tab, and the custom `<li>` adds one more tab next to it.

The second block, `element_product_description_reviews_tabs_content`, extends the tab content area. Again, `parent()` keeps the existing content, and the custom `<div>` adds the matching content panel for the new tab.

The tab link and the content panel are connected through matching ids:

- The link uses `href="#custom-review-content"`.
- The content panel uses `id="custom-review-content"`.

This is how Bootstrap knows which content panel should become visible when the tab is clicked. The `aria-controls` and `aria-labelledby` attributes describe the same connection for accessibility.

Inside the custom content panel, `sw_include` renders the separate `color.html.twig` template. In other words: the tab markup creates the place where the content should appear, and `sw_include` fills that place with the reusable template.

And our `color.html.twig` file looks like this:

```twig
{% block frontend_essentials_show_colors %}
  <div style="background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet); padding: 20px; text-align: center; color: white; font-size: 24px; border-radius: 10px;">
    <p>Colorful div</p>
  </div>
{% endblock %}
```

Now let's compare the result.

Before the customizations:

![Before customizations](assets/images/pdp-no-custom-tab.jpg)

After adding the custom tab in the product detail page:

![After customizations](assets/images/pdp-custom-tab-with-content.jpg)

## Template Inheritance Order

Often you will have plugins or apps overriding the same block. By default, the last installed plugin will have the highest priority.

However, you can set the order of the view coming first in a theme. This is done in the `views` section of the `theme.json` file.

```json
{
  "views": [
    "@Storefront",
    "@Plugins",
    "@MyTheme" // <-- Highest priority
  ]
}
```

This setup ensures that `@MyTheme` has the highest priority and overrides all views listed above.

A practical example with code will follow in a later in another learning course.

If you want to dive deeper in theme inheritance, check out the official [Shopware documentation](https://developer.shopware.com/docs/guides/plugins/themes/add-theme-inheritance.html#views-section).

<ArticleQuestionnaire>
  <ArticleQuestionnaireQuestion>How do you keep original block content when adding your own markup?</ArticleQuestionnaireQuestion>
  <ArticleQuestionnaireAnswer>Delete the block entirely</ArticleQuestionnaireAnswer>
  <ArticleQuestionnaireAnswer correct>Call <code v-pre>{{ parent() }}</code> inside the overridden block</ArticleQuestionnaireAnswer>
  <ArticleQuestionnaireAnswer>Use sw_include instead of sw_extends</ArticleQuestionnaireAnswer>
</ArticleQuestionnaire>

## Summary

In this learning unit, you learned how to:

- Inspect and locate the right Twig block to override.
- Extend templates with **`sw_extends`**.
- Reuse templates with **`sw_include`**.
- Keep the original content of a block with **`parent()`**.
- Understand the inheritance order in Shopware themes and plugins.

With these skills, you can customize specific parts of the Storefront while keeping your templates clean and maintainable.
