How to preload images so they're loaded faster everywhere else on the page, and is it a good practice? - google-maps

Here's the thing: I have a Google Map with a lot of markers in it.
The problem is that the map loads, stays empty for a little while and only then markers are displayed. The markers are customized PNGs.
My idea is to "preload" them (not sure it's the right word) so they appear almost at the same time as the map.
What I did so far is to add the same images I use on my map, outside of the map, earlier in the page in display:none;
I'm not sure but it seems like the time between the map and the images are displayed has been reduced.
Is it the best way to do it, and is it a good practice?

You could use "sprites" i.e. a collection of separate images on 1 single png. This bears the advantage of requiring only 1 load i.e. less separate loads. Google GWT pushes this technique a lot (i.e. Image bundles).
The value of this technique increases with the number of discrete images that require loading: the more separate images, the longer it takes to load them.

Don't use display:none for preloading. Because an element set to display:none doesn't render any of its physical attributes, the browser doesn't bother downloading it until it's made visible.
An alternative is to use visibility:hidden, but you run the risk of running into a user agent that does pretty much the same thing. visibility:hidden requires that the browser compute the box model for the image, which requires that image is loaded (to get the dimensions). I don't believe this works in IE6, though.
The last technique (and my favorite) is to create a div directly before your </body> tag. Position it absolute with left: -99999999px; top: -99999999px. The browser is forced to render the images (and consequently load them) and there's no messy Javascript to deal with.
Now, to integrate this with your issue, put the code for your Google map after your "preload div". Your browser will be forced to load the images before it runs the code to create the map. This should solve your problem.
Hope this helps!

From what I recall of most modern browsers, images are always loaded once (given the src of the image is the same). I guess you mean loading them before the maps load.
In my opinion in does not really matter that much. Markers should be relatively light compared to the map image itself and I can't really use them without the map anyway.
If you think it improve you user experience then I think it is a good practice, but I'd try to get them on a more cleaner way, probably an ajax call early in the page load?
Take a look at Ajax In Action: Preloading Images

Related

Swapping lazy-loaded images to `loading="auto"` upon page load complete

I have a strategy in mind for lazy loading images on a CMS (Sitecore) website, and I'm wondering if I will run into problems with it, since I am not finding examples of it being done.
The point is to improve performance, but reduce the side effect where users can get annoyed by images that are incomplete as the page is scrolled.
The strategy is using loading="lazy" on all images on the page, or only images below the fold, and upon page load, dynamically swap lazy to auto on all of these elements, from which point the browser will decide when to load the images by its own prioritization scheme.
The point is to prioritize images above the fold, but once the prioritized images and everything else are loaded, then tell the browser to load images by its own default loading behavior, so the user will be less likely to encounter incomplete images.
Are there problems I may run into doing this?
I can't imagine I am the first person to try this, but I am not finding examples in my search. Is this strategy established and documented anywhere?
The strategy is using loading="lazy" on all images below the fold, and upon page load, dynamically swap lazy to auto on every image element, from which point the browser will decide when to load the images by it's own prioritization scheme.
You don't need that to do. The browser know better when he should load the image. Just stay with lazy.
Are there problems I may run into doing this?
Yes! When you don't define a width & height for the image. There are some webpages which use achnor navigation. When the browser don't know how much space the image will take, then can happend that you will get some incorrect position when navigating.
Also there are some sideeffects that will load the image later then expected. Inside a slider as an example. But the benefit to not load the image is much more enjoyable then not to lazy loading the image.
Read more about the specific use-cases in this wonderful blog article:
https://web.dev/browser-level-image-lazy-loading/

Image lazy loading strategy; what problems may I encounter?

I am looking at disadvantages of lazy-loading images, and I must be hyper-thorough because we are considering implementing loading="lazy" on many/most images in the site. The reason for that is that I believe I have a strategy that should work.
We are using the browser-native loading="lazy" attribute, since we dropped support for IE recently. Wow, I know.
We are setting all images above the fold to eager, and all images below to lazy, across the entire site.
Then we are listening for the page load event and running a script that converts every image with loading="lazy" to loading="eager" (or auto). So images below the fold will get loaded too, probably in most cases by the time the user scrolls (at least using modern internet connection speeds). The page load event fires after all eager-loaded images have completed, but may/should fire before lazy-loaded images have started, so that is our opportunity to trigger loading below the fold.
One known disadvantage is that lazy-loaded images can cause a layout shift as the user scrolls, since the browser doesn't know the dimensions until the image starts loading. Another disadvantage is that users may be annoyed by images that are not loaded by the time they scroll to the image. This solution addresses both of those problems by converting remaining lazy-loading images to eager as soon as the prioritized images are loaded, to reduce the chance of the user encountering these issues.
There is also the possibility that there may be specific cases where pieces of JavaScript are waiting for an image to load in order to do something with it, and that can sometimes block rendering. Let's treat that as a side issue. I think it's unlikely we'll encounter that in this site, and we'll fix it where it occurs.
A side note, I have also devised a script that observes elements being populated or manipulated on the DOM by external scripts, and converts any newly-added img elements to loading="lazy" (if it occurs before page load), so I am able to guarantee lazy loading on all img elements on the page, and it DOES yield Lighthouse load performance gains of several points.
I am so far not finding many serious and/or likely problems from lazy-loading every or most images on a page, given that it is handled with the strategies that I have devised.
My question is what am I missing. Could this strategy have gaps?
What other considerations do I need to think about? Because I don't want my decisions to cause problems on the site I am working on.
When internet connection is very quick, things are also loading quickly and the user might not even see the status before the images are loaded. However, things are not always so rosy, there might be too many people using the internet and occupying all the bandwidth they can with watching videos, listening to music, chatting with friends.
Your problems start arising when
the users are using too many devices
there is an internet outage during the load of your page
an image is unavailable or slow to load (a very slow third-party UI, perhaps)
Usually, if your design works well and handles these cases in a user-friendly way, then users will notice there was a wait/outage, of course, but will probably not link that to your site. Yet, if your design looks ugly during these phases, then the users will remember that there was an outage/slowness of internet and how ugly your page was.
Since this is something every developer wants to avoid, it makes sense to treat the internet as something that usually works, but always has the potentiality of being down or slow.
As a result, if you know what pictures will appear in the viewport and what pictures will be shown only when the user scrolls, then you can eager-load the pictures the user will see first. Of course, it is not always easy to know what pictures will appear in the viewport, especially if your page looks very differently on different devices. Yet, you could divide your content into two main sections:
the section that is shown even during page load
the section which will be shown only when the page load is complete
you can totally hide the second section and then there would be no visual problems.
Another way to handle this is to know in advance (on server-side) the dimensions of the pictures, hide the picture tags while they are loading and show some placeholder (some "loading" gif, for example) in the place where the pictures will appear and have a load event for all images that are hidden this way which would make sure that the "loading" placeholder will disappear and the actual image appear when the image is loaded. This would ensure that your layout's visual structure is the exact same while it does not have all the images to show yet as when all the images were fully and successfully loaded.
What you may not know if you've never used browser-native lazy loading is that it does not necessarily improve initial load size/time on shorter pages, because it still initiates loading anything closer to the viewport than 3000 pixels, even before the window load event fires. This is what is considered too eager.
Info about this issue: https://calendar.perfplanet.com/2019/native-image-lazy-loading-in-chrome-is-way-too-eager
That can make it useless against Google's Lighthouse performance metrics for shorter pages.
So we are implementing the old-fashioned non-native lazy loading where we have complete control via JavaScript. Our images are served like:
<img data-src="some-image.src" />
<noscript>
<img src="some-image.src" />
</noscript>
...And using JavaScript strategy similar to what was described in the original question here, in addition to the common technique for swapping Image.dataset.src into the Image.src property, or we many use lazySizes.
But I don't get a few things about the functionality of browser-native lazy loading. Particularly, why the browser wouldn't prioritize lazy images above the fold over lazy images below the fold, and not load any lazy image below the fold or fire the load event until everything is loaded above the fold.
And I don't get why lazy loading can't be set with CSS. It would be great if we could apply the loading attribute to sections of a page by CSS selectors alone. Instead we're forced to handle it either with JavaScript or on the server. With CSS it would be as simple as loading: lazy;.
I'm going to look into if these ideas are proposed anywhere. I may also post the code we use in the end.

Does cycling through multiple images using CSS background url property save bandwidth?

I'm trying to create a gallery for a mobile site where I have different stylesheets for different sized devices. Within these stylesheets I have several classes which simply set a background url property to each image I want in the gallery.
Only one of these will be displayed at a time. And I will be cycling through the classes using Javascript to display them in a slideshow type presentation.
I am wondering is this method more bandwidth efficient than having all the images as individual img tags within the DOM? By setting these url properties do they get downloaded to the user's browser when they first load the site or are they only downloaded when the class gets set on a div in the DOM?
Simply I am trying to avoid having to download all the different images to the user's device at once. If you know any alternate methods which are better for this sort of thing I am also interested.
You are right, When you set the image backround, the image will only be downloaded if it is used, By this I mean, used as a style on some dom element.
Alternatively, you could 'change' the background-image css property using javascript. This way, you don't even have the image url in your CSS.
If bandwidth is your biggest concern, I would urge you to have a look at the inspector in webkit browsers like Chrome or safari, or with firebug on Firefox to see the 'network' tab, there you have a clear overview of what is loaded, how ( what order ) and how to optimize things. You can also make some stupid mistakes clear like downloading multiple times the same library from different locations and so.
If you just declare the class in css it shouldn't download anything before it is set. however it is a round question and the answer could take a lot of different shapes.
So I would say that yes it is a good way to do it, and it should be more bandwidth efficient (if you don't know that all the images will be loaded eventually anyhow, since you will typically have asynchronous image-loading either way it shouldn't matter much. I guess that if you only load one image initially the other images (i.e. the mentioned img tags) will not interfere making the load a bit more smooth?).
I find it to be a cleaner solution at least if you aren't sure which images will be viewed (which is likely to believe) to use your css-approach. also it's easier to maintain and provide a better design.
That you will be using javascript indicate that you are also doing the client side. And that give you control to choose what to do which is great :)
One alternative could be to have a local cache of the images as well, but that really depends on the problem at hand, if you will have different images and no real possibility to know in advance which images you will need (and perhaps not even how many of them?) then I think that the cleanest way is the way you purpose.
i.e. set up (or dynamically create) css-classes for images and handle all the logic in javascript.

