[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"theme-db":3,"$fKnz2vuX4bZz1LbUTiuFsvSZ3e07l5_5fqNYp4Tzdhi8":22,"$fwW7bXStHf9-jpcwjHQgkbqdjaqododncpR1hzsabPjs":103,"megamenu":142,"footer-db":198,"$fBAl7BNWawZR2HfVXRFGzB7kp42e12pjkLGjJIole6-s":216,"header-db":230},{"theme":4},{"colors":5,"typography":13,"ui":17,"defaultColorMode":21},{"primary":6,"secondary":7,"background":8,"foreground":9,"muted":10,"headerBg":11,"footerBg":12,"topBarBg":9,"topBarText":11},"#4F46E5","#0D9488","#F9FAFB","#111827","#6B7280","#ffffff","#020617",{"fontFamily":14,"fontUrl":15,"baseFontSize":16},"Inter, system-ui, sans-serif","https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Inter:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;0,800;0,900;1,400;1,700&display=swap","16px",{"borderRadius":18,"contentWidth":19,"shadow":20},"lg","7xl",true,"light",{"columns":23},[24,40,70,91],{"title":25,"links":26},"Plateforme",[27,31,34,37],{"label":28,"href":29,"external":30},"Offre Starter (2 500 €)","\u002Foffre-starter",false,{"label":32,"href":33,"external":30},"Devenir Ambassadeur","\u002Fambassadeur",{"label":35,"href":36,"external":30},"Modules PrestaShop","\u002Fmodules",{"label":38,"href":39,"external":20},"CodeMyShop.com","https:\u002F\u002Fcodemyshop.com",{"title":41,"links":42},"Le Synedre",[43,46,49,52,55,58,61,64,67],{"label":44,"href":45,"external":30},"L'histoire","\u002Fsynedre",{"label":47,"href":48,"external":30},"Constitution","\u002Fsynedre\u002Fconstitution",{"label":50,"href":51,"external":30},"L'équipe","\u002Fequipe",{"label":53,"href":54,"external":30},"Le réacteur en direct","\u002Freacteur",{"label":56,"href":57,"external":30},"Le Drill (entraînement)","\u002Fdrill",{"label":59,"href":60,"external":30},"Protocole de réunion","\u002Fsynedre\u002Freunion",{"label":62,"href":63,"external":30},"Les agents IA","\u002Fagents-ia",{"label":65,"href":66,"external":30},"La Conduite","\u002Fsynedre\u002Fconduite",{"label":68,"href":69,"external":30},"Charte plateforme","\u002Fsynedre\u002Fcharte",{"title":71,"links":72},"Ressources",[73,76,79,82,85,88],{"label":74,"href":75,"external":30},"Blog","\u002Fblog",{"label":77,"href":78,"external":30},"Academy","\u002Facademy",{"label":80,"href":81,"external":30},"Dictionnaire","\u002Fdictionnaire",{"label":83,"href":84,"external":30},"Expertise PrestaShop","\u002Fexpertise",{"label":86,"href":87,"external":30},"Flywheel","\u002Fflywheel",{"label":89,"href":90,"external":30},"Manifeste","\u002Fmanifeste",{"title":92,"links":93},"À propos",[94,97,100],{"label":95,"href":96,"external":30},"Alexandre Carette","\u002Fa-propos",{"label":98,"href":99,"external":30},"Dossier de presse","\u002Fpresse",{"label":101,"href":102,"external":30},"Contact","\u002Fcontact",{"title":104,"slug":105,"metaDescription":106,"category":107,"tags":108,"difficulty":115,"psVersions":116,"content":120,"faq":121,"tldr":137,"readingTime":138,"generatedAt":139,"publishDate":139,"relatedArticles":140,"sourceCategory":141},"Corriger l'affichage du menu déroulant multi-niveaux dans PrestaShop","corriger-affichage-menu-deroulant-multi-niveaux-prestashop","Résolvez le problème d'affichage des sous-menus PrestaShop : classes CSS dropdown vs dropdown-submenu selon la profondeur de catégorie.","design",[109,110,111,112,113,114],"menu","dropdown","CSS","navigation","blocktopmenu","catégories","intermediaire",[117,118,119],"1.6","1.7","8.x","\u003Ch2>Le problème : un menu déroulant qui refuse de s'afficher correctement\u003C\u002Fh2>\n\u003Cp>Un cas classique en intégration PrestaShop : le menu principal affiche les catégories de premier niveau, mais les sous-menus se comportent de façon erratique. Les catégories de niveau 2 s'affichent comme des sous-sous-menus, le positionnement CSS est décalé, et l'expérience utilisateur en souffre.\u003C\u002Fp>\n\u003Cp>La cause est presque toujours la même : le module de menu attribue la mauvaise classe CSS Bootstrap aux éléments \u003Ccode>\u003Cli>\u003C\u002Fcode> selon leur profondeur dans l'arborescence des catégories.\u003C\u002Fp>\n\u003Ch2>Comprendre la hiérarchie des menus Bootstrap\u003C\u002Fh2>\n\u003Cp>Avant de plonger dans le correctif, il faut comprendre comment Bootstrap (utilisé par la plupart des thèmes PrestaShop) gère les menus déroulants :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>**`dropdown`** : classe attribuée à un élément de navigation de premier niveau qui possède un sous-menu. Elle déclenche un menu déroulant vertical classique.\u003C\u002Fli>\n\u003Cli>**`dropdown-submenu`** : classe attribuée à un élément **à l'intérieur** d'un dropdown existant. Elle provoque l'ouverture d'un panneau latéral (flyout) à droite ou à gauche.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>La confusion entre ces deux classes est la source du bug. Si une catégorie de niveau 2 reçoit \u003Ccode>dropdown-submenu\u003C\u002Fcode> au lieu de \u003Ccode>dropdown\u003C\u002Fcode>, elle sera traitée visuellement comme un sous-sous-menu alors qu'elle devrait ouvrir le premier panneau déroulant.\u003C\u002Fp>\n\u003Ch2>La cause racine dans le code PHP\u003C\u002Fh2>\n\u003Cp>Dans les modules de menu PrestaShop (qu'il s'agisse du \u003Ccode>blocktopmenu\u003C\u002Fcode> natif, de \u003Ccode>blockcategories\u003C\u002Fcode>, ou de modules de thème comme Leo Top Menu), la génération du HTML repose sur la propriété \u003Ccode>level_depth\u003C\u002Fcode> de l'objet \u003Ccode>Category\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>Voici le type de code problématique que l'on rencontre fréquemment :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F Code d'origine — PROBLÉMATIQUE\nelseif ($category-&gt;level_depth &gt; 1 && count($children)) {\n    $this-&gt;_menu .= 'dropdown-submenu\"&gt;';\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Ce code applique \u003Ccode>dropdown-submenu\u003C\u002Fcode> à \u003Cstrong>toutes\u003C\u002Fstrong> les catégories dont la profondeur dépasse 1, sans distinction. Or, dans PrestaShop :\u003C\u002Fp>\n\u003Ctr>\u003Cth>`level_depth`\u003C\u002Fth>\u003Cth>Signification\u003C\u002Fth>\u003Cth>Classe CSS attendue\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>1\u003C\u002Fth>\u003Cth>Catégorie racine (\"Accueil\")\u003C\u002Fth>\u003Cth>—\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>2\u003C\u002Fth>\u003Cth>Catégorie principale (visible dans le menu)\u003C\u002Fth>\u003Cth>`dropdown`\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>3\u003C\u002Fth>\u003Cth>Sous-catégorie\u003C\u002Fth>\u003Cth>`dropdown-submenu`\u003C\u002Fth>\u003C\u002Ftr>\n\u003Ctr>\u003Cth>4+\u003C\u002Fth>\u003Cth>Sous-sous-catégorie\u003C\u002Fth>\u003Cth>`dropdown-submenu`\u003C\u002Fth>\u003C\u002Ftr>\n\u003Cp>Le niveau 2 nécessite \u003Ccode>dropdown\u003C\u002Fcode> pour déclencher le premier menu déroulant. Les niveaux 3 et au-delà nécessitent \u003Ccode>dropdown-submenu\u003C\u002Fcode> pour les panneaux latéraux imbriqués.\u003C\u002Fp>\n\u003Ch2>Le correctif\u003C\u002Fh2>\n\u003Cp>La solution consiste à différencier explicitement le traitement selon le \u003Ccode>level_depth\u003C\u002Fcode> :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F Code corrigé — Distinction par niveau de profondeur\nelseif ($category-&gt;level_depth == 2 && count($children)) {\n    \u002F\u002F Niveau 2 : catégorie principale avec enfants → dropdown classique\n    $this-&gt;_menu .= 'dropdown\"&gt;';\n}\nelseif ($category-&gt;level_depth &gt;= 3 && count($children)) {\n    \u002F\u002F Niveau 3+ : sous-catégorie avec enfants → sous-menu latéral\n    $this-&gt;_menu .= 'dropdown-submenu\"&gt;';\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>Points clés du correctif\u003C\u002Fh3>\n\u003Col>\n\u003Cli>**`level_depth == 2`** remplace `level_depth > 1` pour cibler uniquement les catégories principales.\u003C\u002Fli>\n\u003Cli>**`level_depth >= 3`** (et non `== 3`) assure que les arborescences profondes (4, 5 niveaux…) restent correctement gérées.\u003C\u002Fli>\n\u003Cli>La condition `count($children)` est conservée : si une catégorie n'a pas d'enfants, aucune classe dropdown n'est nécessaire.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Localiser le code à modifier\u003C\u002Fh2>\n\u003Ch3>PrestaShop 1.6\u003C\u002Fh3>\n\u003Cp>Le code se trouve généralement dans :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>`\u002Fmodules\u002Fblocktopmenu\u002Fblocktopmenu.php` (module natif)\u003C\u002Fli>\n\u003Cli>`\u002Fmodules\u002Fblockcategories\u002Fblockcategories.php`\u003C\u002Fli>\n\u003Cli>Ou dans le module de menu de votre thème (ex : `blockleotopmenu`, `megamenu`, etc.)\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Recherchez la méthode qui génère le HTML du menu, souvent nommée \u003Ccode>generateCategoriesMenu()\u003C\u002Fcode> ou similaire.\u003C\u002Fp>\n\u003Ch3>PrestaShop 1.7 et 8.x\u003C\u002Fh3>\n\u003Cp>Le menu natif a été refondu. Le module \u003Ccode>ps_mainmenu\u003C\u002Fcode> utilise désormais des templates Smarty et une logique de rendu différente. Si vous utilisez le thème Classic :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">\n# Localiser les fichiers de template du menu\nfind themes\u002Fvotre-theme\u002Fmodules\u002Fps_mainmenu -name \"*.tpl\"\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Dans les versions modernes, le correctif s'applique plutôt côté template :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-smarty\">\n{* Template Smarty — Correction du niveau de dropdown *}\n{if $node.depth == 2 && $node.children|count &gt; 0}\n    &lt;li class=\"dropdown\"&gt;\n{elseif $node.depth &gt;= 3 && $node.children|count &gt; 0}\n    &lt;li class=\"dropdown-submenu\"&gt;\n{else}\n    &lt;li&gt;\n{\u002Fif}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2>Bonnes pratiques pour les menus multi-niveaux\u003C\u002Fh2>\n\u003Ch3>1. Limiter la profondeur d'arborescence\u003C\u002Fh3>\n\u003Cp>Au-delà de 3 niveaux de menu, l'ergonomie se dégrade fortement sur desktop et devient inutilisable sur mobile. Privilégiez une navigation à 2 niveaux maximum avec des pages de catégories bien structurées.\u003C\u002Fp>\n\u003Ch3>2. Tester sur mobile\u003C\u002Fh3>\n\u003Cp>Les classes \u003Ccode>dropdown-submenu\u003C\u002Fcode> fonctionnent avec des événements \u003Ccode>:hover\u003C\u002Fcode> qui n'existent pas sur tactile. Vérifiez que votre thème gère correctement le \u003Ccode>click\u003C\u002Fcode> \u002F \u003Ccode>touch\u003C\u002Fcode> pour les sous-menus.\u003C\u002Fp>\n\u003Ch3>3. Surcharger plutôt que modifier le core\u003C\u002Fh3>\n\u003Cp>Si vous modifiez un module natif, créez une surcharge (override) plutôt que d'éditer directement le fichier. Cela protège votre correctif lors des mises à jour :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-php\">\n\u002F\u002F \u002Foverride\u002Fmodules\u002Fblocktopmenu\u002Fblocktopmenu.php\nclass BlockTopMenuOverride extends BlockTopMenu\n{\n    \u002F\u002F Surcharger la méthode concernée\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>En PrestaShop 8.x, préférez l'approche par décorateur de service Symfony si le module le supporte.\u003C\u002Fp>\n\u003Ch3>4. Vider le cache après modification\u003C\u002Fh3>\n\u003Cp>Après toute modification du menu :\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">\n# Vider le cache PrestaShop\nrm -rf var\u002Fcache\u002Fprod\u002F* var\u002Fcache\u002Fdev\u002F*\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Ou depuis le back-office : \u003Cstrong>Paramètres avancés → Performances → Vider le cache\u003C\u002Fstrong>.\u003C\u002Fp>\n\u003Ch2>Diagnostic rapide\u003C\u002Fh2>\n\u003Cp>Si votre menu ne s'affiche toujours pas correctement après le correctif, inspectez le HTML généré avec les outils développeur de votre navigateur (F12) :\u003C\u002Fp>\n\u003Col>\n\u003Cli>Vérifiez les classes sur chaque `\u003Cli>` : `dropdown` pour le niveau 2, `dropdown-submenu` pour le niveau 3+.\u003C\u002Fli>\n\u003Cli>Contrôlez que le `\u003Cul>` enfant possède bien la classe `dropdown-menu`.\u003C\u002Fli>\n\u003Cli>Assurez-vous que le JavaScript Bootstrap est chargé (recherchez `dropdown.js` ou `bootstrap.min.js` dans les sources).\u003C\u002Fli>\n\u003Cli>Vérifiez qu'aucun conflit CSS ne masque les sous-menus (`overflow: hidden` sur un parent est un piège fréquent).\u003C\u002Fli>\n\u003C\u002Ful>",[122,125,128,131,134],{"q":123,"a":124},"Pourquoi mon menu PrestaShop affiche les sous-catégories au mauvais endroit ?","Le problème vient généralement de la classe CSS attribuée aux éléments de menu selon leur profondeur. Les catégories de niveau 2 (catégories principales) doivent recevoir la classe 'dropdown' pour ouvrir un menu déroulant vertical, tandis que les catégories de niveau 3 et plus doivent recevoir 'dropdown-submenu' pour s'afficher en panneau latéral. Vérifiez dans le code PHP de votre module de menu que la propriété level_depth est correctement évaluée.",{"q":126,"a":127},"Quelle est la différence entre dropdown et dropdown-submenu dans un menu PrestaShop ?","La classe 'dropdown' déclenche un menu déroulant classique qui s'ouvre verticalement sous l'élément parent — elle s'applique aux catégories de premier niveau visibles dans la barre de navigation. La classe 'dropdown-submenu' déclenche un panneau latéral (flyout) qui s'ouvre à droite ou à gauche d'un menu déjà ouvert — elle s'applique aux sous-catégories imbriquées. Confondre les deux provoque un décalage visuel et une navigation inutilisable.",{"q":129,"a":130},"Comment modifier le menu sans perdre mes changements à la prochaine mise à jour PrestaShop ?","Plutôt que de modifier directement le fichier du module, créez une surcharge (override) dans le dossier \u002Foverride\u002Fmodules\u002F. En PrestaShop 1.6 et 1.7, étendez la classe du module et surchargez uniquement la méthode de génération du menu. En PrestaShop 8.x, vous pouvez également utiliser les décorateurs de service Symfony. Pensez aussi à versionner vos modifications avec Git pour pouvoir les réappliquer facilement.",{"q":132,"a":133},"Le menu fonctionne sur desktop mais pas sur mobile, que faire ?","Les menus déroulants Bootstrap reposent sur l'événement :hover pour afficher les sous-menus, or cet événement n'existe pas sur les appareils tactiles. Vérifiez que votre thème inclut un script JavaScript qui convertit les interactions hover en événements click\u002Ftouch pour les sous-menus. Si ce n'est pas le cas, ajoutez un gestionnaire d'événement tactile ou limitez votre menu à deux niveaux maximum sur mobile.",{"q":135,"a":136},"À quoi correspond level_depth dans les catégories PrestaShop ?","La propriété level_depth d'une catégorie PrestaShop indique sa profondeur dans l'arborescence. Le niveau 1 est la catégorie racine (généralement 'Accueil', invisible en front), le niveau 2 correspond aux catégories principales affichées dans le menu, le niveau 3 aux sous-catégories, et ainsi de suite. Cette valeur est stockée dans la table ps_category et est calculée automatiquement par PrestaShop lors de la création ou du déplacement d'une catégorie.","Un menu PrestaShop qui s'affiche mal est souvent causé par une mauvaise attribution des classes CSS Bootstrap : les catégories de niveau 2 doivent recevoir 'dropdown' (pas 'dropdown-submenu') et seules les catégories de niveau 3+ doivent utiliser 'dropdown-submenu'. Le correctif consiste à distinguer explicitement le level_depth dans le code PHP du module de menu.",5,"2026-03-21T15:03:48.000Z",[],"PrestaShop pour les développeurs",{"items":143},[144,153,159,165,173,181,186,192],{"id":145,"type":146,"label":147,"href":84,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":150,"children":151,"psChildren":152},41,"link",{"fr":148},"Expertise",null,0,[],[],{"id":154,"type":146,"label":155,"href":75,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":156,"children":157,"psChildren":158},42,{"fr":74},1,[],[],{"id":160,"type":146,"label":161,"href":36,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":162,"children":163,"psChildren":164},43,{"fr":35},2,[],[],{"id":166,"type":146,"label":167,"href":169,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":170,"children":171,"psChildren":172},44,{"fr":168},"Outils IA","\u002Foutils-ia",3,[],[],{"id":174,"type":146,"label":175,"href":29,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":177,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":178,"children":179,"psChildren":180},45,{"fr":176},"Offre Starter ✨",{"highlight":20},4,[],[],{"id":182,"type":146,"label":183,"href":78,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":138,"children":184,"psChildren":185},46,{"fr":77},[],[],{"id":187,"type":146,"label":188,"href":96,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":189,"children":190,"psChildren":191},47,{"fr":92},6,[],[],{"id":193,"type":146,"label":194,"href":102,"icon":149,"description":149,"badge":149,"groupTitle":149,"style":149,"gridColumns":149,"cssClass":149,"psCategoryId":149,"showPsChildren":30,"position":195,"children":196,"psChildren":197},48,{"fr":101},7,[],[],{"footer":199},{"theme":200,"description":149,"hours":149,"logo":201,"contact":204,"social":205,"bottomBar":215},"dark",{"src":202,"href":203,"alt":95},"\u002Flogo-ac.svg","\u002F",{"email":149,"phone":149,"address":149,"cta":149},[206,209,212],{"platform":207,"href":208,"label":207},"linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Falexandre-carette\u002F",{"platform":210,"href":211,"label":210},"malt","https:\u002F\u002Fwww.malt.fr\u002Fprofile\u002Falexandrecarette",{"platform":213,"href":214,"label":213},"github","https:\u002F\u002Fgithub.com\u002Fprest4cafe",{"copyright":149},{"academy":217,"blog":218,"expertise":229},[],[219,223,226],{"title":220,"url":221,"score":156,"type":222},"Docker PrestaShop Headless : architecture multi-conteneurs en prod","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fdocker-headless-multi-conteneurs","blog",{"title":224,"url":225,"score":156,"type":222},"PrestaShop headless avec Nuxt 3 : pourquoi séparer back et front","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-separation-front-back",{"title":227,"url":228,"score":156,"type":222},"PrestaShop headless : Nuxt 3, pas Next.js — le choix souverain","\u002Fblog\u002Fprestashop\u002Farchitecture\u002Fprestashop-headless-nuxt-nextjs-souverainete",[],{"header":231},{"logo":232,"topBar":235,"contactEmail":238,"features":239,"navBar":149},{"src":202,"alt":233,"text":95,"href":203,"class":234},"Alexandre Carette — Architecte E-commerce Souverain","h-10 w-10",{"message":149,"showLanguages":30,"align":236,"languages":237},"left",[],"contact@alexandrecarette.fr",{"showSearch":30,"showWishlist":30,"showLogin":20,"showContact":30,"showCart":30,"stickyHeader":20,"headerLayout":240},"inline"]