JavaScript library v3.0.9 Build status

Source code on GitHub
Package on npm

Lazy-loading responsive images. HTML5's picture element as well as srcset and sizes attributes. Our JavaScript library does all the heavy lifting for you. Works in browsers and Node.js.

Installation

Browser

Download our library and insert it above the closing </body> tag in your HTML. It's 87 kB (24 kB gzipped).

<script src="tiny.pictures.min.js"></script>

This file will expose the library class as the global variable TinyPictures.

Node.js

npm install --save tiny.pictures-js

Just add var TinyPictures = require('tiny.pictures-js') to your code and use the factory class in the TinyPictures variable.

Demo

Start a local demo server with the following command:

npm run demo

Then point your browser to http://localhost:3000/ to see the SDK's functions in action.

Usage

Once the class is loaded and stored in a variable, you can instantiate it by supplying an options object.

var tinyPictures = new TinyPictures(options)

Example

var tinyPictures = new TinyPictures({
    // window is only necessary when run in a browser
    window: window,
    user: 'demo'
})

Options

window (Window)
Mandatory when used in a browser. The global window object.
user (string)
Mandatory. Your tiny.pictures user name.
overrideSourcesImages (string[]|string|boolean)
Optional. Default []. Use this to supply a set of replacement images that are used instead of images from non-public hosts such as localhost during development. Can be an array of publicly available image URLs, a string that specifies the desired type of image ('random', 'abstract', 'animals', 'business', 'cats', 'city', 'food', 'nightlife', 'fashion', 'people', 'nature', 'sports', 'technics', or 'transport'), or a boolean (true for 'random' and false for []).
overrideSourcesAlways (boolean)
Optional. Default false. Set to true to always replace the original source images by overrideSourcesImages, even if they were publicly available.
While being very useful and funny during development, this may have a serious impact on your employment status if used in production. Use with caution!
protocol ('https'|'http')
Optional. Default 'https'. Set to 'http' if you are running a non-TLS-encrypted website to save your users' devices from unnecessary computation time.
defaultBaseUrl (string)
Optional. Default ''. This value is used by the url function as the default baseUrl parameter.
namedSources ({name: string, url: string}[])
Optional. Default []. An array of objects describing the named sources you configured on your dashboard. Copy the array directly from the integration tab. If a source image URL starts with one of your named sources, you'll get a prettier tiny.pictures URL (e. g. https://demo.tiny.pictures/main/example1.jpg).
srcsetWidths (int[])
Optional. Default is a quite long list of image widths. This list is used whenever an img tag's srcset attribute is created.
lazySizesConfig (object)
Optional. Configuration object that is passed to the lazysizes library used for lazy loading and automatic sizes calculation.

API

url

This function converts any image URL to a tiny.pictures URL. You can specify image processing operations in the options object.

Function parameters

url (string)
URL of the original image.
options (object)
Optional. Default {}. Object containing the image processing options you'd like to be applied.
baseUrl (string)
Optional. No default. Base url that url gets resolved against, if url is a relative URL. Throws an error if not set and url is relative. Is set to the current page's URL (location.href) automatically in the browser.

Function returns

string

Examples

tinyPictures.url('https://tiny.pictures/image.jpg')
// 'https://demo.tiny.pictures/main/image.jpg'

tinyPictures.url('https://tiny.pictures/image.jpg', {width: 200})
// 'https://demo.tiny.pictures/main/image.jpg?width=200'

// In the browser when on page https://tiny.pictures/index.html:
tinyPictures.url('image.jpg', {width: 200})
// https://demo.tiny.pictures/main/image.jpg?width=200

tinyPictures.url('//other.domain/path/to/image.jpg', {width: 200})
// https://demo.tiny.pictures/?width=200&source=https%3A%2F%2Fother.domain%2Fpath%2Fto%2Fimage.jpg

// In Node.js:
tinyPictures.url('image.jpg', {width: 200})
// throws error

tinyPictures.url('image.jpg', {width: 200}, 'https://tiny.pictures/index.html')
// https://demo.tiny.pictures/main/image.jpg?width=200

reveal

This function automatically replaces URLs of img tags to tiny.pictures URLs. You can use and combine any image processing operation you like. Operations are specified as data-attributes (see below) in the image tag.

tiny.pictures can automatically calculate a srcset and sizes attribute that enables the browser to decide which image size to load for an optimal user experience on your website. See the data-tp-sizes attributes below for details.

