CSS et JavaScript personnalisés dans PrestaShop sans casser les mises à jour
Dernière mise à jour : juin 2026, les quatre méthodes ci-dessous, sûres lors des mises à jour, s'appliquent de PrestaShop 1.7 à 9 (pipeline SCSS de Hummingbird inclus). Les exemples de code utilisent l'API register* des assets en 1.7+.
Vous modifiez la couleur d'un bouton. Vous ouvrez la feuille de style du thème, vous la modifiez, et le bouton s'affiche correctement. Trois semaines plus tard, vous mettez le thème à jour pour appliquer un correctif de sécurité, et votre modification a disparu, écrasée en silence, sans avertissement ni trace de ce que vous aviez changé. Tout marchand PrestaShop qui personnalise sa boutique en modifiant les fichiers du cœur finit tôt ou tard par se heurter à ce mur, alors que le plus frustrant, c'est que le problème est entièrement évitable. La plateforme vous offre plusieurs emplacements résistants aux mises à jour pour placer votre CSS et votre JavaScript personnalisés ; l'important est de savoir lequel correspond au changement que vous effectuez, et pourquoi « modifier simplement le thème » finit discrètement par échouer. C'est précisément l'objet de ce guide : savoir où placer votre code personnalisé pour qu'une mise à jour du thème, du cœur ou d'un module ne l'efface jamais.
Pourquoi modifier les fichiers du thème ou des modules est un piège
Un thème PrestaShop est un ensemble de fichiers sur le disque : templates Smarty (.tpl), feuilles de style et JavaScript, tous placés sous /themes/your-theme/. Lorsque vous mettez ce thème à jour, que vous téléversiez un nouveau ZIP ou appliquiez un correctif de l'éditeur, le processus de mise à jour remplace ces fichiers en bloc par la nouvelle version. Il ne fusionne pas vos modifications ; il les écrase. C'est la même chose pour chaque module : ses assets se trouvent dans /modules/module-name/views/, et une mise à jour du module remplace entièrement ce répertoire. Pas de diff, pas de confirmation, pas de sauvegarde. Votre travail disparaît tout simplement, et comme aucune erreur n'est affichée, vous ne le remarquez souvent que lorsqu'un client s'en aperçoit.
Qu'est-ce que cela signifie concrètement pour vous ? Chaque heure passée à modifier les fichiers du cœur est une heure que vous devrez repasser à la prochaine mise à jour, et « la prochaine mise à jour » n'est pas facultative, car c'est ainsi que votre boutique reçoit les correctifs de sécurité et de bugs. Tout l'intérêt des méthodes ci-dessous est de briser ce cycle : écrire votre personnalisation une seule fois, à un endroit que le programme de mise à jour ne touche jamais, et arrêter de refaire un travail perdu.
Associer la méthode au changement
Il n'existe pas une seule « bonne » façon d'ajouter du code personnalisé, il existe la bonne façon pour votre changement. Une retouche de couleur sur une ligne et une refonte visuelle complète n'ont rien à faire au même endroit. Choisissez la méthode la plus légère qui survive aux mises à jour et fasse le travail :
| Vous voulez… | Utilisez | Pour qui | Résiste aux mises à jour parce que… |
|---|---|---|---|
| Ajouter quelques règles CSS | Fichier custom.css | Toute personne ayant accès aux fichiers | Il se charge en dernier et gagne donc la cascade (note : il vit dans l'arborescence du thème, il n'est donc pas totalement à l'abri des mises à jour) |
| Effectuer des changements visuels importants et durables | Thème enfant | Designers, agences | Les surcharges vivent dans un thème séparé que la mise à jour du parent ne peut pas atteindre |
| Injecter du code depuis le back-office (sans accès aux fichiers) | Module de blocs HTML/code | Propriétaires de boutique, non-développeurs | Le code est stocké en base de données, indépendamment des fichiers |
| Charger du CSS/JS de façon conditionnelle, comme un pro | Un petit module personnalisé + hooks d'assets | Développeurs | Indépendant du thème ; rien dans l'arborescence du thème ne peut être écrasé |
Les sections ci-dessous couvrent chaque méthode avec des détails propres à PrestaShop. Deux d'entre elles touchent à des sujets qui méritent leurs propres guides, les thèmes enfants et les blocs HTML du back-office, donc plutôt que de répéter ici toute cette profondeur, cet article reste concentré sur le point commun aux quatre méthodes : garder votre code sûr lors des mises à jour.
Méthode 1, le fichier custom.css (pour de petites retouches CSS)
La plupart des thèmes PrestaShop modernes sont livrés avec un fichier custom.css vide que le thème charge après toutes les autres feuilles de style. Comme il se charge en dernier, vos règles gagnent naturellement la cascade, ce qui en fait un endroit pratique pour quelques retouches rapides. Gardez toutefois à l'esprit que custom.css vit généralement dans l'arborescence du thème : il n'est donc pas protégé par nature contre les mises à jour, un ZIP de thème ou une mise à jour de l'éditeur peut le remplacer. Pour une vraie sécurité lors des mises à jour, placez vos règles dans un thème enfant ou un bloc de code du back-office ; réservez le custom.css du thème aux retouches de couleur, d'espacement ou de police que vous pouvez vous permettre de réappliquer.
De nombreux thèmes, y compris les thèmes de style Classic (Classic est le thème par défaut de PrestaShop 8), chargent /themes/your-theme/assets/css/custom.css ; le thème Hummingbird, plus récent, est une autre option moderne. Mais la prise en charge de custom.css et son chemin exact dépendent du thème : ne partez donc pas du principe qu'il s'agit d'un comportement natif universel. Certains thèmes plus anciens ou commerciaux utilisent plutôt /themes/your-theme/css/custom.css, et une minorité ne le déclarent pas du tout. Vérifiez l'enregistrement des assets du thème actif ou sa documentation, et cherchez un custom.css existant (souvent vide) avant de créer le vôtre. Ajoutez-y vos règles, par exemple une surcharge du bouton principal comme .btn-primary { background-color: #2c3e50; border-color: #2c3e50; }, videz le cache, et c'est terminé.
Connaissez ses limites avant de vous appuyer dessus. custom.css, c'est uniquement du CSS, pas de JavaScript. Il se charge sur toutes les pages, que la règle y soit nécessaire ou non, et il ne vous donne aucun moyen de cibler un type de page, un groupe de clients ou une boutique spécifique. Et une minorité de thèmes ne le déclarent pas du tout. Pour quelques retouches, ces limites n'ont pas d'importance ; dès qu'elles commencent à compter, passez à l'une des méthodes ci-dessous.
Méthode 2, un thème enfant (pour une personnalisation importante et durable)
Lorsque vous faites plus que quelques changements, modification de templates, restylage de sections entières, ajout de votre propre JavaScript, un thème enfant est l'emplacement sûr lors des mises à jour pour tout cela. Un thème enfant hérite de tout ce qui vient de son parent et vous permet de surcharger uniquement les fichiers précis qui vous intéressent, dans un répertoire séparé que les mises à jour du parent ne peuvent pas atteindre. Vous pointez un config/theme.yml vers le parent (sa clé parent: nomme le dossier du thème parent), vous copiez seulement les fichiers que vous surchargez, puis vous ajoutez vos propres custom.css et .js à côté.
C'est la bonne réponse pour une personnalisation sérieuse, et le sujet mérite mieux qu'un paragraphe expédié. Y compris la raison essentielle pour laquelle il faut en créer un au lieu de modifier directement le parent. Nous l'avons traité en détail dans les thèmes enfants dans PrestaShop : pourquoi vous ne devriez jamais modifier le thème parent. Si vous n'avez pas encore choisi le thème à personnaliser, commencez une étape plus tôt avec comment choisir le bon thème PrestaShop pour votre entreprise, un thème parent adapté aux thèmes enfants vous évitera beaucoup de complications par la suite.
Méthode 3, injecter du code depuis le back-office (sans accès aux fichiers)

Les blocs du back-office gardent les petits extraits HTML, CSS et JavaScript en dehors des fichiers du thème.
Si vous n'avez pas d'accès SSH ou FTP, si vous n'en voulez pas, ou si vous ne voulez simplement pas redéployer des fichiers pour un extrait de suivi d'une ligne, un module de blocs de code vous permet d'ajouter du CSS, du JavaScript et du HTML personnalisés directement depuis le back-office PrestaShop. Le code vit dans la base de données plutôt que dans un fichier de thème ou de module, ce qui explique précisément pourquoi une mise à jour du thème ou du cœur ne peut pas y toucher, et pourquoi vous pouvez désactiver un bloc pour annuler son effet instantanément, sans rien supprimer.
C'est l'outil du quotidien pour ajouter un script Google Analytics ou Meta Pixel, placer une surcharge CSS saisonnière dans l'en-tête de la page, ou afficher une bannière promotionnelle, et cela mérite son propre guide plutôt qu'un simple paragraphe ici. Nous détaillons la démarche dans blocs HTML : ajouter du contenu personnalisé n'importe où dans votre boutique PrestaShop, qui explique comment affecter les blocs aux hooks et les afficher uniquement sur les pages ou pour les groupes de clients de votre choix. Notre module mprhtmlblocks a été conçu exactement pour cela : du code personnalisé, géré depuis le back-office, ciblé par hook et affiché sous conditions, sans rien que la prochaine mise à jour puisse écraser.
Méthode 4, un petit module personnalisé avec des hooks d'assets (pour les développeurs)
Pour les développeurs, l'emplacement le plus propre et le plus contrôlable pour des assets personnalisés est un petit module qui les enregistre via le pipeline d'assets natif de PrestaShop. Il est totalement indépendant du thème, rien dans l'arborescence du thème ne peut être écrasé, il survit donc aussi bien aux changements de thème qu'aux mises à jour du cœur, et il débloque un chargement conditionnel impossible avec custom.css.
Le travail se fait dans un seul hook, hookActionFrontControllerSetMedia(). À l'intérieur, vous appelez registerStylesheet() et registerJavascript() sur le contrôleur, en passant un identifiant d'asset, le chemin sous votre module et un tableau d'options. Ces options sont le vrai gain par rapport aux anciens appels addCSS() / addJS() de l'époque 1.6 : une priority (les nombres plus élevés se chargent plus tard, ce qui vous permet de garantir que votre script s'exécute après celui du thème), une requête media, une position JS à bottom, et les attributs async/defer. Sur PrestaShop 1.7 et versions supérieures, privilégiez les méthodes register* ; utilisez addCSS/addJS uniquement si vous maintenez une boutique en 1.6.
public function install()
{
return parent::install()
&& $this->registerHook('actionFrontControllerSetMedia');
}
public function hookActionFrontControllerSetMedia($params)
{
if (!$this->context->controller instanceof ProductController) {
return;
}
$this->context->controller->registerStylesheet(
'module-' . $this->name . '-product',
'modules/' . $this->name . '/views/css/product.css',
['media' => 'all', 'priority' => 200]
);
$this->context->controller->registerJavascript(
'module-' . $this->name . '-product',
'modules/' . $this->name . '/views/js/product.js',
['position' => 'bottom', 'priority' => 200]
);
}
Le bug de chaîne de requête addCSS à connaître
Il existe un piège ancien avec addCSS() : lorsqu'on lui passe une chaîne de requête de contournement du cache (du type ?v=1.2.3), PrestaShop peut produire un chemin qu'il déforme ensuite, si bien que la feuille de style apparaît dans le code source de la page mais que le navigateur ne l'applique jamais. C'est exaspérant à déboguer, car rien ne renvoie de 404. Si vous versionnez vos assets pour contourner le cache, utilisez registerStylesheet(), qui gère correctement la version.
Chargement conditionnel, uniquement là où c'est nécessaire
La vraie raison pour laquelle les développeurs se tournent vers un module, c'est le chargement conditionnel. Dans le même hook, vous pouvez inspecter $this->context->controller et n'enregistrer les assets que lorsqu'il correspond, par exemple en vérifiant instanceof ProductController avant d'ajouter du CSS de page produit, ou instanceof OrderController avant d'ajouter du JavaScript de commande. Le bénéfice est concret : votre code personnalisé reste absent des 90 % de pages qui n'en ont pas besoin, donc vous ne le payez pas dans le temps de chargement de chaque page. Ce même principe. Charger léger, charger tard. Est ce qui permet de garder une boutique personnalisée rapide, et c'est l'esprit derrière les petites touches front-end comme un bouton retour en haut, livrées sous forme d'assets conditionnels propres plutôt que comme un script inline déposé dans un template.
JavaScript demande plus d'attention que CSS
Le CSS se défend rarement ; JavaScript, si. Deux choses causent la plupart des problèmes. D'abord, jQuery : PrestaShop 1.7+ embarque jQuery 3.x sur le front-office, donc si votre script dépend de jQuery, donnez-lui une priorité suffisamment élevée pour qu'il se charge après jQuery, sinon vous verrez "$ is not defined" au premier rendu. Le back-office est un monde à part (les anciennes versions embarquaient jQuery 1.x, les plus récentes 3.x), donc vérifiez le code source de la page avant d'écrire un script d'administration en supposant une version.
Deuxièmement, et c'est la règle que l'on a le plus envie d'enfreindre : ne mettez jamais une balise <script> brute dans un template Smarty. Cela semble rapide, mais un script inline contourne la gestion des assets de PrestaShop. Il ne sera ni géré ni combiné par CCC (Combine, Compress, Cache), et il peut entrer en conflit avec la Content Security Policy des boutiques qui définissent un en-tête CSP. Livrez toujours le JavaScript sous forme de fichier .js externe enregistré via le hook approprié. Quant à la syntaxe moderne, fonctions fléchées, async/await, modules ES, elle convient très bien à PrestaShop 8 et 9, où IE11 n'est plus un sujet ; si vous supportez encore des boutiques 1.7 avec du trafic provenant d'anciens navigateurs, vous devrez peut-être transpiler avec Babel.
Quand le CSS personnalisé « ne fonctionne pas » : la spécificité
La situation la plus courante où « mon CSS personnalisé est ignoré » n'est pas du tout un problème de mise à jour, c'est un problème de spécificité. Votre règle se charge bien, mais le sélecteur du thème est plus spécifique, donc le navigateur applique celui du thème. La solution, par ordre de préférence :
- Reprendre le sélecteur du thème. Ouvrez les outils de développement, trouvez le sélecteur exact utilisé par le thème, puis écrivez le vôtre pour le faire correspondre. Comme custom.css se charge en dernier, un sélecteur de spécificité équivalente gagne déjà.
- Ajouter un parent pour donner du poids. Si la correspondance ne suffit pas, ajoutez un scope, #wrapper .btn-primary bat un simple .btn-primary sans recourir à la force brute.
- Utiliser !important seulement en tout dernier recours réel. Cela fonctionne, mais chaque !important que vous ajoutez rend la prochaine surcharge plus difficile, et vous finissez dans une course à la spécificité que votre vous du futur devra démêler.
Tests : pourquoi « j'ai changé quelque chose et rien ne s'est passé »
Des changements CSS et JS personnalisés qui semblent ne rien faire viennent presque toujours d'une couche de cache, pas de votre code. Procédez dans cet ordre :
- Videz le cache PrestaShop. Allez dans Paramètres avancés → Performances et cliquez sur Vider le cache après chaque changement. Pendant le développement de templates, activez Forcer la compilation sur Oui afin que Smarty régénère les pages.
- Méfiez-vous de CCC. Lorsque Combine, Compress, Cache est activé, vos fichiers individuels sont fusionnés en bundles, ce qui peut modifier l'ordre de chargement. Si un comportement paraît étrange, désactivez temporairement CCC pour l'isoler, puis réactivez-le en production.
- Utilisez le navigateur. L'onglet Réseau confirme que votre fichier a bien été chargé (200, pas 404) ; l'onglet Éléments montre si votre règle est appliquée ou barrée par une règle plus spécifique.
- Purgez le CDN. Si vous utilisez Cloudflare ou un autre CDN, purgez-le après les changements d'assets, les copies obsolètes en périphérie expliquent une énorme part des « mais j'ai déjà changé ça ».
La version courte
- Ne modifiez jamais directement les fichiers du thème ou des modules, la prochaine mise à jour les écrasera sans avertissement.
- 1 à 5 petites retouches CSS : placez-les dans custom.css.
- Changements importants et durables : créez un thème enfant.
- Pas d'accès aux fichiers, ou extraits rapides : utilisez un bloc HTML/code du back-office.
- Développeur, chargement conditionnel : un petit module avec registerStylesheet() / registerJavascript().
- Livrez le JS sous forme de fichiers externes, chargez-le en bas de page, videz tous les caches après les changements et gardez vos personnalisations sauvegardées en dehors du répertoire du thème.
Personnaliser PrestaShop et survivre aux mises à jour ne sont pas deux objectifs opposés. Ils en ont seulement l'air lorsque votre code vit au mauvais endroit. Choisissez la méthode la plus légère et sûre lors des mises à jour pour le changement que vous avez sous les yeux, et une mise à jour de thème redevient ce qu'elle devrait être : un clic de routine, pas une journée à réappliquer un travail perdu. Si vous préférez gérer du code personnalisé depuis le back-office plutôt que toucher aux fichiers, notre module mprhtmlblocks vous permet d'injecter et d'activer/désactiver des blocs HTML, CSS et JavaScript bloc par bloc, stockés en base de données, intouchables par la prochaine mise à jour.
Questions fréquentes
Le fichier custom.css du thème est-il vraiment protégé contre les mises à jour ?
Pas totalement. Comme custom.css vit généralement dans l'arborescence du thème, un ZIP de thème ou une mise à jour de l'éditeur peut le remplacer avec tout le reste. Il est pratique, il se charge en dernier, donc vos règles gagnent la cascade, mais considérez-le comme l'endroit des retouches jetables que vous pouvez vous permettre de réappliquer. Pour une vraie sécurité lors des mises à jour, placez les règles dans un thème enfant ou un bloc de code du back-office, là où le programme de mise à jour ne peut pas les atteindre.
Mon CSS personnalisé se charge, mais le style du thème gagne encore. Qu'est-ce qui ne va pas ?
C'est un problème de spécificité, pas de mise à jour ni de cache. Le sélecteur du thème est plus spécifique que le vôtre, donc le navigateur applique celui du thème. Ouvrez les outils de développement, trouvez le sélecteur exact utilisé par le thème, puis écrivez le vôtre pour le faire correspondre, comme custom.css se charge en dernier, un sélecteur équivalent gagne déjà. Ajoutez un parent de scope comme #wrapper uniquement si la correspondance ne suffit pas, et utilisez !important seulement en tout dernier recours réel.
Puis-je simplement coller une balise <script> dans un template ?
Non. Un script inline contourne la gestion des assets de PrestaShop, il ne sera donc pas combiné par CCC, et il peut casser sur les boutiques qui définissent un en-tête Content Security Policy. Livrez toujours le JavaScript comme un fichier .js externe enregistré via hookActionFrontControllerSetMedia() avec registerJavascript(), ou via un bloc de code du back-office, jamais comme du balisage brut dans un .tpl.
Comment charger mon CSS ou mon JS uniquement sur certaines pages ?
C'est la principale raison d'utiliser un petit module au lieu de custom.css. Dans hookActionFrontControllerSetMedia(), inspectez $this->context->controller et n'enregistrez l'asset que lorsqu'il correspond, par exemple instanceof ProductController pour le CSS de page produit, ou instanceof OrderController pour le JS du tunnel de commande. Votre code reste alors absent des pages qui n'en ont pas besoin, et vous ne le payez pas à chaque chargement de page.
Pourquoi mon script affiche-t-il "$ is not defined" ?
Votre JavaScript s'exécute avant que jQuery soit chargé. PrestaShop 1.7+ embarque jQuery 3.x sur le front-office, donc donnez à votre script une priority suffisamment élevée dans registerJavascript() pour qu'il se charge après jQuery. Le back-office est un monde séparé, les anciennes versions embarquaient jQuery 1.x, donc vérifiez le code source de la page avant d'écrire un script d'administration en supposant une version.
J'ai changé mon CSS et rien ne s'est passé. Où dois-je regarder ?
Presque toujours du côté d'une couche de cache, pas de votre code. Procédez dans l'ordre : videz le cache PrestaShop sous Paramètres avancés → Performances ; désactivez temporairement CCC (Combine, Compress, Cache) si l'ordre de chargement semble incorrect ; confirmez dans l'onglet Réseau du navigateur que votre fichier s'est chargé en 200, pas en 404 ; et purgez votre CDN (Cloudflare et autres), les copies obsolètes en périphérie causent une énorme part des « mais j'ai déjà changé ça ».
Dois-je encore utiliser addCSS() et addJS() ?
Uniquement sur une boutique en 1.6. Sur PrestaShop 1.7 et versions supérieures, privilégiez registerStylesheet() et registerJavascript(), ils vous donnent la priorité, les media queries, une position JS en bas de page et async/defer, et ils gèrent correctement le versionnement de contournement du cache. L'ancien addCSS() a un bug ancien : une chaîne de requête ?v= peut déformer le chemin, si bien que le fichier apparaît dans la source mais ne s'applique jamais, sans 404 pour vous mettre sur la piste.
Commentaires
Laisser un commentaire
Partagez une question, un détail de pose ou un retour qui pourrait aider un autre lecteur.