I'm using document.images to load images when a visitor first visits the website. The reason is because I have a few different areas which have rollover images. Before I switch over to using CSS sprites (modifying a lot of work), I'm going to ask here.
So I'm preloading images with this:
images = new Array();
if (document.images) {
images.push(preloadImage("http://website.com/images/myimg.png", 300, 200));
}
function preloadImage(src, x, y) {
var img = new Image(x, y);
img.src = src;
return img;
}
And according to Chrome's "resource" panel, this is working just fine. Even after pressing CTRL+F5, the images listed in the JS are downloaded.
HOWEVER, they are not used. If I hover over an element in one of my three scripts, the image is downloaded a second time. Derp?
I assume that when preloading images this way, you're supposed to put that image array to use. I thought the browser would be smart enough to say "Hey, this is the same image, let's use it twice" but apparently not.
So is this correct? Do I need to rewrite my programs to preload images individually? I know it doesn't sound hard, but it's really not designed for that.
This is not really an answer to your question, but I proprose a different solution. Put all the images you need to preload inside a div that is hidden from the user. I know, I know, this i not as elegant, but it should work just fine. :)
<div style="display: none;">
<img src="http://website.com/images/myimg.png" alt=""/>
...
</div>
This works fine for me:
function imgPreload() {
var imageList = [
"my/firstimage.png",
"my/secondimage.jpg",
"my/thirdimage.png"
];
for (var i = 0; i < imageList.length; i++ ) {
var imageObject = new Image();
imageObject.src = imageList[i];
}
}
imgPreload();
Cheers. Frank
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 want to asynchronously download image, so first user sees a low resolution image, and higher resolution version is downloaded in the background. I have tried the following.
<html>
<head>
<script>
window.addEventListener('load', function () {
var kuvaEl = document.getElementById('kuva');
var r_src = kuvaEl.getAttribute('r-src');
var a_src = kuvaEl.getAttribute('a-src');
kuvaEl.setAttribute('src', r_src);
kuvaEl.setAttribute('src', a_src);
});
</script>
</head>
<body>
<img id="kuva" src="http://www.viikonloppu.com/wp-content/uploads/2014/04/lotoflaughters.com_-619x428.jpg?c3bc1b"
a-src="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
r-src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
</body>
</html>
But the problem is r_src download is aborted when src is change second time. I want to download both of these images in parallel, and show the r_src first (only if it downloads faster than a_src), and when the *a_src *is ready, show the a_src.
Also, is it possible to download these a_src and r_src images to the browser cache before the src is actually changed? Ideally I would like the the src change to either retrieve the image from the cache or join the pending download for that url.
I can also use jQuery. IE7 must support the implementation.
You just need to use javascript or jquery and load two version of the same image. the first will be your low res, but you will download a high res inside an hidden img tag.
When the download is complete, you just hide / delete the low res image and show the high res.
This link show some test and few way to do it. And it should support ie7 Load a low-res background image first, then a high-res one
You can use interlaced progressive JPEG format.
This method is the preferred method for handling high quality images and has been implemented by so many websites.the idea is that the compression of the image is made in such away that the when you send the image the receiver gets the image in finer and finer detail has the sending of the data progressed.
if you dont want to use the abouve technique
Have the low quality image in the src of the image. once the whole page loaded successfully,change the low quality image with high quality image
<img id="target-image" src="low-quality.jpg" data-src="high-quality.jpg" />
$(window).load(function(){
var imgSrc = $('#target-image').data('src');
$('#target-image').attr('src',imgSrc);
});
You should put your low res as default src. Then use JS to download the high res version and on download completion, change image src.
Also, good practice is to use data-* for custom attributes
If your really want a parallel download, you should replace "load" event for the "DOMContentLoaded" event. However, this will extend the time your user has to wait until page is ready. Your should keep the load event to prioritize critical assets loading (scripts and stylesheets)
window.addEventListener('load', function() {
// get all images
let images = document.getElementsByClassName("toHighRes");
// for each images, do the background loading
for (let i = 0; i < images.length; i++) {
InitHighResLoading(images[i]);
}
});
function InitHighResLoading(image) {
let hrSrc = image.dataset["hr"];
let img = new Image();
img.onload = () => {
// callback when image is loaded
image.src = hrSrc;
}
// launch download
img.src = hrSrc;
}
img {
/* only for code snippet */
max-height: 300px;
}
<img class="toHighRes"
data-hr="https://www.manitowoccranes.com/~/media/Images/news/2014/Potain-China-hi-res.jpg"
src="http://fuzyll.com/images/2016/angel_oak_panorama.jpg" />
Preload may not be the correct term...
I have a page which loads a very large image. I wanted to wait for the large image to completly load before displaying on the page for the user.
At the moment, I have a loading gif and i'm using javascript to wait for the image to load and then replace the loading gif src with the image:
<img src="loading.gif" id="image" />
<script>
img = 'very_large_image.jpg';
var newimg = new Image();
newimg.src = img;
newimg.onload = function(){
$('#image').attr('src',img);
}
</script>
I'm wondering if there are quicker ways to load this image such as a pure CSS way or some way to force the browser to download this asset first. The code above is obviously positioned in the location where the image is expected to load. So there is code above and below.
One CSS option I thought was to position the image off the screen and once it's loaded, perform the src replace.
My server is running http2, so it should be pretty quick. I just want to know if there is a better way then what i'm doing now to ensure the large image is loaded the quickest way possible for all major browsers.
I should add, i've already done plenty of optimisation of the image file already. I'm working with high resolution photography.
Thanks!
You can make the JPG progressive and then just let it load. Browsers will progressively display the image first blurry and then load more details.
This is the best way because user can see the image even before it's fully loaded.
Edit:
On linux use jpegtran, on Windows use Photoshop or RIOT
Your doing a great job!
Here is what I came up with:
https://jsfiddle.net/Vandeplas/jkwweh52/
HTML:
<img src="http://loadinggif.com/images/image-selection/32.gif" large-src="http://www.planwallpaper.com/static/images/518079-background-hd.jpg" large-class="fancyImg">
JS:
$('img[large-src]').each(function() {
var img = $(this);
var newimg = new Image();
newimg.src = img.attr('large-src');
newimg.setAttribute('class', img.attr('large-class'));
newimg.onload = function() {
img.replaceWith(newimg);
};
});
That separates the JS from the HTML + you can easily add infinite more pre-loading images without having to change the js!
Very easy way to preload images which are needed later
$.preloadImages = function() {
for (var i = 0; i < arguments.length; i++) {
$("<img />").attr("src", arguments[i]);
}
}
$.preloadImages("hoverimage1.jpg","hoverimage2.jpg");
I think that the best solution for your problem is split this image and load the parts assync at the same time
I'm using this JavaScript to preload few images on my website.
var images = new Array()
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image()
images[i].src = preload.arguments[i]
}
}
preload(
"img/1.png",
"img/hover.png",
"img/image.png",
"img/work1.png"
)
This code is linked in HEAD of the site.
But when someone is visiting my website he waits for few second's while images are loaded and in that time he sees blank (white) website until JS files are loaded. I want to make that when someone visit my website he see a "Loading progess bar" or message that say "Wati until page is loaded" etc. Without a blank index page where JavaScript is linked
Unless an accurate progress bar is actually helpful to your users you are probably better off simply use an animated gif that gets hidden after your loading functions finish. Something like this:
Put the gif on the top of your index.html file. Something like
<div id="loading-gif"><img src="/path/to/gif"></div>
Then when your content loads, simply execute something like
document.getElementById("loading-gif").style.display = 'none';
Note, license information for the above image is located here.
The Scenario
I have an asp.net web application with a HTML/CSS front end.
This all works fine but in Internet Explorer 6, the transparent PNG's that I use within the site are not transparent due to the poor design of this particular browser.
Solutions Attempted
I've already attempted various IE6 PNG Transparency fixes that didn't work.
The Proposed Solution
I thought about using GIF Image replacements for when the website detects that the browser is IE6. I don't have any javascript experience but someone has mentioned that I could use the "document.write()" feature off javascript to replace the PNG's with GIF's of the same image when using IE6 as the browser.
The Question
Please could someone explain to me how I would go about doing this?
Baring in mind I have an understanding of C# etc. but no javascript knowledge. I'm only just starting out as a web developer so simple explanations would aid me greatly.
Thanks for the help.
Regards.
If we assume that
a) the gif files will have the same name and,
b) they already exist (you're not looking for some gif creator).
Then you just need to replace the src attribute for these files. This would be done onload, and doesn't require document.write(). Go with:
<!--[if lte IE 6]>
<script type="text/javascript">
window.onload = function() {
var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
var image_png_src = images[i].src;
var image_gif_src = image_png_src.replace(".png", ".gif");
images[i].src = image_gif_src;
}
};
</script>
-->
The nice thing about the above method is that it doesn't have to check if it's gif or png or jpg every time, because it simply won't replace it with .gif unless there is a .png. The bad thing is that if, for some reason, you have an image with .png in it (and I can't imagine why) but it isn't the file extension, it would replace that bit with .gif.
Hope that helps.
Have you tried jQuery's pngFix? It makes the PNG transparent for IE 6 and you don't need to maintain two sets of images (PNG and GIF).
Using it doesn't require much javascript knowledge, so it wouldn't hurt to take a look at it.
Let's say your img element has an id="my_img"
To detect if browser is IE6, use conditional comments. Further, add Javascript like this:
<!--[if IE 6]>
<script>
document.getElementById("my_img").src = "images/alternate.gif"
</script>
<![endif]-->
You might also like to have a look at this:
IE6 PNG transparency
Here is the code runs a replace on IE6 only:
window.onload = function() {
if(navigator.userAgent.match(/MSIE 6/) != null)) {
var images = document.getElementByTagName("img");
for (var i = 0; i < images.length; i++) {
var src = images[i];
if(src.match(/\.png$/)){ //endswith .png
images[i].src = src.replace(/\.png$/g,'.gif');
}
}
}
};
jQuery version of the replacement:
$(document).ready(function()
{
// List all PNG images
$("img[src$=.png]").each(function(i, img)
{
// Replace with GIF versions
img.src = img.src.replace(/\.png$/, '.gif')
});
});
W3Schools is a great place to start if you're wanting to learn javascript.
For example, take a look at the getElementsByTagName function...
There is also a browser detect function here
Good luck - hope that helps.