Skip to content

Alles für WordPress, Webentwicklung — und mehr

🔧 Wie man ein WordPress-Theme WooCommerce-fähig macht: eine vollständige Anleitung für Entwickler

🔧 Wie man ein WordPress-Theme WooCommerce-fähig macht: eine vollständige Anleitung für Entwickler

Eigenes Theme im Aufbau und Sie möchten einen Shop integrieren? Technisch funktioniert WooCommerce mit jedem Theme, da es sich lediglich um ein Plugin handelt. Aber „funktionieren" heißt nicht „richtig aussehen": Das Produktraster zerbricht, Seitenleisten verrutschen und die Standardstile kollidieren mit Ihren eigenen.

Das Problem geht tiefer als ein paar CSS-Regeln. Seit WooCommerce 3.3 erhält ein Theme ohne deklarierte Unterstützung eine vereinfachte Darstellung über Shortcodes und eine Warnung im Admin-Bereich. Sie verlieren die volle Kontrolle über das Layout.

Nachfolgend finden Sie einsatzbereite Code-Snippets, die alles abdecken, von der Deklaration der Unterstützung bis hin zu einem Live-Warenkorb im Menü. Jedes Snippet wurde mit der aktuellen WooCommerce-Version getestet und ist nach Abschnitten gegliedert, von den Grundlagen bis zur Feinabstimmung.

💡 Kurzer Überblick:

  • Zuerst muss das Theme die WooCommerce-Unterstützung ausdrücklich deklarieren; ohne dies werden Template-Overrides und einige Funktionen nicht aktiviert
  • Platzieren Sie den Code in einer separaten Datei (zum Beispiel inc/woocommerce.php), die nur geladen wird, wenn das Plugin aktiv ist
  • Für die Einrichtung des Shop-Rasters sind zwei Filter erforderlich: einer ändert die Spaltenanzahl, der andere fügt dem body eine Klasse hinzu
  • Produktgalerie, Zoom, Lightbox und Slider werden durch separate add_theme_support-Aufrufe aktiviert
  • Der Warenkorb im Menü muss per AJAX aktualisiert werden; nutzen Sie dafür den add_to_cart_fragments-Filter

1. Grundlage: Unterstützung deklarieren und prüfen, ob das Plugin aktiv ist

Zuallererst muss das Theme WooCommerce ausdrücklich mitteilen: „Ich unterstütze dich." Ohne dies aktiviert das Plugin keine Template-Overrides und zeigt eine Warnung im Admin-Bereich an. Seit WooCommerce 3.3 erhält ein Theme ohne deklarierte Unterstützung eine vereinfachte Darstellung über Shortcodes. Das funktioniert, schränkt aber Ihre Kontrolle über das Layout ein.

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Es ist wichtig, den after_setup_theme-Hook anstelle von init zu verwenden, wie von der WooCommerce-Dokumentation empfohlen. Seit Version 3.3+ können Sie Rastereinstellungen direkt übergeben:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce', array(
3 'thumbnail_image_width' => 150,
4 'single_image_width' => 300,
5 'product_grid' => array(
6 'default_rows' => 3,
7 'min_rows' => 2,
8 'max_rows' => 8,
9 'default_columns' => 4,
10 'min_columns' => 2,
11 'max_columns' => 5,
12 ),
13 ) );
14} );

Diese Parameter setzen Standardwerte für den Customizer (WooCommerce → Produktbilder / Produktkatalog) und ersparen den Nutzern die manuelle Konfiguration des Rasters.

Prüfen, ob das Plugin aktiv ist

Wenn Sie ein Theme vertreiben, können Sie WooCommerce-Snippets nicht einfach ans Ende der functions.php hängen, denn sie verursachen einen fatalen Fehler, falls das Plugin nicht aktiv ist. Der Code sollte nur geladen werden, wenn WooCommerce läuft:

1define( 'MYTHEME_WOOCOMMERCE_ACTIVE', class_exists( 'WooCommerce' ) );
2
3if ( MYTHEME_WOOCOMMERCE_ACTIVE ) {
4 require_once get_template_directory() . '/inc/woocommerce.php';
5}

Die Konstante wird einmal ausgewertet, und anschließend können Sie überall in Ihrem Theme Aufrufe mit if ( MYTHEME_WOOCOMMERCE_ACTIVE ) klammern. Das ist sauberer, als jedes Mal class_exists oder is_plugin_active aufzurufen.

2. Umgang mit WooCommerce-Stilen