HTML5 Remembering div position after dragging

I wish to create a local (offline) HTML5 page containing various sized rectangles containing a paragraph of text (and links) that can be repositioned by being dragged by the user. It's not necessary to drop them into any target; simply to drag them. But the page has to remember their final locations and show them there when it is reopened.
I did think of using Canvas to do this but drawing the text in the rectangles is very slow. Better to create a div (with a border) for each paragraph. The closest solution I have found so far is this one, where one drags the "aside". The original page is here.
What code would I need to write to store these locations locally (offline), preferably by self-modifying the HTML page itself? I understand there are localStorage and sessionStorage objects in HTML5 but have not tried using them.
PS This page is for my own use and as I use Firefox I am not interested in other browsers. I would prefer using Javascript to jQuery, but all suggestions will be most welcome.
PS While waiting for a reply, I stumbled across this site:
built with HTML5, CSS3 and JavaScript, the diagrams are created with canvas and offline usage is possible, thanks to ApplicationCache.
Would this be the way to go?
You could save the div information (positions and width, (eventually height too)) into the localstorage. When you are reloading the page you just need to get them back out of the localstorage to rerender the whole thing.
jStorage is a simple plugin where you can "speak" to your local storage. You could store an object (serialized) into this and then loop it out on your page load.

Rasterize a fragment of HTML to PNG

