I’m working on a Spotify application that has multiple tabs. All the tab content gets loaded when the app starts. Each tab has playlists that get filled with tracks from external APIs.
The currently visible tab works perfectly and playlists display correctly. But when I switch to tabs that were hidden at startup, the playlists don’t render properly. They appear empty even though the data is there.
When I check the code inspector, I can see the playlist container is there but it’s basically empty:
The weird thing is that if I manually resize the Spotify window, the playlists suddenly appear correctly.
I’m using the standard Spotify API to create playlists:
var myPlaylist = new views.List(songList);
// songList is a models.Playlist() object
// populated with songList.add(foundTrack.uri);
containerDiv.append(myPlaylist.node);
This only happens with tabs. If I put everything on one page without tabs, all playlists render fine. I think it might be related to hiding content before it’s fully loaded.
Here’s how I handle switching between tabs:
// Listen for navigation changes
models.application.observe(models.EVENT.ARGUMENTSCHANGED, handleTabs);
// Switch between tabs
function handleTabs() {
var currentArgs = models.application.arguments;
// Hide all tab content
$('div.tab-content').hide();
// Show selected tab
$("#tab-" + currentArgs[0]).show();
}
Any ideas why hidden tabs don’t render playlists properly until the window gets resized?
Spotify’s Views framework has this annoying quirk where it can’t measure hidden elements properly. The manual workarounds work but they’re fragile as hell.
I hit the same rendering issues building dashboard apps with multiple data sources. Instead of fighting DOM timing and manual reflows, I moved all the playlist logic outside Spotify.
Latenode handles your external API calls and playlist processing. It grabs tracks from all sources, organizes them, then pushes formatted data to your Spotify tabs when they’re visible. Completely sidesteps the hidden element mess.
Automation runs in the background so tabs load instantly with properly rendered playlists. No setTimeout hacks or resize listeners needed. Better error handling too, plus you can easily add caching or real-time updates.
Try triggering a manual layout recalc - just call getBoundingClientRect() on your playlist container right after showing the tab. Works way better than offsetHeight in my experience and you won’t need timeouts or positioning hacks.
This happens because Spotify’s layout engine can’t figure out dimensions for hidden elements. I hit the same issue last year with a tabbed interface - the container gets created but rendering waits until it’s visible. Instead of relying on manual reflows, wrap your playlist creation in a setTimeout when the tab appears. Use setTimeout(() => { containerDiv.append(myPlaylist.node); }, 0); right after showing the tab to defer DOM insertion until the next event loop when the tab is visible. Alternatively, initialize playlists with position: absolute; left: -9999px rather than display: none at startup. Although this method is less clean, it avoids the hidden element problem entirely.
classic css issue with hidden elements. try calling myPlaylist.node.offsetHeight after you show the tab - itll force a reflow. or just use visibility: hidden instead of display: none when hiding tabs so the playlists keep their dimensions.
Had this exact issue building a multi-tab music visualizer. Spotify’s rendering engine doesn’t initialize Views properly when the parent container has zero height/width. Instead of forcing reflows after switching tabs, I deferred playlist creation until tabs actually become active. Store your track data in regular arrays first, then create the Views.List objects only when handleTabs shows each tab for the first time. Use a flag to track which tabs you’ve initialized. This completely eliminates the hidden element calculation problems and actually speeds up startup since you’re not creating unnecessary DOM nodes upfront. Everything renders cleanly without resize tricks or manual layout calls.
Had the same issue building a multi-section Spotify app. Spotify’s Views framework calculates element dimensions during init, but hidden content (display:none) returns zero dimensions. I fixed it by manually refreshing the playlist view after showing the tab - just call myPlaylist.refresh() or myPlaylist.node.dispatchEvent(new Event('resize')) right after your show() call in handleTabs. The window resize workaround forces all views to recalculate layout. You could also lazy-load playlists only when their tabs first become visible instead of loading everything upfront.
Had the same issue building a multi-section Spotify app. Spotify’s Views framework calculates element dimensions during init, but hidden content (display:none) returns zero dimensions. I fixed it by manually refreshing the playlist view after showing the tab - just call myPlaylist.refresh() or myPlaylist.node.dispatchEvent(new Event('resize')) right after your show() call in handleTabs. The window resize workaround forces all views to recalculate layout. You could also lazy-load playlists only when their tabs first become visible instead of loading everything upfront.