WooCommerce liefert drei CSS-Dateien mit: woocommerce-general, woocommerce-layout und woocommerce-smallscreen. Idealerweise entfernen Sie diese nicht, sondern überschreiben sie in Ihrem Theme. So bleiben Drittanbieter-Erweiterungen für WooCommerce, die auf diese Klassen angewiesen sind, funktionsfähig. Wenn Sie jedoch alles von Grund auf neu schreiben und volle Kontrolle wünschen, erfahren Sie hier, wie Sie sie entfernen.

Alle Stile auf einmal entfernen:

1add_filter( 'woocommerce_enqueue_styles', '__return_empty_array' );

Oder selektiv entfernen:

1function mytheme_remove_woo_styles( $styles ) {
2 unset( $styles['woocommerce-general'] );
3 unset( $styles['woocommerce-layout'] );
4 unset( $styles['woocommerce-smallscreen'] );
5 return $styles;
6}
7add_filter( 'woocommerce_enqueue_styles', 'mytheme_remove_woo_styles' );

In der Praxis ist die zweite Variante üblicher: Sie entfernen woocommerce-layout (das prozentbasierte Raster), behalten aber woocommerce-general (Buttons, Hinweise, Formulare) und überschreiben diese selektiv mit Ihrem eigenen CSS unter Verwendung höherer Spezifität.

3. Shop-Seiten konfigurieren

Wie viele Produkte angezeigt werden sollen

Der Filter loop_shop_per_page steuert die Anzahl der Produkte auf der Shop-Seite und in Archiven (Kategorien, Schlagwörter):

1function mytheme_woo_posts_per_page( $cols ) {
2 return 12;
3}
4add_filter( 'loop_shop_per_page', 'mytheme_woo_posts_per_page' );

Anzahl der Spalten im Raster

Hier sind zwei Filter erforderlich. loop_shop_columns allein genügt nicht: Anders als WooCommerce-Shortcodes (die einen Wrapper mit einer columns-N-Klasse besitzen) verfügen Shop-Seiten nicht über diese Klasse. Daher fügen wir sie dem body hinzu:

1function mytheme_woo_shop_columns( $columns ) {
2 return 4;
3}
4add_filter( 'loop_shop_columns', 'mytheme_woo_shop_columns' );
5
6function mytheme_woo_shop_columns_body_class( $classes ) {
7 if ( is_shop() || is_product_category() || is_product_tag() ) {
8 $classes[] = 'columns-4';
9 }
10 return $classes;
11}
12add_filter( 'body_class', 'mytheme_woo_shop_columns_body_class' );

Im CSS können Sie nun Selektoren wie .columns-4 ul.products li.product schreiben, die spezifisch auf das Shop-Raster wirken.

Shop-Titel

WooCommerce zeigt auf der Shop-Seite standardmäßig „Shop" als Titel an. Sofern Ihr Theme bereits Archivtitel verarbeitet, stört diese Dopplung:

1add_filter( 'woocommerce_show_page_title', '__return_false' );

Wenn Sie the_archive_title() nutzen, können Sie den Titel durch den Namen der Shop-Seite ersetzen (festgelegt im Admin-Bereich):

1function mytheme_woo_archive_title( $title ) {
2 if ( is_shop() && $shop_id = wc_get_page_id( 'shop' ) ) {
3 $title = get_the_title( $shop_id );
4 }
5 return $title;
6}
7add_filter( 'get_the_archive_title', 'mytheme_woo_archive_title' );

4. Produktgalerie: Zoom, Lightbox und Slider

Ab WooCommerce 3.0 wurde eine neue Produktgalerie auf Basis von FlexSlider, PhotoSwipe und jQuery Zoom eingeführt. In den Versionen 3.0 bis 3.2 ist sie standardmäßig deaktiviert und erfordert eine explizite Aktivierung. Ab Version 3.3 ist die Galerie für Nicht-WooCommerce-Themes aktiviert und für Themes deaktiviert, die Unterstützung deklarieren; Sie aktivieren die benötigten Komponenten selbst:

1add_theme_support( 'wc-product-gallery-slider' );
2add_theme_support( 'wc-product-gallery-zoom' );
3add_theme_support( 'wc-product-gallery-lightbox' );

Sie können nur einzelne Funktionen aktivieren: etwa Slider und Zoom, die Lightbox jedoch durch Ihre eigene Fancybox-Lösung ersetzen. Jede Direktive lädt ihre eigenen Skripte, aktivieren Sie also nicht, was Sie nicht benötigen.

Spaltenanzahl für Galerie-Thumbnails (unterhalb des Hauptprodukt-Bildes):

