I'm running Twitter Bootstrap 3.2.

My page has a banner image for every breakpoint. That means code like this:

<img class="visible-xs img-responsive" src="headline-768px.jpg">   (128kb)
<img class="visible-sm img-responsive" src="headline-992px.jpg">   (144kb)
<img class="visible-md img-responsive" src="headline-1200px.jpg">  (264kb)
<img class="visible-lg img-responsive" src="headline-2000px.jpg">  (380kb)

The main purpose of having 4 different images is so that mobile devices don't need to download the larger versions. But Bootstrap preloads all the versions regardless of screen size, even if they're hidden at the current breakpoint. This amounts to hundreds of unnecessary kb for every viewer.

Is there a way around this?

Demo of the Problem:

Not all browsers react the same, but typically browser's will load content from a src attribute, regardless of whether some other CSS rule renders that element as invisible.

Here's a baseline example:

<!-- language: lang-html -->
<img class="visible-xs img-responsive" src="http://placehold.it/768x150" />
<img class="visible-sm img-responsive" src="http://placehold.it/992x150" />
<img class="visible-md img-responsive" src="http://placehold.it/1200x150"/>
<img class="visible-lg img-responsive" src="http://placehold.it/2000x150"/>

Demo in jsFiddle

Whenever I refresh the page, the browser loads all images, even ones that are initially invisible:

load-all

Background Image + Media Queries

This tutorial on Simple Responsive Images With CSS Background Images goes into more depth, but the basic solution works like this:

Create a simple div:

<!-- language: lang-html -->
<div class="responsiveBackgroundImage" id="myImage" ></div>

And then sub in the correct background image depending on the screen size:

We'll probably want all the background images to share a couple basic properties like this:

<!-- language: lang-css -->
.responsiveBackgroundImage { 
    width:100%;
    background-size: 100%;
    background-position: 50% 0%;
    background-repeat: no-repeat;
}   

Then replace the background-image property for this particular element at each resolution:

<!-- language: lang-css -->
#myImage {background-image: url(http://placehold.it/768x150); }
@media (min-width: 768px)  { #myImage { background-image: url(http://placehold.it/992x150); }}
@media (min-width: 992px)  { #myImage { background-image: url(http://placehold.it/1200x150);}}
@media (min-width: 1200px) { #myImage { background-image: url(http://placehold.it/2000x150);}}

Demo in jsFiddle

Replacing Images with Javascript

Due to limitations with using background images, you might decide to use a real img element and then just dynamically load the images. Rather than loading the element itself, you can do something similar to what angular does with ng-src when evaluating an expression that resolves to a url. When the browser loads each element, it wouldn't be able to find the file location of src="{{personImageUrl}}". Instead, Angular saves the intended url as a data attribute and then loads when appropriate.

First, take each of your images and prefix the src attribute with data-. Now the browser won't automatically start implementing anything, but we still have the information to work with.

<!-- language: lang-html --> <pre><code>&lt;img class=&quot;visible-xs img-responsive&quot; <b>data-</b>src=&quot;http://placehold.it/768x150&quot;/&gt; </code></pre>

Then query for all the dynamic images we'll eventually want to load.

<!-- language: lang-js -->
$dynamicImages = $("[data-src]");

Next, we're going to want to capture window resize events, and on the very first page load, we'll trigger one just so we can make use of the same code. Use a function like this:

<!-- language: lang-js -->
$(window).resize(function() {
    // Code Goes Here
}).resize();

Then check if each dynamic image is visible. If so, load the image from the data attribute and remove it from the array so we don't have to keep checking and loading it.

$dynamicImages.each(function(index) {
    if ($(this).css('display') !== 'none') {
        this.src = $(this).data('src');
        $dynamicImages.splice(index, 1)
    }
});

Demo in jsFiddle