How to Keep Audio Playing While Visitors Move Through Your Site

Lyon, France (CET)

Freelance available

One unbroken toxic lime waveform thread running straight through three chrome doorway frames on deep void black, unchanged as it passes each one, representing audio that survives page navigation.
One unbroken toxic lime waveform thread running straight through three chrome doorway frames on deep void black, unchanged as it passes each one, representing audio that survives page navigation.
One unbroken toxic lime waveform thread running straight through three chrome doorway frames on deep void black, unchanged as it passes each one, representing audio that survives page navigation.

A visitor lands on a producer's portfolio, presses play on a track, and likes it enough to want to see what else is there. They click through to a project page.

The music stops.

That is the entire failure. It lasts half a second, nobody reports it as a bug, and the session that was about to become interesting quietly ends. The visitor came to listen. The site made listening and browsing mutually exclusive, and browsing won.

On an audio-first site this is not a missing feature. It is the difference between a site that plays a track and a site somebody actually listens to.

Why the sound stops

Nothing broke. The browser did what it was told.

A web audio player is a DOM element, and DOM elements do not outlive the thing that contains them. On a traditional multi-page site, following a link replaces the document, and everything in that document goes with it, including the element that was mid-playback.

On a single-page site, which is what a Framer site is, the document survives but the page content does not. Navigation swaps one page subtree for another. If the player is placed inside a page, it unmounts along with that page, and an audio element that unmounts stops.

That produces two distinct problems, and they need separate answers:

  • Keeping the element alive across a page change, so the sound never cuts.

  • Keeping the state that describes what it was doing, so the interface still knows.

Solving one without the other is worse than solving neither. An element that survives while the state resets gives you a site playing music that no visible control admits to.

What persistent actually has to mean

Three properties, in order of how badly they hurt when missing.

Continuity of output. One audio element, created once, never re-created. Not a new element per page that resumes from a stored timestamp. Resuming from a timestamp sounds identical in theory and glitches audibly in practice, because every re-creation reintroduces load and decode latency.

Continuity of state. Current track, position, volume, play or pause. This has to live somewhere that page navigation cannot reach.

Continuity of controls. The interface follows the visitor. A player that keeps playing while its controls disappear on the next page is the worst outcome on this list: audible sound the visitor cannot stop.

Mount the player above the page, not inside it

A single toxic lime playback bar held steady across three stacked deep void page frames that slide past behind it, a thin liquid chrome rule marking the layout it belongs to, representing a player mounted above the page rather than inside it.

The fix is structural, and it happens before any code.

The player has to render outside the subtree that gets swapped on navigation. In Framer that means it belongs on the site layout, the surface that persists across every page, rather than being dropped onto each page as a separate instance. A component that renders into the document body through a portal will hold its position visually, but it still unmounts if the component that created the portal unmounts. Rendering above the page and being placed above the page are two different things, and you need both.

This is also where the most common bug in this whole category comes from.

One owner, always. If the component is placed on each page individually rather than once on the layout, the visitor gets a fresh instance per page. Two instances mean two audio elements, both capable of playing, neither aware of the other. The symptom is a track that doubles slightly out of phase after a couple of navigations, and it is unmistakable once you have heard it. Place the player exactly once and treat every play button elsewhere on the site as a caller, not an owner.

If you are building the component itself rather than placing an existing one, we walked through the Framer-specific mechanics in creating an interactive audio component in Framer.

Keep the state outside the component

Component state is scoped to a component's life. Since the whole point is surviving something that ends component lives, the state has to sit somewhere else: a module-level store created once when the script first evaluates, holding the audio element and everything true about it.

The rule that keeps this clean is a direction rule. Treat the audio element as the source of truth and the interface as a view of it.

That means the UI subscribes to what the element reports, the play and pause and timeupdate and ended events, and renders that. It does not maintain its own idea of whether something is playing and try to keep the element in sync. The moment two records of the same fact exist, they disagree, usually right after the visitor does something fast.

Practically:

  1. Create the element and the store once, at module scope.

  2. Let any mounted UI read from the store and subscribe to element events.

  3. Route every play, pause, seek, and track change through the store's methods.

  4. Let the UI unmount and remount freely. Nothing about playback depends on it.

For the library question underneath all of this, we compared the two usual candidates in Tone.js vs Howler.js. For a straightforward portfolio player, the lighter option is nearly always the right call.

The browser's permission rules still apply

Persistence does not exempt you from autoplay policy. Audio still needs a real user gesture before it may start, and that gesture unlocks the audio context for the session.

The good news is that persistence makes this easier rather than harder. Unlock once, on the first genuine press of play, and every later playback in that session is permitted and instant. The full set of constraints, including decode latency and why sound arrives late on mid-range phones, is in shipping a sound logo on the web without breaking it.

The trap is the other direction. A hard reload, an external link, or a new tab ends the session and takes the permission with it. Do not try to resume playback automatically when the page loads again. It will be blocked on a cold visit, and on a warm one it is worse than blocked, because it works and the visitor did not ask for it.

Restore the track and the position and the paused state. Leave the pressing of play to the person.

What breaks in practice