1function mytheme_woo_product_thumbnails_columns() {
2 return 4;
3}
4add_action( 'woocommerce_product_thumbnails_columns', 'mytheme_woo_product_thumbnails_columns' );

5. Ähnliche Produkte und Cross-Sells/Up-Sells

Auf der Produktseite zeigt WooCommerce die Blöcke „Ähnliche Produkte" und „Das könnte Ihnen auch gefallen" (Up-Sells) an. Deren Anzahl und Raster werden separat konfiguriert.

Wie viele ähnliche Produkte angezeigt werden sollen:

1function mytheme_woo_related_posts_per_page( $args ) {
2 $args['posts_per_page'] = 4;
3 return $args;
4}
5add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_posts_per_page' );

Spalten für Up-Sells und ähnliche Produkte (gleiches Vorgehen wie beim Shop-Raster): Wir ändern sowohl die Spaltenanzahl als auch die Klasse am body:

1function mytheme_woo_single_loops_columns( $columns ) {
2 return 4;
3}
4add_filter( 'woocommerce_up_sells_columns', 'mytheme_woo_single_loops_columns' );
5
6function mytheme_woo_related_columns( $args ) {
7 $args['columns'] = 4;
8 return $args;
9}
10add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_columns', 10 );
11
12function mytheme_woo_single_loops_columns_body_class( $classes ) {
13 if ( is_singular( 'product' ) ) {
14 $classes[] = 'columns-4';
15 }
16 return $classes;
17}
18add_filter( 'body_class', 'mytheme_woo_single_loops_columns_body_class' );

Beachten Sie, dass woocommerce_output_related_products_args zwei Filter mit unterschiedlichen Prioritäten besitzt: mytheme_woo_related_posts_per_page (Standard 10) ändert posts_per_page, und mytheme_woo_related_columns (Priorität 10) ändert columns. Sie stehen nicht in Konflikt, da sie mit unterschiedlichen Schlüsseln im selben $args-Array arbeiten.

6. Paginierung und Sale-Badge

Sie können die Pfeile der Paginierung durch die Icons Ihres Themes ersetzen:

1function mytheme_woo_pagination_args( $args ) {
2 $args['prev_text'] = '<i class="fa fa-angle-left"></i>';
3 $args['next_text'] = '<i class="fa fa-angle-right"></i>';
4 return $args;
5}
6add_filter( 'woocommerce_pagination_args', 'mytheme_woo_pagination_args' );

Ersetzen Sie die Font-Awesome-Klassen durch Ihre eigenen Icon-Klassen oder direkte SVGs.

Der Text auf dem Sale-Badge (Sale!) lässt sich einfach überschreiben. Das ist nützlich für Websites in anderen Sprachen oder einfach, um das Ausrufezeichen zu entfernen:

1function mytheme_woo_sale_flash() {
2 return '<span class="onsale">' . esc_html__( 'Sale', 'woocommerce' ) . '</span>';
3}
4add_filter( 'woocommerce_sale_flash', 'mytheme_woo_sale_flash' );

Für andere Sprachen ersetzen Sie 'Sale' durch Ihre Übersetzung. Die Übersetzung wird automatisch übernommen, wenn Sie WooCommerce-MO-Dateien für diese Sprache haben.

7. Dynamischer Warenkorb im Menü

Dies ist vermutlich das am häufigsten angefragte Element in jedem Shop-Theme: ein Warenkorb-Icon in der Navigation mit der aktuellen Summe. Die Implementierung besteht aus drei Teilen: das Element zum Menü hinzufügen, das Warenkorb-HTML generieren und das AJAX-Update.

1// Adding the link to the menu
2function mytheme_add_menu_cart_item( $items, $args ) {
3 if ( $args->theme_location === 'primary' ) {
4 $css_class = 'menu-item menu-item-type-cart menu-item-type-woocommerce-cart';
5 if ( is_cart() ) {
6 $css_class .= ' current-menu-item';
7 }
8 $items .= '<li class="' . esc_attr( $css_class ) . '">';
9 $items .= mytheme_menu_cart_item();
10 $items .= '</li>';
11 }
12 return $items;
13}
14add_filter( 'wp_nav_menu_items', 'mytheme_add_menu_cart_item', 10, 2 );
15
16// Cart HTML
17function mytheme_menu_cart_item() {
18 $cart_count = WC()->cart->cart_contents_count;
19 $css_class = 'wpex-menu-cart-total wpex-cart-total-' . intval( $cart_count );
20 $url = $cart_count ? WC()->cart->get_cart_url() : wc_get_page_permalink( 'shop' );
21 $html = WC()->cart->get_cart_total();
22 $html = str_replace( 'amount', '', $html );
23
24 return '<a href="' . esc_url( $url ) . '" class="' . esc_attr( $css_class ) . '">'
25 . '<span class="cart-icon"></span>'
26 . wp_kses_post( $html )
27 . '</a>';
28}
29
30// AJAX fragment update
31function mytheme_menu_cart_link_fragments( $fragments ) {
32 $fragments['.wpex-menu-cart-total'] = mytheme_menu_cart_item();
33 return $fragments;
34}
35add_filter( 'add_to_cart_fragments', 'mytheme_menu_cart_link_fragments' );