We automatically convert img elements to HTML5's picture elements in order to enable automatic support for the WebP image format. To disable this behavior, use the tp-no-picture class on the img element.

Please also consider using this function via our jQuery plugin for convenience.

Function parameters

img (DOM node)
Native DOM node of the image.

Function returns

undefined

img tag attributes

data-tp-src (string)
URL of the original image. It gets transformed into a tiny.pictures URL and is put into the src attribute.
data-tp-options (JSON)
Optional. No default. JSON representation of an options object specifying the operations you'd like to apply. For example, to resize the image to a width of 200 pixels and flip the image, use data-tp-options='{"width": 200, "flip": true}' (note the single quotes).
data-tp-sizes ('auto')
Optional. No default. Use this to enable automatic srcset calculation. Set to any valid value for the sizes HTML attribute or set to auto (literally) for automatic sizes calculation. For details, see the documentation of the lazysizes library.

img classes

tp-nopicture
Optional. If set, the img element is not wrapped by a picture element.

Examples

<img data-tp-src="https://tiny.pictures/example1.jpg" class="tp-nopicture">
<!-- tiny.pictures url is used as the src. -->
<!-- src="https://demo.tiny.pictures/main/example1.jpg" -->

<img data-tp-src="https://tiny.pictures/example1.jpg">
<!-- tiny.pictures url is used as the only value in a srcset. img is wrapped in picture element. -->
<!-- srcset="https://demo.tiny.pictures/main/example1.jpg" -->

<img data-tp-src="https://tiny.pictures/example1.jpg" data-tp-options='{"width":200}'>
<!-- tiny.pictures url is used as the only value in a srcset. img is wrapped in picture element. -->
<!-- srcset="https://demo.tiny.pictures/main/example1.jpg?width=200" -->

<img data-tp-src="https://tiny.pictures/example1.jpg" sizes="100vw, (min-width: 800px) 50vw">
<!-- The browser decides which file to load based on the user's viewport width and display density. img is wrapped in picture element. -->
<!-- srcset="https://demo.tiny.pictures/main/example1.jpg?width=50 50w, https://demo.tiny.pictures/main/example1.jpg?width=75 75w, https://demo.tiny.pictures/main/example1.jpg?width=100 100w, https://demo.tiny.pictures/main/example1.jpg?width=120 120w, https://demo.tiny.pictures/main/example1.jpg?width=180 180w, https://demo.tiny.pictures/main/example1.jpg?width=360 360w, https://demo.tiny.pictures/main/example1.jpg?width=540 540w, https://demo.tiny.pictures/main/example1.jpg?width=720 720w, https://demo.tiny.pictures/main/example1.jpg?width=900 900w, https://demo.tiny.pictures/main/example1.jpg?width=1080 1080w, https://demo.tiny.pictures/main/example1.jpg?width=1296 1296w, https://demo.tiny.pictures/main/example1.jpg?width=1512 1512w, https://demo.tiny.pictures/main/example1.jpg?width=1728 1728w, https://demo.tiny.pictures/main/example1.jpg?width=1944 1944w, https://demo.tiny.pictures/main/example1.jpg?width=2160 2160w, https://demo.tiny.pictures/main/example1.jpg?width=2376 2376w, https://demo.tiny.pictures/main/example1.jpg?width=2592 2592w, https://demo.tiny.pictures/main/example1.jpg?width=2808 2808w, https://demo.tiny.pictures/main/example1.jpg?width=3024 3024w" sizes="100vw, (min-width: 800px) 50vw" -->

<img data-tp-src="https://tiny.pictures/example1.jpg" data-tp-sizes="auto">
<!-- The browser decides which file to load based on the user's viewport width and display density. img is wrapped in picture element. -->
<!-- srcset="https://demo.tiny.pictures/main/example1.jpg?width=50 50w, https://demo.tiny.pictures/main/example1.jpg?width=75 75w, https://demo.tiny.pictures/main/example1.jpg?width=100 100w, https://demo.tiny.pictures/main/example1.jpg?width=120 120w, https://demo.tiny.pictures/main/example1.jpg?width=180 180w, https://demo.tiny.pictures/main/example1.jpg?width=360 360w, https://demo.tiny.pictures/main/example1.jpg?width=540 540w, https://demo.tiny.pictures/main/example1.jpg?width=720 720w, https://demo.tiny.pictures/main/example1.jpg?width=900 900w, https://demo.tiny.pictures/main/example1.jpg?width=1080 1080w, https://demo.tiny.pictures/main/example1.jpg?width=1296 1296w, https://demo.tiny.pictures/main/example1.jpg?width=1512 1512w, https://demo.tiny.pictures/main/example1.jpg?width=1728 1728w, https://demo.tiny.pictures/main/example1.jpg?width=1944 1944w, https://demo.tiny.pictures/main/example1.jpg?width=2160 2160w, https://demo.tiny.pictures/main/example1.jpg?width=2376 2376w, https://demo.tiny.pictures/main/example1.jpg?width=2592 2592w, https://demo.tiny.pictures/main/example1.jpg?width=2808 2808w, https://demo.tiny.pictures/main/example1.jpg?width=3024 3024w" sizes="500px" -->

