Updated June 2026, implementation notes apply to PrestaShop 1.7, 8 and 9. The default Classic theme still ships no back-to-top button; the code below is vanilla JS with a 44px mobile tap target.

The back-to-top button is the kind of detail nobody notices until it's missing, a small arrow in the corner that floats a customer back to your header after they've scrolled to the bottom of a long page. It feels too minor to think about. But on a PrestaShop store, where category and product pages routinely run several thousand pixels tall, the difference between having one and not having one is the difference between a customer being one tap from your search bar and a customer thumb-scrolling a phone screen until they give up. This post is about getting that button onto your store the right way on PrestaShop specifically: where it lives in the theme, how to add it without forking files you'll regret at the next update, and the handful of mistakes that turn a helpful button into a thing that covers your "Add to cart".

If you want the case for why the button moves the needle, the engagement data, the abandonment angle, we made that argument in scroll to top button: small UX improvement, surprising impact. Here we're staying on the practical side: implementation, PrestaShop mechanics, and the decisions that make or break it.

Does your theme already have one? Check before you build

The first PrestaShop-specific thing to know: many modern themes already ship a back-to-top button, and you may be about to add a second one. The default Classic theme on PrestaShop 1.7, 8 and 9 does not include one out of the box, so a stock Classic install needs it added. But most paid themes (and Warehouse-derived themes) do, usually toggled in the theme's own configuration page under Design → Theme & Logo or inside the theme's settings module. Before writing a line of code, scroll to the bottom of a long category page on your live store and watch the corner. If a button already fades in, your job is configuration, not construction.

To confirm where an existing button comes from, view source and search for common markers: a #back-to-top or .scroll-to-top element, or a template fragment in your theme under themes/<yourtheme>/templates/ (often in _partials/footer.tpl or a dedicated scroll-top.tpl). If it's there but not appearing, the theme option is simply switched off. That's a back-office checkbox, not a developer ticket.

The three ways to add one to PrestaShop, and which to pick

If your theme genuinely doesn't have a back-to-top button, you have three realistic routes. They differ mostly in one thing that matters more than convenience on PrestaShop: whether your change survives a theme or core update.

RouteWhere it livesSurvives updates?Best when…
Theme optionTheme settings, no codeYes (it's the theme's own feature)Your theme already includes it, just enable it.
HTML/JS block moduleA custom HTML/module block on a supported hook (e.g. displayFooter)Yes. Nothing in the theme is editedYou want it on a stock theme without touching theme files.
custom.js / custom.cssTheme's own assets/js/custom.jsMostly, but it's tied to that themeYou're comfortable in the theme's asset files and want full control.
Editing footer.tpl directlyParent theme templateNo, overwritten on theme updateNever. Use a child theme instead (see below).

The route to avoid is the tempting one: opening footer.tpl in your active theme and pasting markup in. It works for exactly as long as it takes the theme author to ship an update, at which point your edit is gone and you don't know why. If you must touch templates, do it in a child theme. We explain why that rule is non-negotiable in child themes: why you should never edit the parent theme. For the cleaner no-template-editing approaches, read on.

The clean route: a custom HTML block plus a few lines of JS

The approach that keeps your hands off theme files is to inject the button's markup through an HTML content block and load its behaviour through the theme's custom.js. the Classic theme includes themes/<yourtheme>/assets/js/custom.js (and custom.css alongside it) for site-wide JavaScript. Be aware, though, that whether these files exist and how they behave on update is theme-dependent. Editing them in the active parent theme is still editing theme files, and a theme update can overwrite them unless the theme or vendor preserves them. For genuine update safety, prefer a child theme or assets registered through a module. The full discipline around using them safely, and why they beat editing the compiled theme bundles. Is in custom CSS and JavaScript in PrestaShop without breaking updates.

For the markup itself, you don't want to hardcode a <div> into a template. A dedicated custom HTML/module block dropped into the footer area does the job, use one that supports the target hook (for a footer-anchored button, a module hooking displayFooter or displayBeforeBodyClosingTag), or build a small module of your own. Bear in mind markup can only be injected into hooks a module supports and that the theme actually renders, not literally anywhere on the store. The mechanics of placing custom blocks are covered in HTML blocks: adding custom content anywhere in your PrestaShop store. The button is just an accessible anchor or button element; the JavaScript handles when it appears and the smooth scroll.

A minimal, accessible implementation is genuinely about fifteen lines. It is not a performance concern, and it should be vanilla JS (the Classic theme still bundles jQuery, but relying on it is fragile, many lighter third-party themes drop or defer it, so don't assume $() is available):

  • Markup: a real <button type="button" id="back-to-top" aria-label="Back to top"> with an arrow glyph or SVG inside, never a bare <div>, because a div isn't focusable or announced to screen readers.
  • Show after scrolling: a scroll listener that adds a visible class once window.scrollY passes roughly 300–500px (about one viewport). Throttle the listener so it doesn't fire on every pixel.
  • Smooth return: window.scrollTo({ top: 0, behavior: 'smooth' }) on click, one line, native, no animation library.

Here's the whole thing, markup, throttled show/hide, and the native smooth scroll. It's vanilla, depends on nothing, and honours the visitor's motion preference:

<!-- markup: a real button, focusable and announced -->
<button type="button" id="back-to-top" aria-label="Back to top"></button>
#back-to-top {
  position: fixed;
  right: 1rem;
  bottom: 1rem;           /* raise this if a cookie bar / chat sits here */
  width: 48px;
  height: 48px;          /* 44px+ tap target on mobile */
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease;
  z-index: 1030;       /* deliberate, below banner/chat – test it */
}
#back-to-top.is-visible { opacity: 1; visibility: visible; }
const btn = document.getElementById('back-to-top');
let ticking = false;