Kritischer Punkt: **Umschließen Sie diese Funktionen nicht mit **is_admin(). Warenkorb-AJAX-Anfragen kommen über admin-ajax.php, und wenn die Funktion im Admin-Kontext nicht verfügbar ist, funktioniert die Preisaktualisierung im Menü schlichtweg nicht. Ersetzen Sie theme_location durch Ihre Menü-Kennung (im Beispiel primary).

8. Alternativer Ansatz: das woocommerce.php-Template

Die oben beschriebenen Hooks sind die flexibelste und update-sicherste Methode. Wenn Sie jedoch den gesamten Shop- und Produktseiten-Wrapper grundlegend überarbeiten müssen, gibt es einen Weg über ein separates Template.

Erstellen Sie eine woocommerce.php-Datei im Root-Verzeichnis Ihres Themes (eine Kopie von page.php) und ersetzen Sie den Haupt-Loop durch einen Aufruf von woocommerce_content():

1<?php
2get_header(); ?>
3
4<div id="primary" class="content-area">
5 <main id="main" class="site-main">
6 <?php woocommerce_content(); ?>
7 </main>
8</div>
9
10<?php get_footer();
11

Diese Methode ist einfacher, hat aber ihren Preis: ein Template für alle WooCommerce-Seiten (Shop, Kategorien und Produktdetail). Feintuning (unterschiedliche Raster, unterschiedliche Seitenleisten auf verschiedenen Seiten) wird dadurch schwieriger. Wählen Sie diesen Ansatz nur, wenn Ihr aktuelles Theme auf Markup-Ebene wirklich nicht mit WooCommerce harmoniert und Sie bereit sind, die Einschränkungen in Kauf zu nehmen.

⁉️🤔 Häufig gestellte Fragen

Ist es zwingend erforderlich, die Standard-Styles von WooCommerce zu entfernen?

Nicht zwingend. Ein sichererer Ansatz ist, sie zu behalten und die Selektoren in Ihrem Theme mit höherer Spezifität zu überschreiben. Das erhält die Kompatibilität mit Erweiterungen, die auf standardmäßige WooCommerce-Klassen angewiesen sind. Eine vollständige Entfernung (__return_empty_array) ist nur dann gerechtfertigt, wenn Sie ein Shop-Theme von Grund auf neu erstellen und sicher wissen, dass keine Drittanbieter-Plugins Elemente hinzufügen, die für WooCommerce gestaltet sind. In den meisten Fällen reicht es aus, woocommerce-layout selektiv zu deaktivieren (das prozentuale Raster kollidiert mit Flexbox und Grids in modernen Themes), während woocommerce-general und woocommerce-smallscreen erhalten bleiben und über die CSS-Kaskade sorgfältig überschrieben werden. So erhalten Sie ein sauberes Raster, ohne die Kompatibilität zu verlieren.

Warum funktioniert das Ändern der Spaltenanzahl im Shop nicht?

Weil der Filter loop_shop_columns allein nicht ausreicht. WooCommerce verwendet .columns-N-Klassen auf dem Wrapper, damit das Raster funktioniert, und diese werden automatisch nur bei Shortcodes ([products columns="4"]) hinzugefügt. Auf Shop-Seiten und Archivseiten existiert dieser Wrapper nicht, daher müssen Sie die Klasse über body_class zum body hinzufügen. Die beiden Filter aus Abschnitt 3 lösen dieses Problem vollständig.

Der Filter loop_shop_columns ändert die PHP-Variable, die WooCommerce an das Template übergibt, aber das CSS-Raster hängt von der Wrapper-Klasse ab. Ohne die Klasse columns-4 auf dem body haben Ihre ul.products li.product-Stile keinen Kontext-Selektor und greifen entweder nicht oder betreffen alle Produktlisten auf der gesamten Website.

