Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccessKit Disable GIFs: Don't download GIFs until hovered #1458

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

marcustyphoon
Copy link
Collaborator

@marcustyphoon marcustyphoon commented May 21, 2024

Description

This modifies AccessKit Disable GIFs to delay downloading of the animated portion of most GIFs until the user actually hovers to load them.

I think this is both

  • pretty cool,
  • the way some users probably thought it worked already, and
  • a bit of a regression for some users, as the downloads are Pretty Slow in certain cases and if you're browsing through a lot of GIFs quickly, that's a bit annoying (I could see someone still wanting to use the script in this case, though it's probably niche).

One could make an additional dropdown option "download paused GIFS [when hovered/immediately] or checkbox option "download paused GIFs immediately;" the implementation would be easy. (One could also not implement this feature at all, in which case there are still tweaks in this PR that would be improvements to the script; if we decide on that I'll do that separately.)

Previous work: #1413.

The method to do this is:

  • Using static CSS, display: none GIFs if they aren't hovered and show their stationary "poster" elements, if they have them. This prevents their download, as they have loading="lazy".
  • Once a GIF is downloaded, unhide its poster element if it's hovered.
  • If a GIF doesn't have a poster, override the static CSS to immediately load it, since we need to make a canvas poster for it (Tumblr does not always supply posters). To make an instant download toggle option, simply do this even if the GIF does have a poster.

The nice thing about this method is that when a user scrolls a post with a GIF into view, the GIF immediately appears stationary with a label (currently there's a delay). When they hover the image, the label immediately disappears... and, if the load isn't instant, is replaced by Tumblr's loading ■■■ indicator, due to a happy coincidence of the positioning. The GIF stays paused-with-a-loading-indicator until it's downloaded, at which point it of course becomes animated whenever it's hovered, as normal.

(Misc code tweaks include removing the forced opaque background on our canvases, since this just hides the animated GIF behind the canvas so it's unnecessary, and some DOM order fixes: a) slipping the canvas element in after the GIF element instead of appending it to its parent because that puts it in front of the now-already-inserted label, and b) moving previously-added elements all the way in front of the poster instead of just slipping them in after the GIF.)

Testing steps

  • Optionally turn off the browser cache using dev tools.
  • Confirm that GIFs are paused correctly in posts and in on-user-hover blog cards.
  • Navigate to e.g. https://www.tumblr.com/search/gif (and note that GIFs that are visible during an initial page load are animated briefly; XKit of course doesn't load early enough to prevent those loading).
  • Scroll down and confirm that GIFs appear paused-and-labelled with no delay.
  • Hover a large-file-size GIF and confirm that its gif label is replaced with a loader, and that it stays paused and visible while it loads, then becomes animated.
  • Scroll back up and confirm that GIFs do not lose their labels or functionality when the virtual scroller brings back unloaded content.
  • Observe the behavior with the "disable layout animations" option enabled (it just means the loader is not animated, which feels fine to me).

@marcustyphoon marcustyphoon changed the title AccessKit Disable Gifs: Don't download Gifs until hovered / Use native poster elements AccessKit Disable Gifs: Don't download GIFs until hovered May 22, 2024
@marcustyphoon marcustyphoon changed the title AccessKit Disable Gifs: Don't download GIFs until hovered AccessKit Disable GIFs: Don't download GIFs until hovered May 22, 2024
@marcustyphoon marcustyphoon marked this pull request as ready for review May 22, 2024 23:50
@marcustyphoon
Copy link
Collaborator Author

marcustyphoon commented Feb 8, 2025

Along with #1707, this provides a much easier (diff-wise) way to do this:

  const posterElement = gifElement.parentElement.querySelector(keyToCss('poster'));
  if (posterElement?.currentSrc) {
    const image = new Image();
    image.src = posterElement.currentSrc;
    image.className = gifElement.className;
    image.classList.add(canvasClass);
    addLabel(gifElement);
    gifElement.before(image);
    return;
  }

This should be a used either synchronously within processGifs (to not download gifs until hovered) or in pauseGif after gifElement.decode(); (to download gifs normally). In the latter case it should have await image.decode(); before insertion as well, to avoid flicker.

Oh, and we should still hide .${canvasClass}:not(${hovered}) ~ ${keyToCss('loader')} in don't-download mode.

edit: No, this doesn't work; the created image elements have to be inserted immediately but they take a while to load, so there's a white flicker unless one adds extra code to show the poster for a longer period of time... at which point one may as well use the poster itself.

(nota bene: Tumblr waits for the poster to load to even insert the gif, so they are always already-loaded when our mutation observer callback runs. This is why they're so useful for preventing flickering visual effects. We could have an observer fire when a poster gets added and start processing in advance of the gif appearing if we needed to... but we don't need to.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant