svimg icon indicating copy to clipboard operation
svimg copied to clipboard

Image blurred when already loaded

Open ecstrema opened this issue 3 years ago • 13 comments

When an image is loaded, it is normal that a blurring occurs. However, when it's already loaded, it should not be blurred and wait for the onload event.

Demo: https://www.escaladelaurentides.ca/

Steps to reproduce.

  1. Visit the main page. The blurred->sharp effect happens. That is normal.
  2. visit any other page (for example documents) and switch back to the main page.

Expected: The blur effect doesn't happen a second time, since the image is already loaded.

I am very impressed with the quality of this preprocessor! It's so good that I believe it should be among the default preprocessors in svelte-preprocess!

ecstrema avatar Feb 11 '22 19:02 ecstrema

Glad it's working for you!

I'll take a look at what I can do about this, but from what I recall, it can be pretty difficult to reliably tell in Javascript whether an image is already cached by the browser. Depending on the Cache-Control headers, it might never be cached at all.

For what it's worth, for your particular example image, it might be worth using the immediate attribute to not actually go through the lazy load at all (you can still take advantage of the image preprocessing, obviously). The biggest benefit of lazy loading is to avoid downloading non-critical offscreen images until the user scrolls the image into the viewport to improve the initial page load, but in your case, your image is pretty much always going to be in the viewport when the page first loads. Having the browser lazy-load an immediately-visible image can actually be slower due to the deferral of the image download and the browser having to make the determination of the image's visibility in the viewport, so it can actually feel less responsive.

xiphux avatar Feb 12 '22 03:02 xiphux

Wow thanks for the detailed explanation!

It indeed seems that immediate is what I need. I liked the blur effect when it ocurred only once though;)

ecstrema avatar Feb 12 '22 03:02 ecstrema

Even though it doesn't stop anything from working, I also get this typescript error in vscode:

image

Have you ever encountered it?

ecstrema avatar Feb 12 '22 03:02 ecstrema

It indeed seems that immediate is what I need.

Hmm there is now a flash of unstyled text (the alt text) the first time... First render looks better with only an img tag.

I'll have a look at it.

ecstrema avatar Feb 12 '22 03:02 ecstrema

The typescript error is something I know about - Svelte got better Typescript support sometime after I created this package, so I need to create Typescript definitions for the component now that Svelte supports that.

I think the flash is due to setting the alt text immediately, before the image has finished loading. I can probably make it a bit less jarring by deferring setting the alt text until after the image finishes loading or if the load fails. I believe that's what normal img tags do (doesn't render the alt text while the image is still loading).

xiphux avatar Feb 12 '22 04:02 xiphux

I can probably make it a bit less jarring by deferring setting the alt text until after the image finishes loading or if the load fails

That sounds good

I need to create Typescript definitions for the component now that Svelte supports that.

Do you need any help with the migration to the newer system? I remember seeing somewhere that sveltekit was also a component bundler. I don't know if it's worth setting it up for a single component.

ecstrema avatar Feb 12 '22 05:02 ecstrema

Sure, I'd be happy to look at a pull request if you put one together.

xiphux avatar Feb 12 '22 15:02 xiphux

Great, I'm currently building such a monorepo. It shouldn't be too hard to make a clone of it with your preprocessor and components instead of mine. I'll tell you when I have time to tackle it.

ecstrema avatar Feb 15 '22 18:02 ecstrema

Sorry I never came back! I just saw you updated the repo to 2.0 back in march. I just updated and the typescript error is now gone.

The double blurring still appears though, but I got used to it, and it even feels nice now:)

ecstrema avatar Apr 30 '22 05:04 ecstrema

I don't quite understand the intended functioning of the lazy loading. When I visit https://www.escaladelaurentides.ca/ it loads all images from over the network even if they're below the page fold.

I wonder if it might be nice to rename it to loading to match the browser and invert is so that the default is that it isn't lazy.

I just set this up on the SvelteKit demo app and it's kind of a weird experience for a couple reasons:

  • the blurring seems to occur only on three edges, but not the top edge
  • the image is immediately available both because it's loaded from localhost and because it's cached, but takes quite awhile to fade in

I like the ability to lazy load, but it seems like more of a special case and not necessarily something you'd want to use on every image. I don't think I'm familiar with any large content sites that have this behavior. It seems like something to use sparingly for an e-commerce results page or photo app or something where you'd only want it on the dynamically loaded content images, but not on the static images like the logo, etc.

benmccann avatar Aug 10 '22 19:08 benmccann

It's using native browser image lazy loading, so the heuristics are up to the browser. The browser will often preload lazy images that are just offscreen under the expectation that the user is likely to start scrolling, to hopefully finish loading the image before the user scrolls the image into view. In this particular example, the page is short with images both immediately visible as well as just offscreen and likely preemptively loaded. Lazy loading would be more beneficial for a longer page. I think I suggested disabling lazy loading in my first comment in this issue.

Fair to consider whether the default should be lazy loading or not. This was originally created as a drop-in replacement for svelte-image, which also lazy-loaded by default, and my original use case was a photo blog, so I kept compatibility. Lazy loading should be used with judgement and not broadly used on every image. I could at least make this clearer in the documentation. I'd imagine changing the default would need to wait until a major version break.

This issue was left open to try to find a way to disable the transition animation for content that's already loaded and cached to make it load faster as you say. I have ideas to try but haven't gotten to it yet.

xiphux avatar Aug 11 '22 03:08 xiphux

Thanks for sharing the details around this! I actually didn't realize that the browser had introduced support for lazy loading. Does the fade in animation also come from the browser or is that provided by the library?

I tried to do some research on best practices around this today. I didn't find a whole lot, but I did see that the Chrome team recommends not lazily loading images are in the first visible viewport.

benmccann avatar Aug 18 '22 20:08 benmccann

The blurred placeholder and the fade in animation are coming from svimg. Without it, the browser does what it usually does when it loads images (just lazily) - the document reflows when the image is loaded and suddenly has dimensions, or if you have pre-set dimensions you get a blank space until the image loads in. So the blurred placeholder is trying to fill those dimensions to avoid the reflow and provide something other than an empty box, and the fade in (CSS transition) is trying to make it less jarring when the image does actually load in (otherwise it would immediately snap into focus).

I do think I need to update the documentation with more guidance and/or links to references such as that for when to use lazy loading or not. Even if I switched the default, someone stumbling upon the lazy option without that context could still just put that option on all images and we'd be back in the same spot.

xiphux avatar Aug 21 '22 20:08 xiphux