<script src="tiny.pictures.min.js"></script>
<script>
    var tinyPictures = new TinyPictures({
        window: window,
        user: 'demo'
    })
    var list = document.getElementsByTagName('img')
    for (var i = 0; i < list.length; i++) {
        tinyPictures.reveal(list[i])
    }
</script>

Benefits

The following image is loaded with

<img data-tp-src="https://tiny.pictures/example1.jpg" data-tp-sizes="100vw">

Depending on the user's viewport and display density, the browser loads different images for the fastest possible load time and best user experience. Notice that mobile users may save up to 94.4 % bandwidth in this example.

URLSize
/?width=200&source=...8.5 kB
/?width=300&source=...16.7 kB
/?width=400&source=...27.6 kB
/?width=500&source=...42.2 kB
/?width=600&source=...57.9 kB
/?width=700&source=...78.2 kB
/?width=800&source=...98.7 kB
/?width=900&source=...122.0 kB
/?width=1000&source=...151.0 kB

Demo image loaded by the srcset attribute

For detailed insights into responsive images and why you should also use the sizes attribute, read Jason Grigsby's excellent Responsive Images 101 Series or the illustrative Srcset and sizes by Eric Portis.

revealAll

This is a convenience function to execute reveal on all img tags.

Function parameters

None

Function returns

undefined

lazyload

This function does the same as the revealAll function except that it defers image loading to when the user actually scrolls down to them. Set the tp-lazyload class to images you'd like to be loaded lazily.

It sets the images' src attribute as soon as the user is about to scroll the image into view (300 pixels above).

Function parameters

None

Function returns

undefined

Examples

<img class="tp-lazyload" data-tp-src="https://tiny.pictures/example1.jpg">
<!-- tiny.pictures url is used as the only value in a srcset. img is wrapped in picture element. -->
<!-- class="tp-lazyloaded" srcset="https://demo.tiny.pictures/main/example1.jpg" -->

<img class="tp-lazyload" data-tp-src="https://tiny.pictures/example1.jpg" data-tp-options='{"width":200}'>
<!-- tiny.pictures url is used as the only value in a srcset. img is wrapped in picture element. -->
<!-- class="tp-lazyloaded" srcset="https://demo.tiny.pictures/main/example1.jpg?width=200" -->

<img class="tp-lazyload" data-tp-src="https://tiny.pictures/example1.jpg" sizes="100vw, (min-width: 800px) 50vw">
<!-- The browser decides which file to load based on the user's viewport width and display density. img is wrapped in picture element. -->
<!-- class="tp-lazyloaded" srcset="https://demo.tiny.pictures/main/example1.jpg?width=50 50w, https://demo.tiny.pictures/main/example1.jpg?width=75 75w, https://demo.tiny.pictures/main/example1.jpg?width=100 100w, https://demo.tiny.pictures/main/example1.jpg?width=120 120w, https://demo.tiny.pictures/main/example1.jpg?width=180 180w, https://demo.tiny.pictures/main/example1.jpg?width=360 360w, https://demo.tiny.pictures/main/example1.jpg?width=540 540w, https://demo.tiny.pictures/main/example1.jpg?width=720 720w, https://demo.tiny.pictures/main/example1.jpg?width=900 900w, https://demo.tiny.pictures/main/example1.jpg?width=1080 1080w, https://demo.tiny.pictures/main/example1.jpg?width=1296 1296w, https://demo.tiny.pictures/main/example1.jpg?width=1512 1512w, https://demo.tiny.pictures/main/example1.jpg?width=1728 1728w, https://demo.tiny.pictures/main/example1.jpg?width=1944 1944w, https://demo.tiny.pictures/main/example1.jpg?width=2160 2160w, https://demo.tiny.pictures/main/example1.jpg?width=2376 2376w, https://demo.tiny.pictures/main/example1.jpg?width=2592 2592w, https://demo.tiny.pictures/main/example1.jpg?width=2808 2808w, https://demo.tiny.pictures/main/example1.jpg?width=3024 3024w" sizes="100vw, (min-width: 800px) 50vw"-->

