I'm wondering if there is a way to control which image loads first when the user opens the website. The problem is that I have a simple one-page website that is taking too much time to open the first image (Big Home image - example). I would like to load this image first, and then load the other images in the website, should I do it manually with Jquery for each image (using $.attr("src") after document.ready)? or is there a better way?
Control which image loads first
If you want to have control over which images to load first and load the images synchronously then try this. Working JsFiddle
var loaded = 0;
var imgSrcArray = ["https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Small_icosihemidodecahedron.png/100px-Small_icosihemidodecahedron.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Small_cubicuboctahedron.png/100px-Small_cubicuboctahedron.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0d/Small_dodecahemidodecahedron.png/100px-Small_dodecahemidodecahedron.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Small_rhombicuboctahedron.png/100px-Small_rhombicuboctahedron.png"];
$('div img').on('load',function(){
loaded++;
var indexOfThisImg = imgSrcArray.indexOf($(this).attr('src'));
$('#output').append("loaded image " +indexOfThisImg + '<br/>');
loadNextImg(loaded);
});
function loadNextImg(index){
$('div img:eq('+index+')').attr('src',imgSrcArray[index]);
// if the imag tags are not continuous and you want to load the images in random position in an order then you can maintain the order of the images in a separate array and then use that indexes to load the images.
}
$('div img:eq(0)').attr('src',imgSrcArray[0]);
//trigger the load of first image, which starts the chain reaction
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<img />
<img />
<img />
<img />
</div>
<div id="output">
</div>
The idea is to hold all the images src in an array and load the first image, and on the load event of the image increment the array index and load the second one and so on.. This way we have control on the order of the images that should load. let me know if this helps
Related
I have a simple carousel on my home page. It changes pictures automatically after a couple of seconds. The html looks like this:
<div>
<div id="img-1" class="carousel-image" style="display: block;"></div>
<div id="img-2" class="carousel-image" style="display: none;"></div>
<div id="img-3" class="carousel-image" style="display: none;"></div>
</div>
I use a javascript function to add the images as background-image. To make sure the carousel images are all loaded before the carousel starts changing automatically I use new Image() and count the number of loaded images. Once all three images are loaded I can do startCarousel().
var numberOfLoadedImages = 0;
function setImage(imgUrl, imgId){
var homeImage = document.getElementById(imgId);
homeImage.style.backgroundImage = 'url(' + imgUrl + ")";
var img = new Image();
img.onload = function() {
if(numberOfLoadedImages === 2){
startCarousel();
}
numberOfLoadedImages++;
}
img.src = imgUrl;
if (img.complete) {
img.onload();
}
}
I can then simple call this function like this:
setImage('img-1', 'img-1');
setImage('img-2', 'img-2');
setImage('img-3', 'img-3');
What I would like to achieve is to lazy-load the second and third image. These two are not necessary at first page load; only the first image is important. Google Page Speed Insights mentions the second and third under the heading "Serve images in next-gen formats", whereas, if you ask me, they should not be considered part of the page. They should be loading in the background and they are really not essential for the first display and UX.
How can I tell the browser (or Google Page Speed Insights) that these images are completely non-essential for UX purposes and should not be considered part of the first paint and UX?
I tried putting the second and third call in a timeout with a short interval, but that didn't do the trick.
NB: I am using vanilla javascript; no plugins at all.
You can wait for everything to load and once the page is fully loaded (including images, etc.) you can run setImage for your second and third image.
document.addEventListener('DOMContentLoaded', function() {
setImage('img-2', 'img-2');
setImage('img-3', 'img-3');
}, false);
In case Google Page Speed Insights still registers this and prolong the initial page load time you can use async function to call setImage.
I would like to load an image from a Link:
1) Click on "a href", extract image url from href/src/id
2) Link should dissapear and show Ajax-Loader Image while loading Image.
3) Display loaded image.
If it's possible i dont want to use any buttons or div-constructs to output image - only a simple link.
On Click:
<a class="loc" href="./misc/images/image1.png"></a>
Browser should output an image:
<img src="./misc/images/image1.png" />
so far i made this:
$('a.loc').text('load image').css("cursor","pointer");
$('.loc').click(function(){
$(".loc").fadeOut(300);
$(".loc").html('<img src="/images/ajax-loader.gif" />');
var image = $(this).attr('src');
*** how to show/load image, how to use my var ??? ***
});
Has anybody an idea how to complete this task? I'm, greatful for any help.
You may use replaceWith:
var image = $(this).attr('src');
$(this).replaceWith('<img src="'+ image +'">');
However your method to show a loading image will not work more. You should add some prefetching logic to your codes and use replaceWith after fetching image.
I want to load two images in a single <img /> tag. First small image will be shown by src attribute and second large image will be inside data-src attribute but one image will be shown at once, that will be in src attribute. I want when page load small image will be load and show first and after completing loading of large image in the background it will be replaced by small image so that we can see large image. I have the code that will take large image from data-src attribute and place large image in src attribute.
$(document).ready(function(){
$("#image4").load(function(){
var imgDefer = document.getElementsByTagName('img');
for (var i=0; i<imgDefer.length; i++) {
if(imgDefer[i].getAttribute('data-src')) {
imgDefer[i].setAttribute('src',imgDefer[i].getAttribute('data-src'));
} }
});
});
I want to do this because I don't want to wait for long time to load large image, instead I want to see the small image first. I am facing the problem when page load, it's loading small and large images in parallel. For your information images have the drag and zoom functionality.
Current live code is here: http://virtualepark.com/new1/demo.html
The code you posted here is not deployed on your server - there is some other stuff using the mousewheel-event.
Try loading the big image hidden in the background and once its loaded, set the url of the visible image:
//get all images
$('img').each(function(i, img) {
var img = $(img);
//if they have a data-src
if(img.attr('data-src')) {
//register for the load-event for the initial image
img.one('load', function() {
//if small image is loaded, begin loading the big image
//create new hidden image
var hiddenImg = new Image();
hiddenImg.onload = function() {
//if the hidden image is loaded, set the src-attribute of the
//real image (it will show instantly)
img.attr('src', img.attr('data-src'));
};
//trigger loading of the resource
hiddenImg.src = img.attr('data-src');
});
});
});
(credits to Load image from url and draw to HTML5 Canvas)
you can load to hidden tag and after load complet change them.
you can try to start the loading after the image is loaded.
$('img').load(function(){
var bigImgSrc = $(this).data('src');
var img = $(this);
if(bigImgSrc != img.prop('src')){
var bigImg =$('<img>').prop('src', bigImgSrc);
bigImg.load(function(){
img.prop('src', bigImgSrc);
});
}
});
I'm not 100% sure if you need to append the bigImg to the DOM or if it also loads like this. If you need to add it to the DOM use bigImg.hide().appendTo('body') and then use the remove funtion when loaded.
You should also be aware that the load-function not work in all cases, see https://api.jquery.com/load-event/
edit there was in an infinity loop in the prev. code example
I'm a beginner front-ender considering the following scenario :
A certain HTML page should include a heavy image (e.g - animated gif) but I don't want to force the client to sluggishly wait for it to completely download before enjoying a pretty page, rather I would prefer to show him a lightweight image (e.g - the first frame of the gif) and when the former is readily downloaded by the client's browser, replace the light one with the heavy.
What should be the best approach for the matter - Am I looking for a technological solution or a methodological one?
Thanks!
You can embed the light-weight image using a data-URL. This will show that image immediately.
<img src="data:image/gif;base64,---Your-Base64-Encoded-Image-Here---" />
You can use this web site to convert an image file to a data-URL.
What you then need to do is to load the larger image in the background and, once loaded, make it replace the light-weight image.
<img src="data:image/gif;base64,---Your-Base64-Encoded-Image-Here---" />
<img class="heavy" src="http://server.com/path/to/heavy/weight/image.gif" />
The following CSS hides the heavy-weight image initially:
/* Don't show heavy-weight images until they're loaded */
img.heavy {
display: none;
}
The following jQuery-based javascript will hide the light-weight image and show the heavy-weight image once it is loaded:
$(function () {
// Register handler that will be invoked when a heavy-weight image is loaded
$("img.heavy").on("load", function () {
// Hide the light-weight image
// (we assume that it is the immediate previous 'img' sibling of the
// heavy-weight image)
$(this).prev("img").hide();
// Show the heavy-weight image
$(this).show();
});
});
Update (not using data-URL)
If you don't want to use data-URL for the light-weight image, you can use a similar approach where you don't start loading the heavy-weight image until the light-weight is loaded.
<img class="light" src="http://server.com/path/to/light.gif" />
<img class="heavy" data-src="http://server.com/path/to/heavy.gif" />
The heavy-weight image is not loaded initially because it does not have a src-attribute.
The following script will start loading heavy-weight images (by copying data-src to src) as soon as the light-weight image is loaded, and finally "replace" the light-weight image once the heavy-weight image is loaded.
$(function () {
// Register handler that will be invoked when a light-weight image is loaded
$("img.light").on("load", function () {
// Start loading heavy image (by assigning the src-attribute)
$(this).next("img.heavy").each(function () {
$(this).attr("src", $(this).attr("data-src"));
}).on("load", function () {
// Show the heavy-weight image and hide the light-weight image
$(this).show().prev("img.light").hide();
});
});
});
Update 2 (automatic creation of heavy-weight image element)
If you can derive heavy-weight URLs from light-weight URLs, then you can use another approach which might be easier to use and maintain.
<img class="light" src="img/light/image.gif" />
The following script will create a new heavy-weight image element for each light-weight image that is loaded. The heavy-weight image URL is copied from the light-weight image URL, but with the text light replaced by heavy.
$(function () {
// Register handler that will be invoked when a light-weight image is loaded
$("img.light").on("load", function () {
// Create heavy-weight image element after the light-weight image
// URL is computed from light weight image (by replacing 'light' with 'heavy')
// The element is initially hidden.
$("<img/>")
.attr("src", $(this).attr("src").replace("light", "heavy"))
.hide()
.on("load", function () {
// Show the heavy-weight image and remove the light-weight image
$(this).show().prev("img.light").remove();
})
.insertAfter(this);
});
});
This version also removes the light-weight image from the DOM once the heavy-weight image is loaded.
I may use another simple solution depend on a hidden iframe for the heavy image. It will replace the src of the light image when the iframe is loaded. The iframe src will be the src of the heavy image.
<html>
<head>
<script>
function replaceImg(imgId,ifrId){
ifr = document.getElementById(ifrId);
img = document.getElementById(imgId);
img.src = ifr.src;
}
</script>
</head>
<body>
<img id="img1" src="../img/initializing.png" />
<iframe id="ifr1" onload="replaceImg('img1','ifr1')" src="http://lorempixel.com/800/400" style="display:none"></iframe>
</body>
</html>
A live DEMO is found here. However, if you could not able to notice the light image, press RUN button again in the jsfiddle page.
Is there any way without AJAX of changing the loading order of images on a page? Or even a way to completely halt or pause loading of images already present?
The use case is simple - I have a long list of images down a page, and visitors will be landing on different spots of the page using URL anchors (/images#middle-of-page) that refer to actual containers for those images.
I'd like in the least to load the images inside the requested container FIRST, then continue loading the rest of the images.
The challenge is that there is no way to know the image paths of the requested container image before loading the page DOM.
I've tried getting the container img contents on load, then using the Javascript new Image() technique, but it doesn't change the fact that that image on the page will still be waiting for all previous images to load.
I've also tried immediately prepending a div in the body with a background image (CSS) of said img path, but this also does not prioritize the image load.
Any other ideas?
You need to have a DOM with empty img placeholders, i.e.
<img src="" mysrc="[real image url here]" />
Or you can make images to display "Loading..." image by default. You can even cache real image url in some custom tag, mysrc for example. Then once you know what exactly images you want to show (and in what order) you need to build a sequence of image loading
var images = [];//array of images to show from start and in proper order
function step(i){
var img = images[i++];
img.onload = function(){
step(i);
}
img.src = "[some url here]"
}
Hope this helps.
For interest, this is the function I ended up implementing based on the answers here (I made it an on-demand loading function for optimum speed):
function loadImage(img) { // NEED ALTERNATE METHOD FOR USERS w/o JAVASCRIPT! Otherwise, they won't see any images.
//var img = new Image(); // Use only if constructing new <img> element
var src = img.attr('alt'); // Find stored img path in 'alt' element
if(src != 'loaded') {
img
.load(function() {
$(this).css('visibility','visible').hide().fadeIn(200); // Hide image until loaded, then fade in
$(this).parents('div:first').css('background','none'); // Remove background ajax spinner
$(this).attr('alt', 'loaded'); // Skip this function next time
// alert('Done loading!');
})
.error(function() {
alert("Couldn't load image! Please contact an administrator.");
$(this).parents('div:first').find("a").prepend("<p>We couldn't find the image, but you can try clicking here to view the image(s).</p>");
$(this).parents('div:first').css('background','none');
})
.attr('src', src);
}
}
The img loading="lazy" attribute now provides a great way to implement this.
With it, images load automatically only when on the viewport. But you can also force them to load by setting in the JavaScript:
document.getElementById('myimg').loading = 'eager';
I have provided a full runnable example at: How do you make images load lazily only when they are in the viewport?
One really cool thing about this method is that it is fully SEO friendly, since the src= attribute contains the image source as usual, see also: Lazy image loading with semantic markup