Scroll position not maintained in CMS List when using Filter/Load

When I click on a CMS item and go to its page, then click back to the collection page using the browser back button, the scroll position isn’t being maintained.

When I delete all the Finsweet Attributes code, it actually works fine. bfcache works as expected.

But soon as the CMS Filter/Load code is re-introduced, nada.

Actually it does work on page 1 and on Safari Desktop/Chrome iPhone. But crucially not on Chrome Desktop or Firefox.

I’ve tried a bunch of stuff like trying to store the scroll position but nothing has worked.

I’m going to have 1000s of items in the collection list so this is really important for the UX of the site.

Would really appreciate a fix! Here’s the site:

https://preview.webflow.com/preview/great-ads?utm_medium=preview_link&utm_source=designer&utm_content=great-ads&preview=439cc7004d36950d559620c6ca522aa2&workflow=preview

Hey @v11! Is the issue still present? I am testing on Chrome Desktop and I am scrolled to the item location when going back from the item page

Hey @Support-Luis, thanks for checking it out. No, still not working for me on Chrome or Firefox. Are you scrolling beyond page 1, because it does maintain position for items on page 1 only?

Yes, this worked yesterday but not today. Can you share how were you storing the scroll position before?

@Support-Luis Just to be clear the code to store the scroll position wasn’t enabled yesterday. I tried it last week.

I was saving the Scroll position to session storage then retrieving it. I got help from GPT4 but it was something along the lines of:

// Save the scroll position before navigating away.
window.addEventListener(‘beforeunload’, function() {
sessionStorage.setItem(‘scrollPosition’, window.scrollY.toString());
});

// Restore the scroll position when the page loads.
window.addEventListener(‘DOMContentLoaded’, function() {
const savedScrollPosition = sessionStorage.getItem(‘scrollPosition’);

if (savedScrollPosition !== null) {
    window.scrollTo(0, parseInt(savedScrollPosition, 10));
    sessionStorage.removeItem('scrollPosition');
}

});

That’s okay.

I am afraid this will not work with infinite scroll as we would need to wait until the items where the user was before navigating out of the page to load, which doesn’t happen until we scroll the page. We can try using the render-all mode for this list.

I’ve modified the script where you initialize the Mux Script to also include this save position and scroll the page after all items have rendered + initializing Mux as you were doing before. Please try it and let me know how it works

<script>
  // Reinitialise Mux videos after CMS Load loads a new page and after clicking the browser back button (CMS Filter issue)
  window.fsAttributes = window.fsAttributes || [];

  // Save the scroll position before navigating away.

  window.addEventListener('beforeunload', function () {
    sessionStorage.setItem('scrollPosition', window.scrollY.toString());
  });

  // CMS Load callback
  window.fsAttributes.push([
    'cmsload',
    (listInstances) => {
      console.log('cmsload Successfully loaded!');

      const [listInstance] = listInstances;

      listInstance.on('renderitems', (renderedItems) => {
        console.log('CMS Load', renderedItems);
        // Restore the scroll position when the page loads.
        console.log('CMS Load rendered items');

        // Ensure Mux script is loaded and reinitialize videos
        ensureMuxScriptLoaded(initializeMuxVideos);
      });

      const savedScrollPosition = sessionStorage.getItem('scrollPosition');
      console.log('saved from memory', savedScrollPosition);
      if (savedScrollPosition !== null) {
        window.scrollTo(0, parseInt(savedScrollPosition, 10));
        sessionStorage.removeItem('scrollPosition');
      }
    },
  ]);

  function ensureMuxScriptLoaded(callback) {
    if (!window.muxPlayerScriptLoaded) {
      var script = document.createElement('script');
      script.src = 'https://cdn.jsdelivr.net/npm/@mux/mux-player';
      script.onload = function () {
        window.muxPlayerScriptLoaded = true;
        callback();
      };
      document.body.appendChild(script);
    } else {
      callback();
    }
  }

  function initializeMuxVideos() {
    // Select all Mux containers that haven't been initialized yet
    var playerContainers = document.querySelectorAll(
      '[id^="muxPlayerContainer-"]:not([data-initialized])'
    );
    playerContainers.forEach((container) => {
      var playbackId = container.id.split('muxPlayerContainer-')[1];
      if (playbackId) {
        var playerElement = document.createElement('mux-player');
        playerElement.setAttribute('stream-type', 'on-demand');
        playerElement.setAttribute('playback-id', playbackId);
        playerElement.setAttribute('thumbnail-time', '0');
        playerElement.setAttribute('preload', 'metadata');
        container.appendChild(playerElement);
        container.setAttribute('data-initialized', 'true');
      }
    });
  }
</script>

Thanks @Support-Luis

It now maintains position for render-all mode, but not the other modes like pagination. We’ll eventually have up to 10k CMS items and it will be too much to load on one page, so I’ll need some sort of pagination.

Are there any other ways to accomplish this you can think of?

BTW I’ve setup a new page for testing this:

https://preview.webflow.com/preview/great-ads?utm_medium=preview_link&utm_source=designer&utm_content=great-ads&preview=439cc7004d36950d559620c6ca522aa2&pageId=64f5d009c815622a746a91f7&workflow=preview

We could try with pagination mode with query params so the page is “saved” and then scrolling with the same method. You can test this quickly by changing the load-mode and adding the CMS Load query option

That basically worked, but not without issues. I’m going to park this for now and return to it later. Thanks for your help!

Cheers! Let me know when you get back to it!