Die Shopware 6 Storefront basiert auf Bootstrap 5 und Twig. Themes werden als spezielle Plugins entwickelt und nutzen ein elegantes Override-System: Statt Dateien zu kopieren und zu modifizieren, überschreibt man nur gezielt die Teile, die sich ändern sollen.
Theme-Grundstruktur
Ein Theme ist ein spezielles Plugin mit einer theme.json und dem Theme-Trait:
MyTheme/
├── composer.json
├── src/
│ ├── MyTheme.php # Plugin-Klasse mit ThemeInterface
│ └── Resources/
│ └── theme.json # Theme-Konfiguration
│ └── app/
│ └── storefront/
│ ├── src/
│ │ ├── scss/
│ │ │ └── base.scss # SCSS-Einstiegspunkt
│ │ └── js/
│ │ └── my-theme.js # JS-Einstiegspunkt
│ └── views/
│ └── storefront/ # Twig-Overrides
Plugin-Klasse
<?php
declare(strict_types=1);
namespace MyTheme;
use Shopware\Core\Framework\Plugin;
use Shopware\Storefront\Framework\ThemeInterface;
class MyTheme extends Plugin implements ThemeInterface
{
}
theme.json
{
"name": "MyTheme",
"author": "Wunner Software",
"description": {
"en-GB": "A custom Shopware 6 theme",
"de-DE": "Ein Shopware 6 Custom Theme"
},
"views": ["@Storefront", "@Plugins", "@MyTheme"],
"style": ["@Storefront", "app/storefront/src/scss/base.scss"],
"script": ["@Storefront", "app/storefront/src/js/my-theme.js"],
"asset": ["app/storefront/src/assets"],
"config": {
"blocks": {
"colors": {
"label": {
"en-GB": "Colors",
"de-DE": "Farben"
},
"fields": {
"sw-color-brand-primary": {
"label": {
"en-GB": "Primary color",
"de-DE": "Primärfarbe"
},
"type": "color",
"value": "#1a365d",
"editable": true
}
}
}
}
}
}
SCSS-Anpassung
Shopware Storefront nutzt Bootstrap 5. Der sauberste Weg, Styles anzupassen, ist das Überschreiben von SCSS-Variablen, bevor Bootstrap geladen wird.
base.scss — Variable überschreiben
// Eigene Variablen VOR dem Storefront-Import
$primary: #1a365d;
$secondary: #3182ce;
$font-family-base: 'Inter', system-ui, sans-serif;
$border-radius: 0.375rem;
// Shopware SCSS-Variablen überschreiben
$sw-color-brand-primary: $primary;
$sw-color-brand-secondary: $secondary;
// Eigene Styles — die Storefront-Basis wird über theme.json eingebunden (siehe unten)
.my-custom-component {
background: $primary;
color: white;
padding: 1rem;
border-radius: $border-radius;
}
Eigene SCSS-Partials organisieren
// base.scss — Storefront-Basis wird über theme.json gesteuert, nicht per @import
@import "variables";
@import "components/header";
@import "components/product-card";
@import "components/checkout";
@import "pages/product-detail";
@import "pages/listing";
Twig-Override-System
Shopware verwendet ein Twig-Namespace-System. @Storefront verweist auf die Original-Storefront-Templates. Um ein Template zu überschreiben, erstellt man eine Datei an der gleichen Position im eigenen Theme.
Ein Template vollständig ersetzen
Um /vendor/shopware/storefront/Resources/views/storefront/component/product/card/box.html.twig zu überschreiben:
MyTheme/src/Resources/views/storefront/component/product/card/box.html.twig
Einen einzelnen Block überschreiben (saubererer Ansatz)
{# Datei: views/storefront/component/product/card/box.html.twig #}
{% sw_extends '@Storefront/storefront/component/product/card/box.html.twig' %}
{% block component_product_box_image %}
<div class="my-custom-image-wrapper">
{{ parent() }}
<span class="badge badge-custom">NEU</span>
</div>
{% endblock %}
sw_extends ist der Shopware-spezifische Extend-Tag, der das Theme-Vererbungssystem berücksichtigt. parent() rendert den Original-Block-Inhalt.
Template-Hierarchie verstehen
Wenn in theme.json "views": ["@Storefront", "@Plugins", "@MyTheme"] steht, wird beim Rendern in dieser Reihenfolge nach dem Template gesucht. Das eigene Theme hat die höchste Priorität.
Storefront-JavaScript
Shopware nutzt ein eigenes Plugin-System für JavaScript (nicht zu verwechseln mit PHP-Plugins). Jede interaktive Komponente wird als Storefront-JS-Plugin registriert.
// my-plugin.js
import Plugin from 'src/plugin-system/plugin.class';
export default class MyPlugin extends Plugin {
static options = {
animationDuration: 300,
};
init() {
this._registerEvents();
}
_registerEvents() {
this.el.addEventListener('click', this._onClick.bind(this));
}
_onClick(event) {
event.preventDefault();
this.el.classList.toggle('active');
}
}
Plugin registrieren:
// my-theme.js
import MyPlugin from './my-plugin';
const PluginManager = window.PluginManager;
PluginManager.register('MyPlugin', MyPlugin, '[data-my-plugin]');
Im Twig-Template das Data-Attribut setzen:
<div data-my-plugin="true">
<!-- Inhalt -->
</div>
Theme kompilieren und aktivieren
# Theme installieren
php bin/console plugin:install --activate MyTheme
# Theme kompilieren (SCSS + JS)
php bin/console theme:compile
# Theme einem Sales Channel zuweisen (im Admin-Bereich oder per CLI)
php bin/console theme:change --all MyTheme
Im Entwicklungsmodus mit Watcher:
# Watch-Modus für SCSS und JS — vom Projekt-Root aus starten
composer run watch:storefront
# oder bei Production-Template:
./bin/watch-storefront.sh
Häufige Fallstricke
1. Cache nicht geleert: Nach Template-Änderungen immer bin/console cache:clear ausführen.
2. sw_extends statt extends: In Shopware muss sw_extends verwendet werden, damit das Theme-Override-System korrekt funktioniert.
3. Bootstrap-Version: Shopware 6.5+ nutzt Bootstrap 5, ältere Versionen (6.4 und früher) Bootstrap 4. Variable-Namen unterscheiden sich (z.B. $primary vs. $theme-primary).
4. Asset-Cache: Geänderte Assets (Bilder, Fonts) mit bin/console asset:install und Varnish/Browser-Cache leeren.
Fazit
Shopware Themes sind gut strukturiert und bieten mit dem Block-Override-System eine elegante Möglichkeit, nur die notwendigen Teile anzupassen. Das Twig-Vererbungssystem mit sw_extends und parent() ermöglicht saubere, wartbare Anpassungen ohne Copy-Paste von kompletten Templates.
Kommentare
Kommentare werden von Remark42 bereitgestellt. Beim Laden werden Daten an unseren Kommentar-Server übertragen.