Load images separated from page loading - javascript

I am currently using lazy loading of images, in which all the images are loaded while page is loading and displayed after an image is loaded. In this method, page is shown loading at the tab section of browser till all the images are downloaded.
Now, I want to load the images separate from page loading. Like in google images, page is loaded within 1 second, and images are loaded one by one without showing the page loading in the tab of browser.
How can I achieve this?
So, the final question: How to first load the page fully, without downloading the images from server, and then download the image when the scroller is reached there. Till then, the image may be a grey box.

Loading an image when it comes into view.
Loading attribute
We could use native lazy loading with the loading attribute.
Here's a demo.
<div><img src="https://placeimg.com/410/410/any" loading="lazy" width="410" height="410"></div>
Currently, the latest version of Chrome, Firefox and Edge support native lazy loading.
Be aware that the distance threshold does vary in browsers.
Chrome
The distance threshold after which the deferred content will start
loading-in depends on factors including the current effective
connection type, and whether Lite mode is enabled. The distance is
chosen so that the deferred content almost always finishes loading by
the time it becomes visible.
Firefox
Tells the user agent to hold off on loading the image until the
browser estimates that it will be needed imminently. For instance, if
the user is scrolling through the document, a value of lazy will cause
the image to only be loaded shortly before it will appear in the
window's visual viewport.
Intersection Observer
We could also use the IntersectionObserver API to determine when your images are in view. This offers better compatibility across browsers and offers greater control for when and how our images load.
CodePen
HTML
<div>
<img src="data:,"
data-src="https://placeimg.com/410/410/any"
class="lazy"
alt=""
width="410"
height="410" />
</div>
JS
document.addEventListener("DOMContentLoaded", lazyLoad);
function lazyLoad() {
const images = [].slice.call(document.querySelectorAll("img.lazy"));
var config = {
// If the image gets within 500px in the Y axis, start the download.
rootMargin: "500px 0px",
// detect when visibility passes the 1% mark
threshold: 0.01
};
if ("IntersectionObserver" in window) {
const observer = new IntersectionObserver(showImage, config);
images.forEach(function (image) {
observer.observe(image);
});
}
}
function showImage(entries, observer) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
const image = entry.target;
image.src = image.dataset.src;
observer.unobserve(image);
}
});
}
Existing libraries
There are also existing JavaScript libraries, such as lazySizes.

Related

Display two images with SRCSET at different screen size issue

I have looked over examples online, yet I believe I am overlooking something. I have two similar images that need to be rendered when the screen is at a different size. One image at 1440px screen size and one at 375px screen size. Right now with my code I have set the initial source to render the "mobile view" of the image, and with the srcset of the desktop view image at 1440w. When I load up live server it shows the desktop image, and not the initial source of the mobile view. So it seems to be working but missing a step.. any tips are greatly appreciated!
<img
class="future__container--img"
src="./images/illustration-editor-mobile.svg"
srcset="./images/illustration-editor-desktop.svg 1440w"
alt="illustration-editor-mobile"
/>
So when the browser first loads it is showing the desktop.svg, but when I set the browser to 375px it still displays the desktop.svg. I first had this written in javascript ..
const resizeEditiorImg = () => {
const reswidth = screen.width;
let image = document.querySelector(".future__container--img");
if (reswidth >= 1440) {
image.src = "../images/illustration-editor-desktop.svg";
} else {
image.src = "../images/illustration-editor-mobile.svg";
}
};
window.addEventListener("resize", resizeEditiorImg);
But the issue here is that when the browser first loads on desktop view, it is displaying the mobile image unless the user manually resizes the browser, which is what I believed at first. I hope this post makes sense!
This only work in resize browser because this code resizeEditiorImg
you need run this command resizeEditiorImg in your load page.
example
<body onload="resizeEditiorImg()">

How to load all images before showing the page in React?