I have a page with a series of divs. Each div represents a slide in a slide deck. I need a series of thumbnails, one for each slide. Ideally these thumbnails would be rasterized versions of the slides: a PNG data: url would be perfect. I'd like the work to be done in the browser, and I'm okay with things that only work in one of the modern browsers (e.g. chrome, or firefox). I suspect this is impossible, but would love to hear otherwise.
The method toDataURL() on the canvas object is essentially what I want, but the divs in question aren't instances of canvas, so that won't work.
One solution can be to render HTML to a canvas by embedding the HTML into an SVG image as a <foreignObject> and then drawing the resulting image via ctx.drawImage().
Read the article on MDN here, or take a look at rasterizeHTML.js which is an implementation of said approach.
The limitations are that your content should all be same-origin clean (i.e. accessible by AJAX).
Disclaimer: I am the author of rasterizeHTML.js.
It isn't possible on the client side as this is forbidden to protect from potential frauds like for ie script that would take a screenshot of your page with some private data and send it god one knows where.
Although...
it is possible to copy whole HTML to use it as a thumb preview/whatever and use CSS3 transformations (scaling) + add overlay over it to prevent interactions/text selection etc to mimic a thumbnail of a div.
and there was an option in firefox/chrome extensions to save page to an image - though not sure if it was possible to take only part of the page as an image
or you can always do like google does on its search results page with their page preview (click the magnifying lens near the result title) - have a robot machine which enters the page and takes a screenshot of whatever to produce the preview of the page using this data - don't know how much you WANT to do that but if you wanted it that bad... :)
I'm afraid there is no easy way to do what you want and the CSS3 trick one seems to be the easiest one to pull of.
you can rasterize html to a <canvas> element in javascript with the rasterizeHTML library:
http://cburgmer.github.io/rasterizeHTML.js/