window.addEventListener('scroll', () => {
  if (ticking) return;            // throttle to one check per frame
  ticking = true;
  window.requestAnimationFrame(() => {
    btn.classList.toggle('is-visible', window.scrollY > 400);
    ticking = false;
  });
}, { passive: true });

btn.addEventListener('click', () => {
  const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  window.scrollTo({ top: 0, behavior: reduce ? 'auto' : 'smooth' });
});

The passive: true on the scroll listener and the requestAnimationFrame throttle are the two details that keep this off your store's main thread; the reduced-motion check on click is the accessibility courtesy that costs one line. Register that JS as an external file through a module hook rather than pasting it inline.

Wrapping this in a small purpose-built module rather than loose files has one advantage worth naming: it travels with you across stores and isn't tied to a single theme's lifecycle. That's the same reasoning behind doing scroll animations as a managed layer rather than scattered inline scripts. The button and subtle scroll motion are siblings in the same "frontend polish that shouldn't fork your theme" family.

The PrestaShop-specific gotchas that actually bite

A circular back-to-top button with an upward arrow in the bottom-right corner of a storefront product page

A circular back-to-top button sits in the bottom-right corner of a storefront product page.

The button itself is trivial. What breaks on real PrestaShop stores is everything it shares the bottom-right corner with. PrestaShop installs accumulate floating widgets, and they all want the same real estate.

  • Cookie consent and GDPR banners. The consent and cookie-law modules common on PrestaShop stores, whether a legal-compliance add-on or a third-party CMP, typically dock to the bottom of the viewport. A back-to-top button that ignores them ends up either hidden behind the banner or sitting on top of the "Accept" button. Position the button bottom-right and give the banner the full-width bottom strip, or raise the button above the banner's height while it's showing.
  • Live-chat widgets (Crisp, Messenger, tawk.to). These almost universally pin to bottom-right, exactly where the back-to-top convention says the button belongs. Don't fight it: stack the button above the chat bubble with extra bottom offset, so a customer never has to choose between "talk to us" and "go to top."
  • The z-index stacking war. This is the single most common defect. Chat widgets and consent modules often set very high z-index values, and your button can end up rendered underneath them. Visible but unclickable, which is worse than absent. Set a deliberate z-index and test by actually clicking the button on mobile with the cookie banner and chat both live, not on a clean staging page where neither exists.
  • Sticky headers change the calculus. Many PrestaShop themes (and the sticky-header options in paid themes) keep navigation, search and cart pinned to the top as the customer scrolls. If yours does, the button is less essential, search and cart are already reachable, but it still earns its place for jumping back to the hero, the filters at the top of a category, or the top of a long blog post. On a sticky-header theme, make the button a touch smaller and quieter; it's a convenience, not a lifeline.

Where it earns its keep on a PrestaShop store

Not every page needs it equally. The button pays off most exactly where PrestaShop pages get longest, and it's worth knowing which those are so you can sanity-check it where it matters:

  • Mobile, above all. The smaller viewport means more scrolling for the same content, so a phone user travels far more screen-lengths than a desktop user on the identical category page. If you only get the button right on one device, get it right on mobile, and respect the 44–48px minimum tap target there.
  • Long category pages with 30+ products, faceted-search filters, infinite scroll or deep pagination. After a customer reaches product #35, the header genuinely is thousands of pixels away.
  • Content-heavy product pages with long descriptions, specification tables, reviews and cross-sell carousels, these routinely clear 5,000px.
  • Blog and CMS pages. Your static and editorial content often has the deepest scroll on the whole site. While you're improving those pages, CMS navigation itself is worth tidying. Clearer menu labels for static pages help customers who do scroll back to the top actually find where to go next, which we cover in CMS page display names: better navigation for your static pages.

Getting the behaviour right

Whichever route you take, the same small details separate a button that feels native from one that feels bolted on:

  • Appear only after scrolling. Showing it at the top of the page is meaningless clutter. Reveal it once the customer has scrolled past roughly one viewport.
  • Smooth scroll, not a teleport. An instant jump to the top is disorienting, the customer can't tell whether they scrolled or landed on a new page. A 300–500ms smooth scroll preserves their spatial sense.
  • Fade, don't bounce. A subtle ~200ms fade in and out reads as polished. Bouncing, sliding or pulsing animations pull attention the button doesn't deserve; it should be discoverable, not distracting.
  • Accessible by construction. A real <button> or <a> (focusable and announced), an aria-label, a visible keyboard focus ring, and enough contrast against whatever page background it floats over. These cost nothing to get right at build time and are painful to retrofit.