I am trying to find a more modern solution that doesn't use jQuery as I am using React (Gatsbyjs specifically).
I have a website with multiple image carousels that contain high res images.
The issue is the each image carousel only show one image at a time, so only when the user navigates to the next image does the image get fetched, this results in a choppy loading appearance.
I have tried researching online with onLoad and load event listeners but none seem to have worked so far because they only load the image that is currently being shown by the carousel, instead of all of the images in the carousel.
If there is a way to first load all the images, then set the state to true, and only after the state is true, then the rest of the DOM appears onto the screen, that would be perfect.
Any suggestions? Thanks.
Website in question: https://dev--yachtgamechanger.netlify.com/
As Lonnie Best said, I ended up using Promise.all() to capture the loads of the images.
Just in case anyone else want to check it out:
https://codesandbox.io/s/react-image-preload-ptosn
I guess that your lib is using lazy load approach. And it's really good when dueling with high res images.
You still can change the approach to load all the images before rendering the UI, by going into the carousel component, change the rendering behavior by checking whether all images be loaded or not before render.
Updated: Because you are using gatsby-image, so just use this property:
loading: "eager". For EX:
<Img
fixed={data.file.childImageSharp.fixed}
alt="Gatsby Docs are awesome"
loading="eager"
/>
https://www.gatsbyjs.org/packages/gatsby-image/
You can ensure that an image is pre-downloaded 100% well before it gets displayed to the screen.
Simply create an Image element and set its src property to the URL where the image is located. Then use the image's onload event to detect when it is ready for instant display.
// Image to Pre-Download:
var image = new Image();
console.time("Image Fully Downloaded in");
image.src = "https://www.nasa.gov/sites/default/files/thumbnails/image/pia24870.jpeg";
image.onload = function()
{
console.timeEnd("Image Fully Downloaded in");
console.log("Image is ready for viewing.");
clearInterval(interval);
progress.parentNode.replaceChild(btn, progress);
}
// Fake Progress Indicator:
let progress = document.createElement("progress");
progress.value = 3;
progress.max = 100;
progress.textContent = "Fake Progress";
document.body.appendChild(progress);
let interval = setInterval(()=>
{
if (progress.value === 99)
{
progress.value = 0;
}
else
{
progress.value = progress.value + 1;
}
},50)
// Button to Replace Progress Indicator:
let btn = document.createElement("button");
btn.textContent = "View Entire Image Instantly";
btn.addEventListener('click',function()
{
this.parentNode.replaceChild(image, this);
});
img { max-width: 100%; }
<p>Only after the image is completely downloaded, will you see the button to view it:</p>
Based on this concept, you could pre-load/queue as many images as you like into image objects, so that they are ready to be displayed instantly (well before the user decides to view the next image). Here's an example where I'm switching between preloaded images automatically (so fast that it looks like an animated gif -- but it is actually 27 separate images from 27 different URL locations): See statue example and view source.

How to cancel a background image from loading

How can you cancel the loading of an image defined by a background-image attribute?
There a few questions that show how to cancel the loading of an <img> tag by setting the src to '' or to a different image (such as this one, answered by Luca Fagioli). But this does not work for background images.
Luca provided a jsfiddle ( jsfiddle.net/nw34gLgt/ ) to demonstrate the <img src="" /> approach to canceling an image load.
But modifying that jsfiddle to use background-image instead clearly shows that the image continues loading, even if:
you do background-image: none (as suggested here)
or background-image: url("web.site/other_image.jpg")
or background-image: url('').
In fact, in my testing on Firefox 54, the background image continues loading even if you do window.stop() or close the tab.
So, is there any way at all to stop loading a background image once it starts?
My use-case for this is client-side, so I can't change the site to not use background images. I am viewing a gallery of many thumbnail images, but the thumbnails are much larger than they need to be. Smaller versions are available so I wanted to replace the large thumbnails with the smaller versions via Greasemonkey to ease the network load on my poor, slow connection. Each entry in the gallery is a <div> with a background-image inside an <a> linking to the full-size image. (using Fotorama).
If you need to target inline styles on the elements, then I think you can run a script near the bottom of the page to do that.
Testing this locally, the original images do not show as loading in the network tab.
var allDivs = document.getElementsByTagName('DIV');
for (var i = 0; i < allDivs.length; i++) {
// check for inline style
var inlineStyle = allDivs[i].getAttribute('style');
// check if background-image is applied inline
if (inlineStyle && inlineStyle.indexOf('background-image') != 1 ) {
allDivs[i].style.backgroundImage = 'url("newImg.jpg")'; // assign new value?
}
}
That is going to grab every div, so hopefully these elements have a class you can use to query first. Then you have a smaller collection to run the above on.
Classes, not inline styles:
If you could target classes, it would look a bit cleaner. You could create a new class and use it.
var els = document.querySelectorAll('.bg-img');
for (var i = 0; i < els.length; i++) {
els[i].classList.remove('bg-img');
els[i].classList.add('no-bg-img');
}

Issue with high resolution images in chrome(windows) loading from javascript