Back and forward. Browser history navigation follows the same path as a link on a single-page site, so a correctly placed player handles it. Test it anyway. It is the fastest way to catch a player that was quietly placed on a page template.

Multiple triggers. A track list where every row has its own play button is normal and correct, provided each row calls the single owner and reads its playing state back from the store. Rows that hold their own state produce the classic bug of three rows all showing pause at once.

Layout shift. A fixed bar sits over the bottom of the document. Without reserved space, it covers the footer, and on mobile it covers the last item of every list. Reserve the height globally rather than patching it per page.

Mobile browser chrome. The bar has to respect safe areas, and it has to survive the address bar collapsing on scroll. Also worth wiring: the media session metadata, so lock-screen and headphone controls show the track and work as expected. Visitors who put a phone in a pocket expect that.

Performance budget. A persistent player is on every page, so its cost is paid on every page. Keep it small and lazy about what it loads before someone presses play. Optimising audio performance on a site covers the wider picture.

The design commitment nobody mentions

A slim toxic lime bar anchored along the base of a deep void page while stacked rows above it stop short of its edge, chrome guide lines marking the reserved height, representing a persistent player treated as permanent layout furniture.

A persistent player is permanent furniture. It takes a strip of every page for the rest of the site's life, and that is a design decision at least as large as the engineering one.

Four rules we hold to:

  • Fixed height budget, decided once. Somewhere near 64 to 88 pixels on desktop, less on mobile. It does not grow for special cases.

  • Collapsed until earned. Before anything has played, the bar is absent or reduced to a thin resting state. A full transport control for a track nobody selected is noise.

  • Never over a primary action. Check it against the bottom of forms, checkout buttons, and the last row of long lists.

  • Same object, every page. No per-page variants. The point of the pattern is that it reads as one continuous thing.

The reason to be strict is that the bar is the only element on the site a visitor sees on every screen. That makes it the most visible surface you own, which is a good argument for restraint rather than expression. Which patterns actually convert on a music portfolio, and where the bar sits among them, is the subject of portfolio audio players that convert.

Control and accessibility

Persistent audio raises the stakes on control, because the sound now outlives the page the visitor started it on.

Every transport control needs to be reachable and operable by keyboard, with a sensible focus order and a label that says what it does rather than what it looks like. Play and pause state must be announced, not just drawn. Volume and mute preferences should persist across the session, and mute should mean mute across the whole site, not only the current page.

Nothing should ever play on load. The wider ground is covered in building an accessible audio experience, and the short version applies here exactly: audio a visitor cannot control is audio that gets the whole tab muted.

Before you call it shipped

  • Play a track, navigate to three different pages. Does the sound continue without a gap?

  • On each of those pages, does the bar show the correct track, position, and state?

  • Navigate ten times in a row. Is there exactly one audio element, and no doubling?

  • Press back and forward. Same result?

  • Hard reload. Does it restore quietly, paused, without attempting playback?

  • Open the site on a phone. Is the bar clear of safe areas, and do lock-screen controls work?

  • Keyboard only, no mouse. Can you start, pause, and mute?

  • Every page with a footer or a long list. Is anything hidden behind the bar?

FAQ

Does this work on a multi-page site, or only a single-page app?
Only a single-page app, which includes Framer sites. If the document is replaced on navigation, nothing in it survives, and no amount of state management changes that. The workaround on multi-page sites is a persistent frame, which brings enough problems of its own that it is rarely worth it.

Should the player keep playing when the visitor opens a project page with its own audio?
No. Two sources at once is never right. Route the page's player through the same owner, so starting one stops the other automatically. This is the main practical dividend of the single-owner rule.

Is it acceptable to resume playback automatically after a reload?
No. It will be blocked on a cold visit and unwelcome on a warm one. Restore the state and let the visitor press play.

What about visitors who never want site audio at all?
Give them a mute that persists and a resting state that takes almost no space. A persistent player is only defensible when it is completely dismissible.

Does this add much weight to every page?
It should not. The component is small, the metadata is small, and the audio itself should load only when a track is selected. If a persistent player is measurably slowing pages down, the loading strategy is the problem rather than the pattern.

The takeaway

Playback that survives navigation comes down to three decisions, and only one of them is code.

Place the player once, on the layout, so it never unmounts. Keep the element and its state at module scope, with the element as the source of truth. Then design the bar as permanent furniture, because that is what it now is.

The visitor who pressed play was telling you something. Keeping the sound running while they look around is the least you can do about it.

Building this for a client rather than for yourself? It is a build item with a scope and a delivery date, and it belongs on the deliverables list like any other. We covered how to get that paid without a chase in invoicing a sonic branding project.

Category

Interactive Audio Design

date published

Sep 7, 2026

reading time

8 min read

Table of content

Share on X
Share
Share on Linkedin
Share
Share on Facebook
Share

Design made memorable

Portrait of Fab, founder of Supadark
Portrait of Fab, founder of Supadark

I transcend boundaries to create visually stunning, sonic memorable, and strategically impactful solutions. I craft designs that catch the eye and the ear to tell compelling stories.

Try

Framer

Build your website in seconds. Click the button below to create a free Framer account.

© 2026 Supadark. All rights reserved