
🔧 Comment rendre un thème WordPress compatible avec WooCommerce : un guide complet pour les développeurs
Construisez votre propre thème et souhaitez y intégrer une boutique? Techniquement, WooCommerce fonctionne avec n'importe quel thème, car il s'agit simplement d'une extension. Mais «fonctionner» ne signifie pas «s'afficher correctement»: la grille de produits se casse, les barres latérales se décalent et les styles par défaut entrent en conflit avec les vôtres.
Le problème va bien au-delà de quelques règles CSS. Depuis WooCommerce 3.3, un thème sans prise en charge déclarée reçoit un rendu simplifié via des shortcodes et un avertissement dans l'administration. Vous perdez le contrôle total de la mise en page.
Voici des extraits de code prêts à l'emploi, couvrant tout, de la déclaration de prise en charge à un panier dynamique dans le menu. Chacun a été testé sur la version actuelle de WooCommerce et est organisé par section, des fondamentaux aux réglages fins.
💡 Aperçu rapide:
- D'abord, le thème doit déclarer explicitement la prise en charge de WooCommerce; sans cela, les surcharges de templates et certaines fonctionnalités ne s'activeront pas
- Placez le code dans un fichier séparé (par exemple
inc/woocommerce.php) qui se charge uniquement lorsque l'extension est active - La configuration de la grille de la boutique nécessite deux filtres: l'un modifie le nombre de colonnes, l'autre ajoute une classe à
body - La galerie de produits, le zoom, la lightbox et le slider s'activent via des appels distincts à
add_theme_support - Le panier dans le menu doit se mettre à jour via AJAX; utilisez le filtre
add_to_cart_fragments
1. Fondamentaux: déclarer la prise en charge et vérifier si l'extension est active
Avant toute chose, le thème doit dire explicitement à WooCommerce: «Je vous prends en charge.» Sans cela, l'extension n'activera pas les surcharges de templates et affichera un avertissement dans l'administration. Depuis WooCommerce 3.3, un thème sans prise en charge déclarée reçoit un rendu simplifié via des shortcodes. Cela fonctionne, mais limite votre contrôle sur la mise en page.
1 add_action( 'after_setup_theme', function() { 2 add_theme_support( 'woocommerce' ); 3 } );
Il est important d'utiliser le hook after_setup_theme plutôt que init, comme le recommande la documentation de WooCommerce. Depuis la version 3.3+, vous pouvez passer directement les paramètres de la grille:
1 add_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 } );
Ces paramètres définissent les valeurs par défaut pour l'outil de personnalisation (WooCommerce → Images des produits / Catalogue de produits) et évitent aux utilisateurs de devoir configurer la grille manuellement.
Vérifier si l'extension est active
Lorsque vous distribuez un thème, vous ne pouvez pas simplement ajouter des extraits WooCommerce à la fin de functions.php, car ils provoqueront une erreur fatale si l'extension n'est pas active. Le code ne doit se charger que lorsque WooCommerce est en cours d'exécution:
1 define( 'MYTHEME_WOOCOMMERCE_ACTIVE', class_exists( 'WooCommerce' ) ); 2 3 if ( MYTHEME_WOOCOMMERCE_ACTIVE ) { 4 require_once get_template_directory() . '/inc/woocommerce.php'; 5 }
La constante est évaluée une seule fois, et ensuite, n'importe où dans votre thème, vous pouvez encadrer les appels par if ( MYTHEME_WOOCOMMERCE_ACTIVE ). C'est plus propre que d'appeler class_exists ou is_plugin_active à chaque fois.
2. Gérer les styles de WooCommerce
WooCommerce est livré avec trois fichiers CSS: woocommerce-general, woocommerce-layout et woocommerce-smallscreen. L'idéal est de ne pas les supprimer, mais de les surcharger dans votre thème. Ainsi, les extensions tierces de WooCommerce qui s'appuient sur ces classes ne cassent pas. Mais si vous écrivez tout à partir de zéro et souhaitez un contrôle total, voici comment les supprimer.
Supprimer tous les styles en une fois:
1 add_filter( 'woocommerce_enqueue_styles', '__return_empty_array' );
Ou supprimer de manière sélective:
1 function mytheme_remove_woo_styles( $styles ) { 2 unset( $styles['woocommerce-general'] ); 3 unset( $styles['woocommerce-layout'] ); 4 unset( $styles['woocommerce-smallscreen'] ); 5 return $styles; 6 } 7 add_filter( 'woocommerce_enqueue_styles', 'mytheme_remove_woo_styles' );
En pratique, la seconde option est plus courante: vous supprimez woocommerce-layout (la grille basée sur des pourcentages) mais conservez woocommerce-general (boutons, notifications, formulaires) et les surchargez sélectivement avec votre propre CSS en utilisant une spécificité plus élevée.
3. Configurer les pages de la boutique
Combien de produits afficher
Le filtre loop_shop_per_page contrôle le nombre de produits sur la page de la boutique et dans les archives (catégories, étiquettes):
1 function mytheme_woo_posts_per_page( $cols ) { 2 return 12; 3 } 4 add_filter( 'loop_shop_per_page', 'mytheme_woo_posts_per_page' );
Nombre de colonnes dans la grille
Deux filtres sont nécessaires ici. Utiliser loop_shop_columns seul ne suffit pas: contrairement aux shortcodes WooCommerce (qui disposent d’un wrapper avec une classe columns-N), les pages boutique n’ont pas cette classe. Nous l’ajoutons donc à body:
1 function mytheme_woo_shop_columns( $columns ) { 2 return 4; 3 } 4 add_filter( 'loop_shop_columns', 'mytheme_woo_shop_columns' ); 5 6 function 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 } 12 add_filter( 'body_class', 'mytheme_woo_shop_columns_body_class' );
Désormais, en CSS, vous pouvez écrire des sélecteurs comme .columns-4 ul.products li.product, et ils s’appliqueront spécifiquement à la grille de la boutique.
Titre de la boutique
Par défaut, WooCommerce affiche «Shop» comme titre sur la page boutique. Si votre thème gère déjà les titres d’archive, ce doublon devient gênant:
1 add_filter( 'woocommerce_show_page_title', '__return_false' );
Si vous utilisez the_archive_title(), vous pouvez remplacer le titre par le nom de la page boutique (défini dans l’administration):
1 function 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 } 7 add_filter( 'get_the_archive_title', 'mytheme_woo_archive_title' );
4. Galerie produit: zoom, lightbox et slider
À partir de WooCommerce 3.0, une nouvelle galerie produit a été introduite, basée sur FlexSlider, PhotoSwipe et jQuery Zoom. Dans les versions 3.0 à 3.2, elle est désactivée par défaut et nécessite une activation explicite. À partir de la version 3.3, la galerie est activée pour les thèmes non WooCommerce et désactivée pour les thèmes qui déclarent la prendre en charge; vous activez vous-même les composants dont vous avez besoin:
1 add_theme_support( 'wc-product-gallery-slider' ); 2 add_theme_support( 'wc-product-gallery-zoom' ); 3 add_theme_support( 'wc-product-gallery-lightbox' );
Vous pouvez n’activer que certaines fonctionnalités: par exemple, le slider et le zoom, oui, mais remplacer la lightbox par votre propre solution Fancybox. Chaque directive charge ses propres scripts, n’activez donc pas ce dont vous n’avez pas besoin.
Nombre de colonnes pour les vignettes de la galerie (sous l’image principale du produit):
1 function mytheme_woo_product_thumbnails_columns() { 2 return 4; 3 } 4 add_action( 'woocommerce_product_thumbnails_columns', 'mytheme_woo_product_thumbnails_columns' );
5. Produits apparentés et ventes croisées / ventes additionnelles
Sur la page produit, WooCommerce affiche des blocs «Produits apparentés» et «Vous aimerez peut-être aussi» (ventes additionnelles). Leur nombre et leur grille se configurent séparément.
Combien de produits apparentés afficher:
1 function mytheme_woo_related_posts_per_page( $args ) { 2 $args['posts_per_page'] = 4; 3 return $args; 4 } 5 add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_posts_per_page' );
Colonnes pour les blocs de ventes additionnelles et de produits apparentés (même logique que pour la grille boutique): nous modifions à la fois les colonnes et la classe sur body:
1 function mytheme_woo_single_loops_columns( $columns ) { 2 return 4; 3 } 4 add_filter( 'woocommerce_up_sells_columns', 'mytheme_woo_single_loops_columns' ); 5 6 function mytheme_woo_related_columns( $args ) { 7 $args['columns'] = 4; 8 return $args; 9 } 10 add_filter( 'woocommerce_output_related_products_args', 'mytheme_woo_related_columns', 10 ); 11 12 function mytheme_woo_single_loops_columns_body_class( $classes ) { 13 if ( is_singular( 'product' ) ) { 14 $classes[] = 'columns-4'; 15 } 16 return $classes; 17 } 18 add_filter( 'body_class', 'mytheme_woo_single_loops_columns_body_class' );
Notez que woocommerce_output_related_products_args comporte deux filtres avec des priorités différentes: mytheme_woo_related_posts_per_page (priorité par défaut 10) modifie posts_per_page, et mytheme_woo_related_columns (priorité 10) modifie columns. Ils n’entrent pas en conflit car ils agissent sur des clés différentes au sein du même tableau $args.
6. Pagination et badge promotion
Vous pouvez remplacer les flèches de pagination par les icônes de votre thème:
1 function 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 } 6 add_filter( 'woocommerce_pagination_args', 'mytheme_woo_pagination_args' );
Remplacez les classes Font Awesome par vos propres classes d’icônes ou des SVG directs.
Le texte du badge de promotion (Sale!) est facile à modifier. C’est utile pour les sites dans d’autres langues ou simplement pour supprimer le point d’exclamation:
1 function mytheme_woo_sale_flash() { 2 return '<span class="onsale">' . esc_html__( 'Sale', 'woocommerce' ) . '</span>'; 3 } 4 add_filter( 'woocommerce_sale_flash', 'mytheme_woo_sale_flash' );
Pour d’autres langues, remplacez 'Sale' par votre traduction. La traduction sera prise en compte automatiquement si vous disposez des fichiers MO de WooCommerce pour cette langue.
7. Panier dynamique dans le menu
C’est probablement l’élément le plus demandé dans un thème de boutique: une icône de panier dans la navigation avec le total actuel. La mise en œuvre comprend trois parties: ajouter l’élément au menu, générer le HTML du panier et la mise à jour en AJAX.
1 // Adding the link to the menu 2 function 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 } 14 add_filter( 'wp_nav_menu_items', 'mytheme_add_menu_cart_item', 10, 2 ); 15 16 // Cart HTML 17 function 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 31 function mytheme_menu_cart_link_fragments( $fragments ) { 32 $fragments['.wpex-menu-cart-total'] = mytheme_menu_cart_item(); 33 return $fragments; 34 } 35 add_filter( 'add_to_cart_fragments', 'mytheme_menu_cart_link_fragments' );
Point critique: n’enveloppez pas ces fonctions dans is_admin(). Les requêtes AJAX du panier passent par admin-ajax.php, et si la fonction n’est pas disponible dans le contexte admin, la mise à jour du prix dans le menu ne fonctionnera tout simplement pas. Remplacez theme_location par l’identifiant de votre menu (primary dans l’exemple).
8. Approche alternative: le template woocommerce.php
Les hooks décrits ci-dessus constituent la méthode la plus flexible et la plus résistante aux mises à jour. Mais si vous devez refondre radicalement l’ensemble de l’enveloppe de la boutique et de la page produit, il existe une voie via un template séparé.
Créez un fichier woocommerce.php à la racine de votre thème (une copie de page.php) et remplacez la boucle principale par un appel à woocommerce_content():
1 <?php 2 get_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
Cette méthode est plus simple, mais elle a un coût: un seul template pour toutes les pages WooCommerce (la boutique, les catégories et la fiche produit). Les ajustements fins (différentes grilles, différentes barres latérales selon les pages) deviennent plus difficiles. Choisissez cette approche uniquement si votre thème actuel ne s’entend vraiment pas avec WooCommerce au niveau du balisage, et que vous êtes prêt à en accepter les limites.
⁉️🤔 Foire aux questions
Est-il obligatoire de supprimer les styles par défaut de WooCommerce?
Non, ce n’est pas obligatoire. Une approche plus prudente consiste à les conserver et à surcharger les sélecteurs dans votre thème avec une spécificité plus élevée. Cela préserve la compatibilité avec les extensions qui s’appuient sur les classes WooCommerce standard. La suppression complète (
__return_empty_array) ne se justifie que si vous construisez un thème boutique from scratch et que vous avez la certitude qu’aucun plugin tiers n’ajoutera d’éléments stylés pour WooCommerce. Dans la plupart des cas, il suffit de désactiver sélectivementwoocommerce-layout(la grille en pourcentage entre en conflit avec flexbox et les grilles CSS des thèmes modernes) tout en conservantwoocommerce-generaletwoocommerce-smallscreenet en les surchargeant soigneusement via la cascade CSS. Vous obtenez ainsi une grille propre sans perdre la compatibilité.
Pourquoi le changement du nombre de colonnes dans la boutique ne fonctionne-t-il pas?
Parce que le filtre loop_shop_columns seul ne suffit pas. WooCommerce utilise les classes .columns-N sur le conteneur pour faire fonctionner la grille, et elles ne sont ajoutées automatiquement qu’aux shortcodes ([products columns="4"]). Sur les pages boutique et les archives, ce conteneur n’existe pas, vous devez donc ajouter la classe à body via body_class. Les deux filtres de la section 3 résolvent complètement ce problème.
Le filtre
loop_shop_columnsmodifie la variable PHP que WooCommerce transmet au template, mais la grille CSS dépend de la classe du conteneur. Sans la classecolumns-4surbody, vos stylesul.products li.productn’ont pas de sélecteur de contexte et soit ne s’appliquent pas, soit touchent toutes les listes de produits du site.
Dois-je reconstruire le thème après une mise à jour de WooCommerce?
Si vous utilisez des hooks (tous les extraits de cet article), non. Les hooks changent extrêmement rarement. Si vous surchargez des templates (les fichiers de woocommerce/templates/), oui, vous devez comparer vos copies avec les versions actuelles après chaque mise à jour majeure. C’est précisément pour cette raison que la documentation officielle recommande les hooks comme méthode de personnalisation privilégiée.
Les hooks sont un contrat. WooCommerce garantit leur stabilité entre les versions. Les templates sont une implémentation qui peut changer à tout moment: de nouvelles actions sont ajoutées, le balisage évolue, les classes sont renommées. En cinq ans d’existence de ces hooks (
loop_shop_columnsetwoocommerce_output_related_products_args), leur signature n’a jamais changé, tandis que le fichiercontent-product.phpa été mis à jour des dizaines de fois sur la même période.
Puis-je utiliser is_admin() pour protéger les fonctions du panier?
Non, et c’est un piège courant. Les requêtes AJAX de WooCommerce (ajout au panier, mise à jour de la quantité) sont traitées via admin-ajax.php; dans ce contexte, is_admin() renvoie true. Si vous enveloppez les fonctions du panier dans if ( ! is_admin() ), les mises à jour des fragments AJAX (add_to_cart_fragments) cesseront de fonctionner et le total dans l’icône du panier ne changera pas sans rechargement de la page.
L’encapsulation dans
! is_admin()ne doit être utilisée que pour ce qui ne doit pas s’exécuter dans l’administration (affichage HTML front-end), mais les fonctions de gestion AJAX doivent toujours être disponibles. Pour le code de la section 7, n’utilisez pas du toutis_admin(). WooCommerce appelle lui-même les callbacks nécessaires via son gestionnaire AJAX, et la restriction cassera la logique.
Comment ajouter la prise en charge de WooCommerce à un thème bloc (FSE)?
Pour les thèmes bloc, la déclaration de prise en charge n’a pas changé: le même add_theme_support('woocommerce'). Mais au lieu de hooks et de surcharge de templates PHP, vous travaillez dans l’éditeur de site: WooCommerce fournit des blocs (Produits, Recherche de produits, Panier, Commande) que vous insérez dans les templates via Appearance → Editor. Les ajustements fins se font via theme.json et les variables CSS.
Les thèmes bloc changent fondamentalement l’approche: vous n’écrivez pas de hooks PHP pour la mise en page, mais vous assemblez visuellement les pages à partir de blocs WooCommerce prêts à l’emploi. Mais la base (
add_theme_supportdansfunctions.php) reste la même. Pour les ajustements fins impossibles à réaliser avec des blocs (par exemple, un texte personnalisé sur le bouton «Ajouter au panier»), les bons vieux filtres de cet article fonctionnent aussi dans les thèmes FSE.
Quelle stratégie choisir pour votre projet
Si vous améliorez un thème existant, commencez par les étapes 1 et 2: déclarez la prise en charge et configurez la grille. Dans la plupart des cas, cela suffit pour que la boutique ait un aspect correct. Ajoutez ensuite uniquement les correctifs qui résolvent des problèmes spécifiques: une galerie cassée, une pagination disgracieuse, l’absence du panier dans le menu.
Si vous écrivez un thème from scratch destiné à la vente ou à la distribution, parcourez toute la liste. Chaque élément ajoute une fonctionnalité que les utilisateurs attendent d’un thème boutique «prêt à l’emploi»: une grille personnalisable, le zoom sur les produits, une icône de panier dynamique. Placez le code dans inc/woocommerce.php et chargez-le en fonction de la constante. Ainsi, le thème fonctionne aussi bien comme blog que comme boutique.
Le point de départ est toujours le même:
1 add_action( 'after_setup_theme', function() { 2 add_theme_support( 'woocommerce' ); 3 } );
Huit lignes. Tout le reste n’est que détails qui distinguent un thème «compatible» d’un thème «conçu pour».



