Load a Low-Res Background Image First, Then a High-Res One

Load a low-res background image first, then a high-res one

Here's the method I use...

CSS:

#div_whatever {
position: whatever;
background-repeat: no-repeat;
background-position: whatever whatever;
background-image: url(dir/image.jpg);
/* image.jpg is a low-resolution at 30% quality. */
}

#img_highQuality {
display: none;
}

HTML:

<img id="img_highQuality" src="dir/image.png">
<!-- img.png is a full-resolution image. -->

<div id="div_whatever"></div>

JQUERY:

$("#img_highQuality").off().on("load", function() {
$("#div_whatever").css({
"background-image" : "url(dir/image.png)"
});
});
// Side note: I usually define CSS arrays because
// I inevitably want to go back and add another
// property at some point.

What happens:

  1. A low-res version of the background quickly loads.
  2. Meanwhile, the higher resolution version is loading as a hidden image.
  3. When the high-res image is loaded, jQuery swaps the div's low-res image with the high-res version.

PURE JS VERSION

This example would be efficient for changing one to many elements.

CSS:

.hidden {
display: none;
}

#div_whatever {
position: whatever;
background-repeat: no-repeat;
background-position: whatever whatever;
background-image: url(dir/image.jpg);
/* image.jpg is a low-resolution at 30% quality. */
}

HTML:

<div id="div_whatever"></div>
<img id="img_whatever" class="hidden" src="dir/image.png" onload="upgradeImage(this);">

JAVASCRIPT:

function upgradeImage(object) {
var id = object.id;
var target = "div_" + id.substring(4);

document.getElementById(target).style.backgroundImage = "url(" + object.src + ")";
}

UPDATE / ENHANCEMENT (1/31/2017)

This enhancement is inspired by gdbj's excellent point that my solution results in the image path being specified in three locations. Although I didn't use gdbj's addClass() technique, the following jQuery code is modified to extract the image path (rather than it being hardwired into the jQuery code). More importantly, this version allows for multiple low-res to high-res image substitutions.

CSS

.img_highres {
display: none;
}

#div_whatever1 {
width: 100px;
height: 100px;
background-repeat: no-repeat;
background-position: center center;
background-image: url(PATH_TO_LOW_RES_PHOTO_1);
}

#div_whatever2 {
width: 200px;
height: 200px;
background-repeat: no-repeat;
background-position: center center;
background-image: url(PATH_TO_LOW_RES_PHOTO_2);
}

HTML

<div id="div_whatever1"></div>
<img id="img_whatever1" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_1">

<div id="div_whatever2"></div>
<img id="img_whatever2" class="img_highres" src="PATH_TO_HIGH_RES_PHOTO_2">

JQUERY

  $(function() {
$(".img_highres").off().on("load", function() {
var id = $(this).attr("id");
var highres = $(this).attr("src").toString();
var target = "#div_" + id.substring(4);
$(target).css("background-image", "url(" + highres + ")");
});
});

What's happens:

  1. Low res images are loaded for each of the divs based on their CSS
    background-image settings. (Note that the CSS also sets the div to the intended
    dimensions.)
  2. Meanwhile, the higher resolution photos are being
    loaded as hidden images (all sharing a class name of img_highres).
  3. A jQuery function is triggered each time an img_highres photo
    completes loading.
  4. The jQuery function reads the image src path, and
    changes the background image of the corresponding div. In the
    example above, the naming convention is "div_[name]" for the visible divs
    and "img_[same name]" for the high res images loaded in the
    background.

How to replace a low resolution background-image with a better one once the higher resolution image has loaded fully?

TLDR:
define the hi-res image to be loaded in your CSS as "invisible"

#hi-res {
visibility: hidden;
}

preload image at the Head

<link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">

and then wait till the DOM has fully loaded to "display" the image with

$(window).load(function(){
document.getElementById('hi-res').style.visibility='visible';
});


So what you're running into is not a 'loading' issue, but a 'rendering' issue. The browser is already doing what it thinks you want it to do, that is: swapping one image for another after it's "loaded", or more accurately "found" in the DOM. The issue then is that the browser is coming across (loading) that hi-res image sooner than when it is able to quickly render it. Essentially you want to specifically have the browser wait to load an image at a point when it can render it quickly.

The preload attribute should help address this in that it is essentially a request on the DOM that says: Yo, you're definitely going to need this soon, so grab it before everything else and in full. That being said, it doesn't mean it will render all that quickly once the browser is told to display the image.

So, if you really want to double tap this to ensure the alternative image does not replace the lo-res one before the browser can devote all it's resources to rendering it on screen you can simply have it explicitly hidden from view until everything else is done loading. You can do this by using CSS:

#hi-res {
visibility: hidden;
}

and then JS on DOM:

$(window).load(function(){
document.getElementById('hi-res').style.visibility='visible';
});

Preloading
Back in the day you could have used lazy loading or even just a simple JS wait script at the bottom of your page.

However, I think the best solution to your problem would be to simply preload your images using rel="preload" as specified in the MDN Web Docs

This could done by preloading the CSS file itself:

<head>
<meta charset="utf-8">
<title>JS and CSS preload example</title>

<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">

<link rel="stylesheet" href="style.css">
</head>

Source

Or more simply on the media elements themselves:

<head>
<meta charset="utf-8">
<title>Responsive preload example</title>

<link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">
<link rel="preload" href="bg-image-wide.png" as="image" media="(min-width: 601px)">

<link rel="stylesheet" href="main.css">
</head>

Source

Fast Image loading methods, low to high res with multiple backgrounds - javascript solution?