<img class="tp-lazyload" data-tp-src="https://tiny.pictures/example1.jpg" data-tp-sizes="auto">
<!-- The browser decides which file to load based on the user's viewport width and display density. img is wrapped in picture element. -->
<!-- class="tp-lazyloaded" srcset="https://demo.tiny.pictures/main/example1.jpg?width=50 50w, https://demo.tiny.pictures/main/example1.jpg?width=75 75w, https://demo.tiny.pictures/main/example1.jpg?width=100 100w, https://demo.tiny.pictures/main/example1.jpg?width=120 120w, https://demo.tiny.pictures/main/example1.jpg?width=180 180w, https://demo.tiny.pictures/main/example1.jpg?width=360 360w, https://demo.tiny.pictures/main/example1.jpg?width=540 540w, https://demo.tiny.pictures/main/example1.jpg?width=720 720w, https://demo.tiny.pictures/main/example1.jpg?width=900 900w, https://demo.tiny.pictures/main/example1.jpg?width=1080 1080w, https://demo.tiny.pictures/main/example1.jpg?width=1296 1296w, https://demo.tiny.pictures/main/example1.jpg?width=1512 1512w, https://demo.tiny.pictures/main/example1.jpg?width=1728 1728w, https://demo.tiny.pictures/main/example1.jpg?width=1944 1944w, https://demo.tiny.pictures/main/example1.jpg?width=2160 2160w, https://demo.tiny.pictures/main/example1.jpg?width=2376 2376w, https://demo.tiny.pictures/main/example1.jpg?width=2592 2592w, https://demo.tiny.pictures/main/example1.jpg?width=2808 2808w, https://demo.tiny.pictures/main/example1.jpg?width=3024 3024w" sizes="500px" -->

<script src="tiny.pictures.min.js"></script>
<script>
    var tinyPictures = new TinyPictures({
        window: window,
        user: 'demo'
    })
    tinyPictures.lazyload()
</script>

jQuery

You may register tiny.pictures as a jQuery plugin. This creates a tinyPictures function, that executes the reveal function for all matching DOM nodes.

Example

<img data-tp-src="https://tiny.pictures/example.jpg" data-tp-options='{"width":200}'>
<script src="jQuery.js"></script>
<script src="tiny.pictures.min.js"></script>
<script>
    var tinyPictures = new TinyPictures({
        window: window,
        user: 'demo'
    })
    tinyPictures.registerJQueryPlugin(jQuery)
    jQuery('img').tinyPictures({"width":200})
</script>
<!-- src="https://demo.tiny.pictures/main/example.jpg?width=200" -->

AngularJS (a.k.a. Angular 1)

If the SDK is loaded after AngularJS, it automatically registers a tiny.pictures module and a filter called tinyPicturesUrl, that exposes the url function for use in templates.

Example

<script src="angular.js"></script>
<script src="tiny.pictures.min.js"></script>
<script>
    var tinyPictures = new TinyPictures({
        window: window,
        user: 'demo'
    })
    tinyPictures.registerAngularJsModule(angular)
    angular.module('yourApp', ['tiny.pictures'])
</script>
…
<img ng-src="{{ item.imageUrl | tinyPicturesUrl: {width: 200, quality: 90} }}">

Angular (a.k.a. Angular 2)

With Angular 2 and above, you may just import the library in your component files and use its functions directly. The example below also shows a simple pipe based on the url function.

Example

import { Component, Pipe, PipeTransform } from '@angular/core'
import TinyPictures from 'tiny.pictures-js/browser'

const imageUrl = 'https://tiny.pictures/example1.jpg'
const tinyPictures = new TinyPictures({
    window: window,
    user: 'demo'
})

@Component({
    selector: 'my-component',
    template: '<h1>Nice images</h1>' +
              '<img src="' + tinyPictures.url(imageUrl) + '">' +
              '<img src="imageUrl | tinyPicturesUrl">'
})
export class MyComponent {
    imageUrl: string = imageUrl
}

@Pipe({
    name: 'tinyPicturesUrl'
})
export class TinyPicturesUrlPipe implements PipeTransform {
    transform(...args): string {
        return tinyPictures.url(...args)
    }
 }