Should you measure it?

You can, and on a busy store it's worth a few minutes: fire an analytics event on each button click. That tells you what share of sessions on long pages actually use it, and which pages generate the most clicks. Usually a useful flag for "these are my deepest, most-engaged pages." Treat any percentage you read elsewhere as directional, not a target; the honest number depends entirely on how long your pages are and how your customers behave, so read it off your own store rather than trusting a blog figure.

The back-to-top button is a rare thing in store UX: an almost zero-downside improvement. It costs a few lines, uses negligible resources, helps the customers who need it, and stays invisible to the ones who don't. The only way to get it wrong on PrestaShop is to bolt it on carelessly, editing the parent theme so it vanishes at the next update, or dropping it into a corner already claimed by your cookie banner and chat widget. Add it the clean way, in a place that survives updates, and test it where the floating widgets actually live. Then forget about it, which is exactly what a good UX detail is supposed to let you do.

Frequently asked questions

Does PrestaShop's default theme include a back-to-top button?

No. The Classic theme on PrestaShop 1.7, 8 and 9 ships without one, so a stock Classic install needs it added. Many paid and Warehouse-derived themes do include one, usually toggled in the theme's own settings. Before building anything, scroll to the bottom of a long category page on your live store, if a button already fades in, your job is flipping a back-office checkbox, not writing code.

What's the cleanest way to add one without breaking updates?

Put the markup in a back-office HTML block on a footer hook like displayFooter or displayBeforeBodyClosingTag, and register the JavaScript as an external file through a small module. Nothing in the theme tree gets edited, so a theme update can't wipe it. Editing footer.tpl in the active parent theme is the route to avoid; if you must touch templates, do it in a child theme.

Should I use jQuery for the scroll logic?

No, write it in vanilla JavaScript. The Classic theme still bundles jQuery, but many lighter third-party themes drop or defer it, so you can't assume $() is available. The whole button is about fifteen lines of plain JS: a throttled scroll listener that toggles a visibility class past ~400px, and window.scrollTo({ top: 0, behavior: 'smooth' }) on click. No library needed.

My button is visible but I can't click it. Why?

That's the most common defect, a z-index stacking clash. Chat widgets and consent banners often set very high z-index values, so your button renders underneath them: visible but unclickable, which is worse than absent. Set a deliberate z-index and test by actually clicking on mobile with the cookie banner and chat both live, not on a clean staging page where neither exists.

All three want the bottom-right corner. Give the consent banner the full-width bottom strip and keep the button in the corner, or raise the button's bottom offset while the banner is showing. For a chat bubble, stack the button above it with extra offset so a customer never has to choose between "talk to us" and "go to top." Always verify with both widgets live.

At what scroll distance should the button appear?

Roughly one viewport, about 300–500px down. Showing it at the very top of the page is meaningless clutter; revealing it only after the customer has scrolled is what makes it feel intentional. Throttle the scroll listener (a requestAnimationFrame guard plus a passive listener) so the check runs at most once per frame and stays off the main thread.

Does it need to be accessible, and how?

Yes, and it's cheap to get right at build time. Use a real <button> or <a> rather than a styled <div> so it's focusable and announced, add an aria-label="Back to top", keep a visible keyboard focus ring, ensure enough contrast against the page background, and respect prefers-reduced-motion by falling back to an instant jump. Retrofitting these later is far more painful than including them from the start.

Is the button still worth it if my theme has a sticky header?

It's less essential but still useful. A sticky header keeps search and cart reachable, so the button isn't a lifeline, but it still helps a customer jump back to the hero, the filters at the top of a category, or the top of a long blog post. On a sticky-header theme, make the button a touch smaller and quieter so it reads as a convenience rather than a competing fixed element.

Tags: PrestaShop UX
Share this post:
David Miller

David Miller

Founder, mypresta.rocks

David Miller is a PrestaShop specialist with over a decade of hands-on experience and the founder of mypresta.rocks, a software studio in Tychy, Poland. He builds and maintains a catalogue of 152 PrestaShop modules, including 21 "Revolution" suites spanning SEO, checkout, security, performance, marketing, search, support, and warehouse operations, that improve real stores every day, all tested against PrestaShop 1.7.8, 8.x, and 9.x. He also acts as caretaker for production stores turning over millions in annual sales, so his work is judged on live revenue, not demos. His experience runs the full breadth of ecommerce, performance, security, SEO, and marketing, and reaches beyond PrestaShop to WooCommerce, Shopify, and custom-built systems. On the blog he writes about the code-aware side of PrestaShop: what the platform really does under the hood, what breaks in production, and which fixes hold up.

Comments

No comments yet. Be the first!
Enjoyed this article?

Get our latest tips, guides and module updates delivered to your inbox.

You may unsubscribe at any moment. For that purpose, please find our contact info in the legal notice.

Loading...
Back to top