Muss ich das Theme nach einem WooCommerce-Update neu erstellen?

Wenn Sie Hooks verwenden (alle Codebeispiele aus diesem Artikel), nein. Hooks ändern sich äußerst selten. Wenn Sie Templates überschreiben (Dateien aus woocommerce/templates/), ja, dann müssen Sie Ihre Kopien nach jedem größeren Update mit den aktuellen Versionen abgleichen. Genau deshalb empfiehlt die offizielle Dokumentation Hooks als bevorzugte Anpassungsmethode.

Hooks sind ein Vertrag. WooCommerce garantiert ihre Stabilität zwischen Versionen. Templates sind eine Implementierung, die sich jederzeit ändern kann: Neue Actions werden hinzugefügt, Markup ändert sich, Klassen werden umbenannt. In den fünf Jahren, in denen diese Hooks existieren (loop_shop_columns und woocommerce_output_related_products_args), hat sich ihre Signatur nie geändert, während die Datei content-product.php im selben Zeitraum dutzende Male aktualisiert wurde.

Kann ich is_admin() verwenden, um Warenkorbfunktionen zu schützen?

Nein, und das ist eine häufige Falle. WooCommerce-AJAX-Anfragen (In den Warenkorb, Menge aktualisieren) werden über admin-ajax.php verarbeitet; in diesem Kontext gibt is_admin() true zurück. Wenn Sie Warenkorbfunktionen in if ( ! is_admin() ) verpacken, funktionieren AJAX-Fragment-Updates (add_to_cart_fragments) nicht mehr, und die Summe im Warenkorb-Symbol ändert sich nicht ohne einen Seiten-Reload.

Das Verpacken in ! is_admin() sollte nur für Dinge verwendet werden, die nicht im Admin-Bereich ausgeführt werden sollen (Frontend-HTML-Ausgabe), aber AJAX-Handler-Funktionen müssen immer verfügbar sein. Verwenden Sie für den Code in Abschnitt 7 überhaupt kein is_admin(). WooCommerce selbst ruft die notwendigen Callbacks über seinen AJAX-Handler auf, und die Einschränkung würde die Logik zerstören.

Wie füge ich WooCommerce-Unterstützung zu einem Block-Theme (FSE) hinzu?

Für Block-Themes hat sich die Support-Deklaration nicht geändert: dasselbe add_theme_support('woocommerce'). Aber anstelle von Hooks und dem Überschreiben von PHP-Templates arbeiten Sie im Site-Editor: WooCommerce stellt Blöcke (Produkte, Produktsuche, Warenkorb, Kasse) bereit, die Sie über Appearance → Editor in Templates einfügen. Die Feinabstimmung erfolgt über theme.json und CSS-Variablen.

Block-Themes ändern den Ansatz grundlegend: Sie schreiben keine PHP-Hooks für das Layout, sondern setzen Seiten visuell aus fertigen WooCommerce-Blöcken zusammen. Aber die Grundlage (add_theme_support in functions.php) bleibt dieselbe. Für Feinanpassungen, die mit Blöcken nicht möglich sind (zum Beispiel benutzerdefinierter Text auf dem „In den Warenkorb"-Button), funktionieren die bewährten Filter aus diesem Artikel auch in FSE-Themes.

Welche Strategie Sie für Ihr Projekt wählen sollten

Wenn Sie ein bestehendes Theme erweitern, beginnen Sie mit den Schritten 1 und 2: Deklarieren Sie den Support und konfigurieren Sie das Raster. In den meisten Fällen reicht das aus, damit der Shop anständig aussieht. Fügen Sie dann nur die Korrekturen hinzu, die spezifische Probleme lösen: eine defekte Galerie, eine unschöne Paginierung, ein fehlender Warenkorb im Menü.

Wenn Sie ein Theme von Grund auf für den Verkauf oder die Verteilung schreiben, gehen Sie die gesamte Liste durch. Jeder Punkt fügt etwas hinzu, das Nutzer von einem Shop-Theme „out of the box" erwarten: ein anpassbares Raster, Zoom auf Produkte, ein Live-Warenkorb-Symbol. Platzieren Sie den Code in inc/woocommerce.php und laden Sie ihn basierend auf der Konstante. So funktioniert das Theme gleichermaßen gut als Blog und als Shop.

Der Ausgangspunkt ist immer derselbe:

1add_action( 'after_setup_theme', function() {
2 add_theme_support( 'woocommerce' );
3} );

Acht Zeilen. Alles Weitere sind Details, die ein „kompatibles" Theme von einem „speziell entwickelten" unterscheiden.