Déplacer le menu horizontal PrestaShop vers un autre hook
Guide complet pour repositionner le menu horizontal PrestaShop (blocktopmenu) du hook displayTop vers displayNav. Code, pièges CSS et migration PS 8.
En bref : Pour déplacer le menu horizontal PrestaShop, remplacez le hook `displayTop` par `displayNav` dans la méthode install() du module, ajoutez une méthode `hookDisplayNav()` qui délègue au rendu existant, et réinstallez le module. Assurez-vous que le hook `header` est bien enregistré pour le chargement des CSS/JS.
Pourquoi repositionner le menu horizontal dans PrestaShop
Le module blocktopmenu (renommé ps_mainmenu depuis PrestaShop 1.7) s'accroche par défaut au hook displayTop. Ce positionnement convient à la majorité des thèmes, mais certains designs exigent que le menu apparaisse dans la barre de navigation supérieure — le hook displayNav — pour obtenir un header plus compact ou un agencement visuel différent.
Déplacer un module d'un hook à un autre est une opération courante en développement PrestaShop, mais elle réserve plusieurs pièges si on ne maîtrise pas le mécanisme des hooks et le système de surcharge des thèmes.
Comprendre les hooks d'affichage du header
Avant de toucher au code, il faut comprendre la hiérarchie des hooks dans le header PrestaShop :
PrestaShop 1.7+ / 8.x : Les hooks ont été renommés et scindés.
displayNavdevientdisplayNav1etdisplayNav2. Le moduleps_mainmenus'accroche àdisplayToppar défaut. Le principe de migration reste identique.
Méthode 1 : Greffer le module via le back-office
La méthode la plus simple ne nécessite aucune modification de code :
- Rendez-vous dans **Apparence → Positions des modules**
- Recherchez le module `blocktopmenu` (ou `Menu principal` en PS 8.x)
- Décrochez-le du hook `displayTop` (icône de suppression)
- Cliquez sur **Greffer un module**, sélectionnez le module et choisissez le hook `displayNav`
- Le hook `header` est **indispensable** : c'est lui qui injecte les fichiers CSS et JS dans le ``. Sans lui, le menu s'affichera sans aucun style.
- On commente `displayTop` et on ajoute `displayNav` à la place.
- **Back-office → Modules → blocktopmenu → Désinstaller** (sans supprimer les données si l'option est proposée)
- **Réinstaller** le module
- Renommez le dossier `themes/votre-theme/modules/blocktopmenu/` en `blocktopmenu-save/`
- Videz le cache PrestaShop
- Rechargez la page
- [ ] Le menu s'affiche au bon emplacement
- [ ] Les sous-menus en survol (dropdown) fonctionnent
- [ ] Les fichiers CSS sont bien chargés (inspecteur navigateur → onglet Réseau)
- [ ] Les fichiers JS sont chargés (effets hover, animations Superfish)
- [ ] Le menu responsive fonctionne sur mobile
- [ ] Le cache PrestaShop est vidé (`Paramètres avancés → Performances`)
- [ ] La page est testée en navigation privée (pas de cache navigateur)
Limite : cette méthode ne greffe pas automatiquement les assets CSS et JS du module. Si le menu s'affiche sans mise en forme, il faudra passer à la méthode 2.
Méthode 2 : Modifier le module pour enregistrer le bon hook
Cette méthode est plus robuste car elle garantit le chargement des assets et persiste après une réinstallation du module.
Étape 1 — Modifier la méthode `install()`
Dans le fichier blocktopmenu.php (PS 1.6) ou ps_mainmenu.php (PS 1.7+), localisez la méthode install() et remplacez le hook d'affichage :
public function install($delete_params = true)
{
if (!parent::install() ||
// On remplace displayTop par displayNav
// !$this->registerHook('displayTop') ||
!$this->registerHook('header') ||
!$this->registerHook('displayNav') ||
!$this->registerHook('actionObjectCategoryUpdateAfter') ||
!$this->registerHook('actionObjectCategoryDeleteAfter') ||
!$this->registerHook('actionObjectCategoryAddAfter') ||
!$this->registerHook('actionObjectCmsUpdateAfter') ||
!$this->registerHook('actionObjectCmsDeleteAfter') ||
!$this->registerHook('actionObjectCmsAddAfter') ||
!$this->registerHook('actionObjectSupplierUpdateAfter') ||
!$this->registerHook('actionObjectSupplierDeleteAfter') ||
!$this->registerHook('actionObjectSupplierAddAfter') ||
!$this->registerHook('actionObjectManufacturerUpdateAfter') ||
!$this->registerHook('actionObjectManufacturerDeleteAfter') ||
!$this->registerHook('actionObjectManufacturerAddAfter')
) {
return false;
}
return true;
}
Points essentiels :
Étape 2 — Ajouter la méthode `hookDisplayNav()`
Le module possède une méthode hookDisplayTop() qui génère le HTML du menu. Il faut créer son équivalent pour le hook displayNav :
public function hookDisplayNav($params)
{
return $this->hookDisplayTop($params);
}
Cette approche par délégation est la plus propre : tout le code de rendu reste centralisé dans hookDisplayTop(), et hookDisplayNav() se contente de le relayer.
Étape 3 — Réinstaller le module
Après modification du fichier PHP, il faut désinstaller puis réinstaller le module pour que les nouveaux hooks soient enregistrés en base de données :
Astuce : En PrestaShop 8.x, vous pouvez aussi forcer l'enregistrement d'un hook sans réinstaller via la console Symfony :
```bash
php bin/console prestashop:module reset ps_mainmenu
```
Le piège classique : le CSS qui disparaît
C'est le problème le plus fréquent lors d'un changement de hook. Le menu s'affiche en HTML brut, sans aucune mise en forme. Deux causes possibles :
Cause 1 : Le hook `header` n'est pas enregistré
Le chargement des CSS et JS se fait dans la méthode hookDisplayTop() via ces appels :
$this->context->controller->addCSS($this->_path.'css/blocktopmenu.css');
$this->context->controller->addCSS($this->_path.'css/superfish-modified.css');
$this->context->controller->addJS($this->_path.'js/hoverIntent.js');
$this->context->controller->addJS($this->_path.'js/superfish-modified.js');
$this->context->controller->addJS($this->_path.'js/blocktopmenu.js');
Si ces appels ne sont plus exécutés (parce que hookDisplayTop n'est plus appelé), les assets ne sont pas chargés. La solution : s'assurer que la méthode hookDisplayNav() délègue bien à hookDisplayTop() comme montré plus haut.
Cause 2 : Les surcharges du thème
La plupart des thèmes incluent leurs propres fichiers CSS pour le module menu dans :
themes/votre-theme/modules/blocktopmenu/css/
Ces surcharges sont parfois liées au hook d'origine. Pour diagnostiquer :
Si le menu s'affiche correctement (avec les styles par défaut du module), le problème vient bien de la surcharge thème. Il faudra alors adapter les fichiers CSS du thème pour cibler le conteneur du hook displayNav au lieu de displayTop.
Adaptation pour PrestaShop 8.x
En PrestaShop 8.x avec le module ps_mainmenu, l'architecture a évolué mais le principe reste le même :
// ps_mainmenu.php — PrestaShop 8.x
public function install()
{
return parent::install()
&& $this->registerHook('displayNav1') // au lieu de displayTop
&& $this->registerHook('displayHeader')
&& $this->registerHook('actionObjectCategoryUpdateAfter')
&& $this->registerHook('actionObjectCategoryDeleteAfter')
&& $this->registerHook('actionObjectCategoryAddAfter')
&& $this->registerHook('actionObjectCmsUpdateAfter')
&& $this->registerHook('actionObjectCmsDeleteAfter')
&& $this->registerHook('actionObjectCmsAddAfter');
}
public function hookDisplayNav1($params)
{
return $this->renderWidget(null, $params);
}
Note : En PS 8.x, le pattern
renderWidget()remplace les ancienshookDisplay*()directs. Le module implémente l'interfaceWidgetInterfaceet centralise le rendu dansrenderWidget().
Vérifications post-modification
Après avoir déplacé le menu, vérifiez systématiquement :
Méthode alternative : transplantation SQL directe
Pour les développeurs à l'aise avec la base de données, il est possible de changer le hook sans modifier le code PHP ni réinstaller le module :
UPDATE ps_hook_module hm
JOIN ps_hook h_old ON hm.id_hook = h_old.id_hook AND h_old.name = 'displayTop'
JOIN ps_hook h_new ON h_new.name = 'displayNav'
JOIN ps_module m ON hm.id_module = m.id_module AND m.name = 'blocktopmenu'
SET hm.id_hook = h_new.id_hook;
Attention : Cette méthode ne modifie que la greffe. Si le module n'a pas de méthode
hookDisplayNav(), il faudra quand même l'ajouter dans le code PHP. Pensez aussi à vider le cache après la modification SQL.
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.