Intégrer Bootstrap dans le menu PrestaShop : refonte du blocktopmenu
Guide complet pour remplacer le menu natif PrestaShop par un menu Bootstrap responsive. Code, bonnes pratiques et migration vers PrestaShop 8.
En bref : Le module blocktopmenu (ps_mainmenu depuis PS 1.7) peut être refactorisé pour utiliser les classes Bootstrap natives, ce qui résout les bugs mobile, facilite la personnalisation et permet d'intégrer panier et recherche directement dans la navbar.
Pourquoi le menu natif PrestaShop pose problème
Le module blocktopmenu (renommé ps_mainmenu depuis PrestaShop 1.7) est fonctionnel, mais il souffre de plusieurs limitations qui frustrent les intégrateurs :
- **Comportement mobile bancal** : sur PrestaShop 1.6, les sous-menus nécessitaient parfois un double clic pour se déplier, ce qui dégradait l'expérience utilisateur sur mobile.
- **CSS et JS propriétaires** : le menu utilise ses propres styles et scripts au lieu de s'appuyer sur un framework CSS standard, ce qui complique la personnalisation.
- **Intégration limitée** : impossible d'ajouter nativement des éléments comme le panier ou la barre de recherche dans la barre de navigation.
La solution la plus propre consiste à refondre le rendu du menu en s'appuyant sur les classes Bootstrap, tout en conservant la logique back-office de gestion des catégories.
Stratégie de refonte : modifier le module ou créer un override
Option 1 : Override du module (recommandé)
Pour PrestaShop 1.6 et 1.7, la méthode la plus maintenable consiste à créer un override du module plutôt que de modifier directement ses fichiers :
/override/modules/blocktopmenu/blocktopmenu.php
Cela permet de conserver les mises à jour du module sans perdre vos personnalisations.
Option 2 : Template custom dans le thème
Sur PrestaShop 1.7+, privilégiez la surcharge du template dans votre thème :
/themes/votre-theme/modules/ps_mainmenu/ps_mainmenu.tpl
Sur PrestaShop 8.x, le module ps_mainmenu utilise Smarty et la même logique de surcharge s'applique.
Réécrire le rendu HTML avec les classes Bootstrap
L'objectif est de remplacer le markup propriétaire par une structure Bootstrap standard. Voici un exemple de méthode generateCategoriesMenu refactorisée pour produire un menu dropdown Bootstrap :
private function generateCategoriesMenu($categories, $is_children = 0)
{
$html = '';
foreach ($categories as $key => $category) {
$cat = new Category($category['id_category'], $this->context->language->id);
$link = Tools::htmlentitiesUTF8($cat->getLink());
$hasChildren = isset($category['children']) && !empty($category['children']);
$isActive = ($this->page_name === 'category'
&& (int) Tools::getValue('id_category') === (int) $category['id_category']);
if ($hasChildren && !$is_children) {
// Catégorie parent avec sous-menu
$html .= '<li class="nav-item dropdown' . ($isActive ? ' active' : '') . '">';
$html .= '<a class="nav-link dropdown-toggle" href="' . $link . '" ';
$html .= 'data-bs-toggle="dropdown" role="button" aria-expanded="false">';
$html .= htmlspecialchars($category['name'], ENT_QUOTES, 'UTF-8');
$html .= '</a>';
$html .= '<ul class="dropdown-menu">';
$html .= $this->generateCategoriesMenu($category['children'], 1);
$html .= '</ul>';
$html .= '</li>';
} else {
// Catégorie sans enfant ou sous-catégorie
$cssClass = $is_children ? 'dropdown-item' : 'nav-link';
$html .= '<li' . ($is_children ? '' : ' class="nav-item"') . '>';
$html .= '<a class="' . $cssClass . ($isActive ? ' active' : '') . '" ';
$html .= 'href="' . $link . '">';
$html .= htmlspecialchars($category['name'], ENT_QUOTES, 'UTF-8');
$html .= '</a>';
$html .= '</li>';
}
}
return $html;
}
Points clés du code
- **`data-bs-toggle="dropdown"`** : attribut Bootstrap 5 (utilisez `data-toggle` pour Bootstrap 3/4 sur PrestaShop 1.6).
- **Échappement HTML** : `htmlspecialchars()` avec `ENT_QUOTES` pour prévenir les failles XSS sur les noms de catégories.
- **Détection de la page active** : on compare `id_category` pour appliquer la classe `.active` et améliorer l'UX.
- **Récursivité propre** : le paramètre `$is_children` contrôle le niveau d'imbrication et adapte les classes CSS.
Intégrer le panier et la recherche dans la navbar
Une fois le menu converti en navbar Bootstrap, vous pouvez y intégrer d'autres éléments. Voici la structure HTML recommandée :
<nav class="navbar navbar-expand-lg navbar-light bg-white">
<div class="container">
<a class="navbar-brand" href="{$link->getPageLink('index')}">
<img src="{$logo_url}" alt="{$shop_name}" height="40">
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#mainNavbar" aria-controls="mainNavbar"
aria-expanded="false" aria-label="Menu">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="mainNavbar">
<!-- Menu catégories -->
<ul class="navbar-nav me-auto">
{$menu_html}
</ul>
<!-- Barre de recherche -->
<form class="d-flex me-3" action="{$link->getPageLink('search')}" method="get">
<input class="form-control" type="search" name="s" placeholder="Rechercher...">
</form>
<!-- Panier -->
<div class="navbar-cart">
{hook h='displayNav'}
</div>
</div>
</div>
</nav>
Corriger le bug du double-clic mobile
Sur PrestaShop 1.6, le menu responsive natif souffrait d'un bug connu : les boutons "+" pour déplier les sous-catégories nécessitaient deux clics. Ce problème venait d'un conflit entre les événements click et touchstart.
Avec Bootstrap, ce bug disparaît car le framework gère nativement les interactions tactiles. Si vous gardez le JS natif, voici le correctif :
// Remplacer l'event click par un gestionnaire propre
$('.menu-mobile .arrow').on('touchstart click', function(e) {
e.preventDefault();
e.stopPropagation();
$(this).closest('li').toggleClass('open');
$(this).closest('li').find('> .dropdown-menu').slideToggle(200);
});
Migration vers PrestaShop 8.x
Sur PrestaShop 8.x, le module ps_mainmenu reste basé sur Smarty mais le thème par défaut utilise Bootstrap 5. Si vous migrez depuis une version 1.6 :
- **Remplacez `data-toggle` par `data-bs-toggle`** dans tous vos templates.
- **Passez de jQuery à du JavaScript natif** si possible — PrestaShop 8 réduit sa dépendance à jQuery.
- **Utilisez les surcharges de template** (`/themes/votre-theme/modules/ps_mainmenu/`) plutôt que les overrides PHP.
- **Testez le rendu mobile** : le `navbar-toggler` Bootstrap 5 gère nativement le responsive sans JS supplémentaire.
- **Ne modifiez jamais les fichiers core du module** : utilisez les overrides ou les surcharges de template.
- **Videz le cache** après chaque modification : Back-office → Paramètres avancés → Performances.
- **Testez sur mobile** : le menu est l'élément le plus critique de la navigation mobile. Utilisez les DevTools Chrome en mode responsive.
- **Accessibilité** : conservez les attributs `aria-expanded`, `aria-label` et `role` pour la conformité WCAG.
- **Performance** : si vous ajoutez le panier au menu, utilisez un chargement AJAX pour éviter d'invalider le cache de page complète.
Bonnes pratiques
Questions fréquentes
Tout ce que vous devez savoir sur ce sujet.
Un projet PrestaShop ?
Discutons-en directement.
193 projets livrés
Lire sur le blog

Alexandre Carette
Expert PrestaShop & Architecture E-commerce
Développeur PrestaShop depuis 2014, 193 projets livrés. Je conçois des architectures headless Nuxt + PrestaShop et des outils d'automatisation IA pour les e-commerçants.