//
// You have dozen of hd photos, and don't want to embed them right from the get go
// in order to avoid 'interlaced' load, boost application load, etc.
// Idea is to place lo-res photos, temporarily, in place where hd ones should go,
// while downloading full quality images in the background.
//
// People usualy do this kind of caching by attaching 'onload' event handler to off-screen
// Image object ( created by new Image(), document.createElement('img'), or any
// other fashion ), which gets executed natively by a browser when the event
// ( 'onload' in this case ) occurs, and setting the '.src' property of an image to
// the phisical path ( relative/absolute ) of an img to start the download process.
// The script pressented here use that approach for multiple images,
// and notifies of task done by running provided function.
//
// So, solution is to provide locations of images you want to,
// and get notified when they get fully downloaded, and cached by browser.
// To do that you pass a function as 1st parameter to the fn below,
// passing as many images as needed after it.
//
// Code will scan through provided images keeping the ones that are actualy
// image files( .jpeg, .png, .tiff, etc.), create 'off-screen' Image objects
// and attach onload/onerror/onabort handler fn to each one( which will be called
// when coresponding circumstance occurs ), and initiate loading by setting the
// .src property of an Image object.
//
// After the 'load-handler' has been called the number of times that coresponds to
// number of images ( meaning the dload process is done ), script notifies you
// of job done by running the function you provided as first argument to it,
// additinaly passing images( that are cached and ready to go ) as
// parameters to callback fn you supplied.
//
// Inside the callback you do whatever you do with cached photos.
//
function hd_pics_dload( fn /* ,...hd-s */ ) {

var
n = 0, // this one is used as counter/flag to signal the download end
P = [], // array to hold Image objects

// here goes the image filtering stuff part,
// all the images that pass the 'regex' test
// ( the ones that have valid image extension )
// are considerd valid, and are kept for download
arg_imgs = Array.prototype.filter.call(
Array.prototype.slice.call( arguments, 1 ),
function ( imgstr ) {
return ( /\.(?:jpe?g|jpe|png|gif|bmp|tiff?|tga|iff)$/i ).test( imgstr );
}
);

// aborts script if no images are provided
// runs passed function anyway

if ( arg_imgs.length === 0 ) {
fn.apply( document, arg_imgs );
return arg_imgs;
}

// this part keeps track of number of 'load-handler' calls,
// when 'n' hits the amount of given photos
// provided callback is runned ( signaling load complete )
// and whatever code is inside of it, it is executed.
// it passes images as parameters to callback,
// and sets it's context ( this ) to document object

var hd_imgs_load_handler = function ( e ) {

// logs the progress to the console
console.log( e.type, ' -- > ', this.src );

( ++n === arg_imgs.length )
&& fn.apply( document, arg_imgs );

};

// this part loops through given images,
// populates the P[] with Image objects,
// attaches 'hd_imgs_load_handler' event handler to each one,
// and starts up the download thing( by setting '.src' to coresponding image path )

for (
var i = 0,
len = arg_imgs.length;
i < len;
i++
) {
P[i] = new Image;
P[i].onabort = hd_imgs_load_handler;
P[i].onerror = hd_imgs_load_handler;
P[i].onload = hd_imgs_load_handler;
P[i].src = arg_imgs[i];
}

// it gives back images that are about to be loaded
return arg_imgs;

}
//
// use:

hd_pics_dload(

// 1st provide a function that will handle photos once cached
function () { console.log('done -> ', arguments ); },

// and provide pics, as many as needed, here
// don't forget to separate all parameters with a comma
'http://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Flag_of_the_United_Nations.svg/2000px-Flag_of_the_United_Nations.svg.png',
'http://upload.wikimedia.org/wikipedia/commons/e/e5/IBM_Port-A-Punch.jpg',
'http://upload.wikimedia.org/wikipedia/commons/7/7e/Tim_Berners-Lee_CP_2.jpg',
'http://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/NewTux.svg/2000px-NewTux.svg.png',
'http://upload.wikimedia.org/wikipedia/commons/4/4c/Beekeeper_keeping_bees.jpg',
'http://upload.wikimedia.org/wikipedia/commons/9/9a/100607-F-1234S-004.jpg'
);

//

html load background image lower quality

You could scale the image proportionally to itself with just HTML and CSS but the browser would still load the whole image into memory.

You would need to use some photo editing software to change the resolution of the image and image format to JPEG, which has a better compression algorithm than the PNG image format.

HTML:

<div class="img_resz">
<img src="img.jpg">
</div>

CSS:

.img_resz img 
{
width: 90%;
}

Loading a smaller resolution image until the larger resolution one is done downloading

You could just load the low res one first, as you know it’ll be fairly quick, and then load the high res image once the low res image has been loaded.

Glide.with(this)
.load(lowResImageUrl)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}

@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
Glide.with(yourContext).load(highResImage).into(imageView);
return false;
}
})
.into(imageView)

Loading high res background image

There's no way to make images magically load faster. Sometimes, though, splitting an image in smaller images allows for surprising size gains; so if it's not out of question for your CSS layout (it typically is, though), you could try this.

Another possibility for you would be to use progressive JPEG images. They are encoded in such a way that enables browsers to display a progressively more precise image as it loads. This means that at first, the image appears blurry (or incomplete) but with full-dimensions, then it progressively gets sharper and better. It's well-suited for images meant to load slowly (or at least, images acknowledged to load slowly).

How to change Multiple small-res image source with the actual high-res image after they have been loaded?

As the comment suggests, Progressive image loading like medium can be implemented by using a simple open-source files from GitHub blurry-image-load. Read readme.md and add the necessary files to your project and follow the instruction.

How to load an image from low to high resolution?

You could either use some JS solution for this, as suggested by dantheman93, check out this article on how to recreate it manually, or you could just check out progressive JPGs, as it might be what you are looking for.



Related Topics



Leave a reply



Submit