| name | wall-of-sound |
| description | Use when the user wants a wall of album covers, an image wall, a covers grid, or any square art drifting slowly in the background of a site. Includes collecting their saved albums from Spotify and building the wall from them. The wall goes behind whatever front the site already has; a frosted panel is the default when the site has none. |
Wall of Sound
A full-viewport background of square images (album covers, posters, any square art) in columns that drift very slowly in alternating directions, behind whatever front the page already has. When the site has no front of its own, the default treatment is a centered frosted panel holding the content, which is what the demo uses.
The usual source is the user's saved albums on Spotify, collected in Step 0. Any square-image source works the same way.
When to use this
Common asks: "create my personal wall of sound," "make a wall out of my saved albums," "put my Spotify covers behind my site," "make a drifting poster wall," "an image grid that slowly moves in the background." Not for hero carousels, foreground galleries, or anywhere the images are the content rather than the atmosphere.
Step 0: collect the covers
If the user already has a list of images (shape and count guidance in reference/data-format.md), skip ahead. Otherwise collect their saved albums; this needs browser tooling, and without it, ask the user for an albums.json instead.
- Open open.spotify.com yourself, go to Your Library, and switch to the Albums view. Involve the user only if Spotify shows a logged-out page.
- Collect each album's artist, title, and cover URL as you scroll: the list is virtualized and rows unmount once they leave the view. Scroll with real wheel or trackpad events; setting
scrollTop moves the bar without rendering any rows, and the scroll appears to complete while you silently miss most of the library. Use overlapping increments, dedupe on the 24-character image id, and stop when the scroll stops advancing.
- Each cover URL yields both size variants without a second request; the rule is in
reference/data-format.md.
- Write
albums.json in the documented shape, next to the page that will fetch it. Spotify shows no album count, so derive the expected total from the library grid's aria-rowcount and aria-colcount (minus the empty slots in the last row) and compare; a shortfall means the scroll dropped rows.
Put the wall in
- Add as first children of
<body>: <div class="wall" id="wall" aria-hidden="true"></div> and <div class="scrim" aria-hidden="true"></div>. The id is required; the JS finds the container by id.
- Add the CSS from
reference/wall.css: everything above the DEFAULT PANEL TREATMENT banner always, what is below it only when the site has no front of its own (on a site that has one, it restyles typography and resets the box model). Keep --col-w and --gap through any retune; the JS probe reads them. If the site already uses any of the wall class names, prefix them all and update the strings in wall.js, including the one in the visibilitychange handler.
- Lift the site's front above the wall and make it see-through: the wall is
z-index: 0 and the scrim z-index: 1, both fixed, so the content wrapper needs position: relative; z-index: 2 (the default .page already has it). Any opaque background in the front hides the wall completely, so make the surfaces that should show it translucent; .panel's semi-opaque background plus backdrop blur is the pattern.
- Add the JS from
reference/wall.js and keep exactly one of its two call sites, inline data or fetch; the file's comments cover the mapping and the timing.
- Check it live: the drift barely perceptible, text readable over the busiest covers (the scrim comment in
wall.css has a light-wash variant for dark-text fronts), a full freeze under reduced motion.
The default panel front
Wrap the content in .page > .panel > main and add the DEFAULT PANEL TREATMENT rules from wall.css. Styling for the content inside main is the site's own to write.
Adjusting it
Anything marked tunable in the reference-file comments is safe to retune per site. Two rules hold through any retune: animate transform only (anything that triggers layout or paint turns the wall into jank), and space tiles with margin-bottom on the tile, never flex gap on the track (the why is at the rule in wall.css). Drift speed is the biggest lever on the mood; keep it slow, on mobile too. The rest of the quality behavior (lazy tiles, aria-hidden, the tab-hidden pause, the reduced-motion freeze) ships in the reference files; keep it.