I am having a problem with a site. My problem is I am loading several images progressively - starting with a small resolution image for fast loading I am then ajaxing a bigger image in (normally the original size that a user uploads).
The code below works perfectly. HOWEVER when done on chrome on windows. if the bigger image is a really high res (lets say 4400 x 4000). The screen would go white and the image would disappear. The white bursts out of the container (which has overflow:hidden) on it and covers the screen. Only the elements with a higher z-index over the image displays.
If I inspect the element that is white. It shows that it is the element, and the image is loaded - the URL is fine and if I click the image to open in another tab it loads fine.
Does anyone have any idea why this is happening?
if(href){
var img = document.createElement('img');
img.className = 'openLBFullView hidden';
img.onload = function(){
loadBiggerImg(this);
};
$(img).data('url',$currentImg.data('url'));
img.src = href;
img.id = 'my-image';
}
var loadBiggerImg = function(img){
var originalImg = $('#my-image');
//append the img to the document
originalImg.before(img);
// append original styles and classes to new image
$(img).attr('style',originalImg.attr('style'));
$(img).attr('class',originalImg.attr('class'));
// fix for windows IE adding attributes
$(img).removeAttr('width').removeAttr('height');
//fade in new image over the top and remove old one
$(img).fadeIn(200,function(){
originalImg.remove();
});
}
One of the possible solutions - large images dont render in chrome
This not neccesarily will fix your issue though - I'd try using lowres jpegs scaled to highres and preload big one - once loaded fade lowres one and show the big one (in a way fake the progressive JPEG) - Hope that helps man.

Javascript load background-image asynchrously

Is it possible to load a background-image asynchronously?
I've seen many jQuery plugins to load normal image in an asynchronous way, but I can't find if it's possible to preload / asynchronously load a background-image.
EDIT
I clarify my problem. I've been working on this test site http://mentalfaps.com/
The background image is loaded randomly from a set of images refreshed each hour by a chron job (which takes random images on a flickr catalog).
The host is free and slow at the moment, so the background image takes some time to load.
The positioning of the first overlay (the one with the PNG transparent mentalfaps logo) and width are regulated by a function created in the jQuery(document).ready construct.
If you try to refresh the page many times, the width of the right overlay div is 0 (and so you see a "hole" in the layout)
Here is the method to set my positions:
function setPositions(){
var oH = $('#overlay-header');
var overlayHeaderOffset = oH.offset();
var overlayRightWidth = $(window).width() - (overlayHeaderOffset.left + oH.width());
if (overlayRightWidth >= 0) {
$('#overlay-right').width(overlayRightWidth);
} else {
$('#overlay-right').width(0);
}
var lW = $('#loader-wrapper');
lW.offset({
left: (overlayHeaderOffset.left + oH.width() - lW.width())
});
}
The problem is that the $(window).width() is lower then the effective window width! so the check fails and the script goes for $('#overlay-right').width(0);
any ideas?
Not sure whether I really understand your question, but background images (and all other images) are already loaded asynchronously - the browser will start separate requests for them as soon as it encounters the URL while parsing the HTML.
See this excellent answer for background on loading order: Load and execution sequence of a web page?
If you meant something else, please clarify.
The trick to loading something in the background is to load it once, so the next time when it is loaded it already is in the cache.
Put the following at the end of your html:
<script>
var img = new Image();
img.onload = function () {
document.getElementsByTagName('body')[0].style.backgroundImage = 'background.png';
};
img.src = 'background.png';
</script>
You could use a prefetch link in the head.
<link rel="prefetch" href="/images/background.jpg">
You should be able to add these links to the head via JavaScript.
I like to use CSS to fill the background with a color for page load.
After DOM ready event, I use jQuery to modify the CSS and add a background image. That way, the image isn't loaded until after page loads. Not sure about async, but this method gives the user a decent experience.
Example: http://it.highpoint.edu/
The right side navigation links have a background image. The page initializes with a background color. It is replaced with a background image after page load, via jQuery.
changes in this file jquery.ImageOverlay.js
set your height and width and enjoy this...
imageContainer.css({
width : "299px",
height : "138px",
borderColor : hrefOpts.border_color
});
As it is already mentioned, the background image is loaded asynchronously. If you need to load the background image from JQuery code you may also set the addClass() method to set a CSS class or attr("style=\"background-image:url('myimage.png')\"")
Ive found the answer myself, it was a problem due to the .offset() method that gived sometimes the wrong values.
I had the write values using the .position() :
var overlayHeaderOffset = oH.position();

Categories