bLazy.js – A lazy load image script

2015.11.14: New release, bLazy version 1.5.1

bLazy is a lightweight script for lazy loading and multi-serving images. It’s written in pure JavaScript why it doesn’t depend on 3rd-party libraries such as jQuery. bLazy works on all modern browsers, including on IE7+.


  1. How to use bLazy
  2. Options
  3. Public functions
  4. Responsive Images
  5. Iframes, unity games etc.
  6. With AngularJS
  7. Changelog (github)
  8. License
  9. Support

How to use bLazy (lazy load images)

You can lazy load your images in just two easy steps.

Step 1) Change your image markup a bit.

  • Add class “b-lazy”.
  • Add a placeholder image to the image source (src). In my example I’m using a base64 encoded transparent gif so it won’t do any extra requests.
  • Save the real image source in the data-src attribute
    <img class="b-lazy" 

Step 2) Include blazy.js and initialize it. If you’re using jQuery (or simliar) do it in document.ready:

    <script src="blazy.js"></script>
        ;(function() {
            // Initialize
            var bLazy = new Blazy();

bLazy comes with a few options

Options– key [type] (default value)
breakpoints[array] (false) Multi-serve images based on screen size. Go to multi-serve image example
container [string](window) If you want to lazy load elements inside a scrolling container change the default value to the selector of the container
error [function(ele, msg)] (false) Callback for when something goes wrong. There are two error messages, missing and invalid. You’ll get missing if no data-src is defined. Invalid if the data-src is invalid. Go to callback example
errorClass [string](‘b-error’) The classname an element will get if something goes wrong.
loadInvisible [bool](false) Set to true if you want to load invisible (hidden) elements.
offset [int] (100) The offset controls how early you want the elements to be loaded before they’re visible. Default is 100, so 100px before an element is visible it’ll start loading.
saveViewportOffsetDelay [int] (50) Delay for how often it should call the saveViewportOffset function on resize. Default is 50ms.
selector[string] (‘.b-lazy’) Element selector for elements that should lazy load. If you want to lazy load all images write ‘img’. You can add multiple selectors separated with comma; ‘.b-lazy, .bLazy, .blazy’.
separator [char](‘|’) Used if you want to pass retina images: data-src=”image.jpg|image@2x.jpg”. Go to the retina image example
src [string] (‘data-src’) Attribute where the original element source can be found
success [function(ele)] (false) Callback for when an image has loaded. Go to callback example
successClass [string](‘b-loaded’) The classname an element will get when loaded.
validateDelay [int](25) Delay for how often it should call the validate function on scroll/resize. Default is 25ms.

You pass the options as an object of key/value pairs:

    // Format
    var bLazy = new Blazy({ 
        key: value
      , key: value
      , key: value


You can change the selector if you don’t want to add the ‘b-lazy’ class or if you need to have multiple.

    // Example
    var bLazy = new Blazy({ 
        selector: 'img' // all images


The offset controls how early you want the elements to be loaded before they’re visible. Default is 100, so 100px before an element is visible it’ll start loading.

    // Example
    var bLazy = new Blazy({ 
        offset: 100 // Loads images 100px before they're visible

Images inside a container

You can also lazy load images inside a scrolling container, just define the selector of the container:

    // Example
    var bLazy = new Blazy({ 
        container: '#scrolling-container' // Default is window

Callback when image has loaded or fails

If you need to do anything when an image has loaded or fails you can pass a callback function:

    // Example
    var bLazy = new Blazy({ 
        success: function(ele){
            // Image has loaded
            // Do your business here
      , error: function(ele, msg){
            if(msg === 'missing'){
                // Data-src is missing
            else if(msg === 'invalid'){
                // Data-src is invalid

Retina images

If you’re not doing retina-first don’t worry. It’s easy to serve retina images for retina displays. Just add the source to the retina image in the data-src by using the separator (default is ‘|’) and bLazy will do the rest:

    <img class="b-lazy" 

Background images

You can also lazy load background images. If the element with the lazy load class (default: ‘.b-lazy’) isn’t an image, the source will be added to the element as a background image:

    <div class="b-lazy" data-src="background-image.jpg"</div>

Multi-serve images

You can multi-serve images, so users on smaller devices will get a smaller image served and the page will load faster. If you have more than one it’s important that the widths are ascending like in my example; 420 comes before 768. If you set up a multi rule but your image markup doesn’t have the src attribute on it, it’ll look after the default src, data-src.

    // Example
    var bLazy = new Blazy({ 
        breakpoints: [{
	          width: 420 // max-width
		, src: 'data-src-small'
           , {
	          width: 768 // max-width
	        , src: 'data-src-medium'

Image markup:

    <img class="b-lazy" 

Image transitions

Image transitions are not a built-in feature in bLazy.js but you can easily add it with css. When an image has loaded a loaded class (default: b-loaded) is added to the image, so you can add:

    .b-lazy {
        -webkit-transition: opacity 500ms ease-in-out;
           -moz-transition: opacity 500ms ease-in-out;
             -o-transition: opacity 500ms ease-in-out;
                transition: opacity 500ms ease-in-out;
                 max-width: 100%;
                   opacity: 0;
    .b-lazy.b-loaded {
                   opacity: 1;

Public functions

Public functions
revalidate() Revalidates document for visible images. Useful if you add images with scripting or ajax
load(element(s), force) Forces the given element(s) to load if not collapsed. If you also want to load a collapsed/hidden elements you can add true as the second parameter.
You can pass a single element or a list of elements. Tested with getElementById, getElementsByClassName, querySelectorAll, querySelector and jQuery selector.
destroy() Unbind events and resets image array
    // Example
    var bLazy = new Blazy();
    bLazy.functionName(); // eg bLazy.revalidate();

Responsive images

An example on how to lazy load and multi-serve responsive images without having the page reflow.


    <div class="image-wrapper ratio_16-9">
      <img class="b-lazy" 
      <!-- Fallback for non JavaScript browsers -->
      <noscript><img src="image.jpg" alt="alt-text" /></noscript> 


    .image-wrapper {
        // Adding a loader and background color. The user will see it
	// if the image is loading slow.
        background: #1E1E1E url('loader.gif') center center no-repeat;
        width: 100%
    .ratio_16-9 {
        // The image has a 16/9 ratio. Until the image has loaded
        // we need to reserve some space so the page won't reflow.
        // How to calculate the space (padding-bottom): 9/16*100 = 56.25
        // Another example: you have an image 400x250.
        // So if you want to calculate the space you do: 250/400*100 = 62.5
        padding-bottom: 56.25%; 
        height: 0;
        .b-lazy {
            max-width: 100%;

Iframes, unity games etc.

With blazy.js you can lazy load everything with a src attribute, not only images. For example iframes:

<iframe class="b-lazy" data-src="page.html" width="300" height="300">
 <p>Your browser does not support iframes.</p>

With AngularJS

Some users have asked if they can use blazy.js together with angular.js. The short answer is yes. Blazy.js is just plain javascript why you of course can do that. However since angular strippes the data-prefix from attribute names as part of the directive-name normalization process you either need to:

  • change the default data-src name because otherwise it’s like setting two src’s and firefox and chrome handles that differently.
  • or don’t have any default src.
// Example
var bLazy = new Blazy({ 
    src: 'data-blazy' // Default is data-src

<img class="b-lazy"    


<img class="b-lazy" data-src="image.jpg" alt="alt-text" />


bLazy is licensed under MIT and the DWIWYWBPVMS license. (Do With It What You Want But Please Visit My Sponsor).


Support bLazy by visiting my sponsor:

bPopup.js – A jQuery modal popup plugin

01.24.15: New release, bPopup version 0.11.0

01.16.14: Sadly my host has had serious server issues why all old comments are gone!

bPopup is a learning and exploring jQuery project. It’s a lightweight cross browser jQuery popup plugin. It’s not creating your popup but doing all the logic as opening, closing, centering on resize & scroll, creating a modal overlay etc. It can open any container you create with all kinds of content. bPopup has been tested in IE67-9, FF2-7, Opera 9-10, Safari 4-5 and Chrome 4-15.


  1. How to use bPopup
  2. Options (API)
  3. Changelist (github)
  4. What can you do?
  5. License
  6. Support

How to use bpopup

» Click here to see a jsfiddle you can play with! « Basic example that will bind a click event which will trigger bPopup when fired. Add a reference to the jquery core lib (newer than 1.3.x) and bPopup. Please don’t hotlink to bPopup:

    <script src=""></script>
    <script src="jquery.bpopup-x.x.x.min.js"></script>

Markup: Add a button + an element to pop up.

        <head> ... </head>
            <!-- Button that triggers the popup -->
            <button id="my-button">POP IT UP</button>
            <!-- Element to pop up -->
            <div id="element_to_pop_up">Content of popup</div>

CSS: Hide the element you want to pop up on page load.

    #element_to_pop_up { display:none; }

The magic: Bind a click event on the button which will trigger the popup.

    // Semicolon (;) to ensure closing of earlier scripting
    // Encapsulation
    // $ is assigned to jQuery
    ;(function($) {

         // DOM Ready
        $(function() {

            // Binding a click event
            // From jQuery v.1.7.0 use .on() instead of .bind()
            $('#my-button').bind('click', function(e) {

                // Prevents the default action to be triggered. 

                // Triggering bPopup when click event is fired




Or with custom settings

    ;(function($) {
        $(function() {
            $('#my-button').bind('click', function(e) {
                    appendTo: 'form'
                    , zIndex: 2
                    , modalClose: false



API – name [type] (default value)
amsl[int] (50) Above Mean Sea Level. Vertical distance from the middle of the window, + = above, – = under.
appendTo [string] (’body’) Element to append popup (and modal overlay) to. For sites append to ‘form’.
appending [bool] (true) Should the popup append to an element or just open where it is? Version 0.7.0
autoClose[int] (false) Auto close the popup after x amount of ms, autoClose: 1000 = auto closes after 1 sec. Version 0.9.4
closeClass [string] (‘b-close’) Class to bind the close event to. Version 0.3.3
content [string] (‘ajax’) Content of bpopup. Types: [‘ajax’, ‘iframe’, ‘xlink‘, ‘image’ (Added in version 0.9.0)]. If loadUrl isn’t defined it’ll not use content type. Version 0.4.1
contentContainer [string] (false) Element which content should be added to. If undefined/null it will add it to $(this). Usage contentContainer:’.element’ or contentContainer:’#element’. Version 0.4.1
easing [string] (‘swing’) The easing of the popup when it opens. ‘swing’ and ‘linear’ are built-in in jQuery. If you want more you can use the jQuery Easing plugin. Version 0.9.0
escClose [bool] (true) Should popup close when press on escape?
follow [bool,bool] ([true,true]) Should the popup follow the screen vertical and/or horizontal on scroll/resize? [horizontal, vertical, fixed on screen (see positionStyle instead)] Version 0.3.6. Changed in version 0.5.0 and again in version 0.6.0 and again in version 0.7.0.
followEasing [string] (‘swing’) The follow easing of the popup. ‘swing’ and ‘linear’ are built-in in jQuery. If you want more you can use the jQuery Easing plugin. Version 0.9.0
followSpeed [int/string] (500) Animation speed for the popup on scroll/resize. Version 0.3.6
iframeAttr [string] (‘scrolling=”no” frameborder=”0″‘) Gives you the possibility to customize the built-in iframe support. Default removes the scrollbar and border. Version 0.9.4
loadData [object or string] (false) LoadData is representing the data attribute in the jQuery.load() method. It gives you the opportunity to submit GET or POST values through the ajax request. Version 0.9.0
loadUrl [string] (false) External page or selection to load in popup. See loadCallback for callback. Version 0.3.4
modal [boolean] (true) Should there be a modal overlay behind the popup?
modalClose [bool] (true) Should the popup close on click on overlay? Version 0.4.0
modalColor [string] (‘#000′) What color should the overlay be? Version 0.3.5
opacity [float] (0.7) Transparency, from 0.1 to 1.0 (filled). Version 0.3.3
position [int,int] ([‘auto’,’auto’]) Defines the position where the popup should pop up. ‘auto’ = center, [horizontal, vertical] Version 0.5.0. Changed in version 0.7.0, swapped positions so it’s now x, y instead of y, x
positionStyle [string] (‘absolute’) The popup’s position. ‘absolute’ or ‘fixed’ Version 0.7.0
scrollBar [bool] (true) Should scrollbar be visible?
speed [int/string] (250) Animation speed on open/close. Version 0.9.0
transition [string] (‘fadeIn’) The transition of the popup when it opens. Types: [‘fadeIn’, ’slideDown’, ’slideUp’, ’slideIn’, ’slideBack’]. Version 0.9.0 / 0.9.4
transitionClose [string] (false) The transition of the popup when it closes. Default (false) will use same as defined in transition above. Types: [‘fadeIn’, ’slideDown’, ’slideUp’, ’slideIn’, ’slideBack’]. Version 0.9.4
zIndex [int] (9999) Popup z-index, modal overlay = popup z-index – 1.
callback Event fires after the popup has loaded.Usage: $(‘element_to_pop_up’).bPopup({ //options }, function(){ //callback }); Version 0.3.5
loadCallback Callback for loadUrl, triggers when the loadUrl is loaded: $(‘element_to_pop_up’).bPopup({ loadUrl: ‘test.html’, loadCallback: function(){ //doMagic }}); Version 0.8.0
onOpen Event fires before the popup opens.Usage: $(‘element_to_pop_up’).bPopup({ onOpen: function(){ //doMagic }}); Version 0.5.0
onClose Event fires after the popup closes.Usage: $(‘element_to_pop_up’).bPopup({ onClose: function(){ //doMagic }}); Version 0.5.0
Public Function
close() Closes the popup. Usage:
var bPopup = $(‘element_to_pop_up’).bPopup();
Version 0.4.0
reposition(animateSpeed) Recalculates the center position of the popup. The animate speed attribute is optional. If not defined it will use the “followSpeed” value. Usage:
var bPopup = $(‘element_to_pop_up’).bPopup();
Version 0.10.0
Recycle Bin – not there anymore
duration[int/string] (‘normal’) Animation speed.Removed in version 0.3.6 – See fadeSpeed and followSpeed.
fadeSpeed [int/string] (250) Animation speed on fadeIn/out. Version 0.3.6. Renamed in version 0.9.0 – see speed instead
minTop [int] (20) Minimum distance from top to popup. Removed in version 0.3.6
vStart [int] (null) Vertical start position for popup. Version 0.3.6, Removed in version 0.5.0 – See Position.
xLink [boolean] (false) Is the popup a xlink popup? Version 0.3.4, Removed in version 0.4.1 use content type instead (content:’xlink’)


The change-list will be updated on github in the future:

0.9.0 change-list (26.02.13):

  • New option: transition: ‘fadeIn’. Now you can change the way the popup should pop up. Default is fadeIn as it always has been, but now it can also ‘slideDown’ or ‘slideIn’. More to follow!
  • New option: loadData: false. loadData is representing the data attribute in the jQuery.load() method. It gives you the opportunity to submit GET or POST values through the ajax request.
  • New option: easing: ‘swing’ and followEasing: ‘swing’. Now you can control the easing effect on open and follow. In jQuery there are two kinds of easings, swing as default and linear. If you want more you can include a plugin like the jQuery easing plugin.
  • New feature: New content type added, ‘image’. When using loadUrl (ajax or image) it will recenter when the request has loaded. Be aware of the animate height/width bug in jQuery 1.9.0 ( It’s fixed in version 1.9.1.
  • Changed: Renamed the option fadeSpeed to speed. The name fadeSpeed doesn’t make sense anymore after I added the new transitions.
  • Changed: Skipped the lowerCamelCase naming convention, sorry, I just don’t like it. bClose is now b-close, bModal b-modal and so on.
  • Bugfix: Closing the popup while scrolling will now always close the popup entirely.

0.8.0 change-list (09.01.13):

  • Bugfix: Closing a popup with the public close method didn’t unbind the click events properly. The bug was only present if used with multiple popups (Thanks to Ben Meyers for reporting it).
  • Bugfix: Resizing with positionStyle: fixed didn’t center.
  • Bug: Apple introduced a timer bug in IOS6 when zooming/scrolling and didn’t fix it in the latest release 6.0.1, why I temporary disabled the scroll/resize events in bPopup but only for iDevices with IOS 6 or 6.0.1. I need more time to investigate for a better solution but hopes that Apple will fix it in the next IOS release. I found some fixes which are working but I’ll not implement them in bPopup at the time. Fix 1: Fix 2: If you want to use one of them include the script before bPopup and remove “isIOS6X” from bPopup (2 places).
  • Changed: The closeclass is now using delegate() instead of the more heavy live() event handler. Important note – this means that bPopup now is depending on jQuery 1.4.2+ instead of 1.3.0+. Is someone using jQuery below version 1.4.2?
  • New option: loadCallback. When using loadUrl you can now define a callback.
  • Cleaned code a bit.

0.7.0 change-list (21.04.12):

  • Bugfix: Multiple popup count fix (Thanks to Michael for reporting)
  • Bugfix: Callback now returns ‘this’ instead of ‘window’ (Thanks to Jeppe for reporting)
  • Bugfix: Scroll before popup is loaded opacity fix
  • Bugfix: Moved initialization of popup to after onOpen event so it will center properly when adding stuff onOpen.
  • Changed: Important note – Swapped arguments in Position so it now takes [x, y] instead of [y, x] like everything else in the world.
  • Changed: Important note – Also swapped arguments in Follow so it also takes [x, y] instead of [y, x] and removed third argument. See positionStyle instead.
  • New option: appending: true. Defines if the popup should append to an element or just open where it is.
  • New option: positionStyle: ‘absolute’. Defines the position style which has impact on how the popup follows on scroll and resize. Absolute or fixed.
  • Removed private function, getDistanceToBodyFromLeft().

0.6.0 change-list (29.10.11):

  • New feature: Supports multiple bPopups. Now you can open all the bPopups you want on top of each other.
  • New feature: Won’t follow if popup is bigger then the window.
  • Changed: Added 3rd parameter to follow, default false. If true the popup will be fixed on the screen.
  • Removed: Browser detecting is bad why I removed the check for IE6. IE6 doesn’t support position: fixed but I don’t support IE6 any more. I’m afraid I killed it. It’s easy to add if you still need to support IE6.

0.5.1 change-list (13.04.11):

  • Bugfix: Added a duration time to the hide() call so onOpen and loadUrl always will be trigged when needed.
  • Bugfix: Added frameborder=”0″ and scrolling=”no” to iframe to remove borders in IE. Removed width=”100%” and height=100%” from iframe so you have full control over the iframe
  • Code update: updated the logic regarding follow and position

0.5.0 change-list (12.03.11):

  • bPopup, now with more control and features!
  • New events: onOpen and onClose
  • New option: Position[‘auto’,’auto’]. Replacing vStart. Gives you full control where the popup should be.
  • Changed option: follow changed to array of booleans, follow[true,true]. Defines if the popup should follow vertical and/or horizontal.
  • Changed option: default value for amsl changed from 150px to 50px.
  • Removed option: vStart, see Position.
  • Removed feature: the popup doesn’t auto reset input fields or auto focus any more. If you need this feature do the magic inside the onOpen event.
  • Removed feature: xlink removed from content type. Instead do the xlink stuff inside the onOpen event.
  • Bugfix: Modal overlay fits whole screen on an iphone in safari.
  • Known issue: The popup doesn’t center properly when zooming on an iphone in safari.

0.4.1 change-list (17.10.10):

  • New option: content, now it’s possible to load content into the popup through Ajax or in an iframe. It takes the url from loadUrl.
  • New option: contentContainer, gives you the possibility to load content into a small area of the popup e.g. a div at the bottom.
  • Removed option: xLink, use content type instead (content:’xlink’)!

0.4.0 change-list (22.09.10):

  • Attention: In this update there has been changes that affect how you interact with the popup!
  • New option: modalClose (should the popup close on click on overlay?)
  • New way to create the popup.You should now call $(selector).bPopup() instead of $(selector).openPopup().
  • New way to force popup to close. Force close by calling the public function close(), $(selector).bPopup().close(), instead of triggering the close event with $(‘.bClose’).closePopup(). This will stop cluttering up the $.fn namespace.
  • Changed default value for opacity from 0.5 to 0.7
  • Ensures that the same popup can’t be opened twice at a time.
  • Next update will include support for iframes, generic xlink support and more.

0.3.6 change-list (14.07.10):

  • New options: fadeSpeed, follow, followSpeed, vStart
  • Deleted: duration, minTop
  • Included position:absolute styling on popup in plugin

0.3.5 change-list (05.07.10):

  • New option: modalColor
  • bPopup can now take callback functions

0.3.4 change-list:

  • New option: loadUrl
  • The popup can now open an url inside the popup
  • Implemented x-link feature
  • Refactored code, created private help functions
  • Changed default value for scrollBar to true

0.3.3 change-list:

  • New options: opacity, closeClass
  • Changed modal overlay to position fixed in supported browsers. Non position fixed supported browsers still uses position absolute.
  • Added default close event
  • Fixed issue with overlay in IE6+7 and body positioned relative with a width

0.3.2 change-list:

  • Modal overlay width miscalculation on resize.
  • Auto textfield focus
  • Resetting textfields before showing popup

0.3.1 change-list:

  • New options: escClose, zIndex and minTop.
  • Fixed bug with modal overlay when body has position: relative and a width. Now calculates the distance from the left to the body.

0.3.0 change-list:

  • Unbind events on close.
  • Centering popup on resize.
  • Centering popup on horizontal scroll.
  • Refactor code.

What can you do?

  • Report bugs
  • Help optimizing code
  • Give suggestions


bPopup is licensed under the DWIWYWBPVMS license. (Do With It What You Want But Please Visit My Sponsor).


Support bPopup by visiting my sponsor:

How to fix jQuery.load() in IE for cached images

Solution 1, removing the cache by adding a datetime string to the image src:

      .attr('src', 'image_url?' + new Date().getTime())
      .load(function() {
         alert('Image loaded');

This solution works almost everytime but sometimes it has introduced even more IE weirdness for me. It can also be an costly affair if you have many visitors why I have tried alternatives. I ended up with solution 2 and it seems to work everytime! :)

Solution 2 (improved), adding the src after the load() call seems to do the trick as well and will keep the cache:

      .load(function() {
         alert('Image loaded');
      }).attr('src', 'image_url');




Does google index lists created with angular’s ng-repeat directive?