Generate responsive HTML picture elements powered by on-the-fly Filestack image conversions.
Table of Contents
Adaptive is a tool which allow Filestack users to combine the power of on-the-fly image processing with the latest standard for responsive web images.
This library ships with a built-in virtual DOM adapter powered by hyperx, which allows you to simply call picture(source, options, renderer)
, where renderer can be any DOM builder supported by hyperx (e.g React.createElement). If renderer is not provided then picture will default to returning plain DOM.
You can find the newest version at https://static.filestackapi.com/adaptive/1.3.0/adaptive.min.js
<script src="https://static.filestackapi.com/adaptive/1.3.0/adaptive.min.js" crossorigin="anonymous"></script>
<script>
const options = {
alt: 'windsurfer',
sizes: {
fallback: '60vw',
}
};
const el = fsAdaptive.picture(FILESTACK_HANDLE, options);
document.body.appendChild(el);
</script>
Output:
<picture>
<img src="https://cdn.filestackcontent.com/5aYkEQJSQCmYShsoCnZN"
srcset="
https://cdn.filestackcontent.com/resize=width:180/5aYkEQJSQCmYShsoCnZN 180w,
https://cdn.filestackcontent.com/resize=width:360/5aYkEQJSQCmYShsoCnZN 360w,
https://cdn.filestackcontent.com/resize=width:540/5aYkEQJSQCmYShsoCnZN 540w,
https://cdn.filestackcontent.com/resize=width:720/5aYkEQJSQCmYShsoCnZN 720w,
https://cdn.filestackcontent.com/resize=width:900/5aYkEQJSQCmYShsoCnZN 900w,
https://cdn.filestackcontent.com/resize=width:1080/5aYkEQJSQCmYShsoCnZN 1080w,
https://cdn.filestackcontent.com/resize=width:1296/5aYkEQJSQCmYShsoCnZN 1296w,
https://cdn.filestackcontent.com/resize=width:1512/5aYkEQJSQCmYShsoCnZN 1512w,
https://cdn.filestackcontent.com/resize=width:1728/5aYkEQJSQCmYShsoCnZN 1728w,
https://cdn.filestackcontent.com/resize=width:1944/5aYkEQJSQCmYShsoCnZN 1944w,
https://cdn.filestackcontent.com/resize=width:2160/5aYkEQJSQCmYShsoCnZN 2160w,
https://cdn.filestackcontent.com/resize=width:2376/5aYkEQJSQCmYShsoCnZN 2376w,
https://cdn.filestackcontent.com/resize=width:2592/5aYkEQJSQCmYShsoCnZN 2592w,
https://cdn.filestackcontent.com/resize=width:2808/5aYkEQJSQCmYShsoCnZN 2808w,
https://cdn.filestackcontent.com/resize=width:3024/5aYkEQJSQCmYShsoCnZN 3024w"
alt="photo_01"
sizes="60vw">
</picture>
Subresource Integrity (SRI) is a security feature that enables browsers to verify that files they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched file must match
To obtain sri hashes for adaptive library check manifest.json file on CDN:
https://static.filestackapi.com/adaptive/{LIBRARY_VERSION}/manifest.json
<script src="//static.filestackapi.com/adaptive/{LIBRARY_VERSION}/adaptive.min.js" integrity="{FILE_HASH}" crossorigin="anonymous"></script>
Where {LIBRARY_VERSION}
is currently used library version and {FILE_HASH}
is one of the hashes from integrity field in manifest.json file
npm install filestack-adaptive
import react from 'react';
import reactDOM from 'react-dom';
import { picture } from 'filestack-adaptive';
// Need to spread children parameter to prevent React key warnings
const createElement = (Component, props, children) => {
return React.createElement(Component, props, ...children);
};
const options = { alt: 'windsurfer', sizes: { fallback: '100vw' } };
const tree = picture(FILESTACK_HANDLE, options, createElement);
ReactDOM.render(tree, document.body);
In a case of need to create your own <picture/>
element you can call makePictureTree directly in your JSX
import React, { Component } from 'react';
import { makePictureTree } from 'filestack-adaptive';
class Picture extends Component {
renderSources(sources) {
return sources.map((sourceObj) => {
return <source {...sourceObj} />;
});
}
renderImage(imageObj) {
return <img {...imageObj} />;
}
render() {
const tree = makePictureTree(this.props.handle, this.props);
return (
<picture>
{tree.sources && this.renderSources(tree.sources)}
{this.renderImage(tree.img)}
</picture>
);
}
}
export default Picture;
You can also use Filestack storage alias or external urls as an image source:
<script src="https://static.filestackapi.com/adaptive/1.3.0/adaptive.min.js"></script>
<script>
const options = {
alt: 'windsurfer',
sizes: {
fallback: '60vw',
}
};
const srcHandle1 = {
srcHandle: 'src://your_storage_alias_name/example.jpg',
apiKey: 'YOUR_FILESTACK_API_KEY'
};
const el1 = fsAdaptive.picture(srcHandle1, options);
document.body.appendChild(el1);
const srcHandle2 = {
srcHandle: 'https://yourdomain.com/photo1.jpg,
apiKey: 'YOUR_FILESTACK_API_KEY'
};
const el2 = fsAdaptive.picture(srcHandle2, options);
document.body.appendChild(el2);
</script>
When the image width is known it will generate a srcset for HiDPI screens at 2x. More densities can be specified
by passing an array to the resolutions
option, e.g. resolutions: ['1x', '2x', '3x']
.
const options = {
alt: 'windsurfer',
width: '768px',
};
picture(FILESTACK_HANDLE, options);
Output:
<picture>
<img src="https://cdn.filestackcontent.com/resize=width:768/5aYkEQJSQCmYShsoCnZN"
srcset="https://cdn.filestackcontent.com/resize=width:768/5aYkEQJSQCmYShsoCnZN 1x,
https://cdn.filestackcontent.com/resize=width:1536/5aYkEQJSQCmYShsoCnZN 2x"
alt="windsurfer"
width="768">
</picture>
Adaptive now supports webcomponent. Supported options: src, width, alt, cname, policy, signature, keys, resolutions
<fs-adaptive src="NxW2v528S9W6K1l5LnFS" width="769px" alt="windsurfer" ></fs-adaptive>
Output:
<picture>
<img src="https://cdn.filestackcontent.com/resize=width:768/NxW2v528S9W6K1l5LnFS"
srcset="https://cdn.filestackcontent.com/resize=width:768/NxW2v528S9W6K1l5LnFS 1x,
https://cdn.filestackcontent.com/resize=width:1536/NxW2v528S9W6K1l5LnFS 2x"
alt="windsurfer"
width="768">
</picture>
You can specify generated widths by using resolutions
, which takes an array
of numbers or strings (e.g. 540
or '540w'
).
const options = {
alt: 'windsurfer',
sizes: {
'(min-width: 1080px)': '100vw',
fallback: '90vw',
},
resolutions: [540, 1080],
};
picture(FILESTACK_HANDLE, options);
Output:
<picture>
<source media="(min-width: 1080px)"
sizes="100vw"
srcset="https://cdn.filestackcontent.com/resize=width:540/5aYkEQJSQCmYShsoCnZN 540w,
https://cdn.filestackcontent.com/resize=width:1080/5aYkEQJSQCmYShsoCnZN 1080w">
<img src="https://cdn.filestackcontent.com/5aYkEQJSQCmYShsoCnZN"
srcset="https://cdn.filestackcontent.com/resize=width:540/5aYkEQJSQCmYShsoCnZN 540w,
https://cdn.filestackcontent.com/resize=width:1080/5aYkEQJSQCmYShsoCnZN 1080w"
alt="windsurfer"
sizes="90vw">
</picture>
WebP can be used when it's supported by the browser. Filestack will take care of the image conversion and cache it on the delivery network for future requests.
const options = {
alt: 'windsurfer',
formats: ['webp', 'jpg'], // order matters!
};
picture(FILESTACK_HANDLE, options);
Output:
<picture>
<source srcset="https://cdn.filestackcontent.com/output=format:webp/5aYkEQJSQCmYShsoCnZN"
type="image/webp">
<source srcset="https://cdn.filestackcontent.com/output=format:jpg/5aYkEQJSQCmYShsoCnZN"
type="image/jpg">
<img src="https://cdn.filestackcontent.com/5aYkEQJSQCmYShsoCnZN" alt="windsurfer">
</picture>
In order to use custom cname for generated file links just use cname option:
const options = {
cname: 'fs.test123.com'
};
picture(FILESTACK_HANDLE, options);
Output:
<picture>
<img src="https://cdn.fs.test123.com/5aYkEQJSQCmYShsoCnZN">
</picture>
Adaptive also supports Filestack transformations. Available options are listed in doc:
https://www.filestack.com/docs/image-transformations
const options = {
alt: 'windsurfer',
width: 400,
transforms: {
blur: {
amount: 5
},
border: true, // use default options of border transformation
}
};
picture(FILESTACK_HANDLE, options);
Output:
<picture>
<img src="https://cdn.filestackcontent.com/blur=amount:5/border/resize=width:400/5aYkEQJSQCmYShsoCnZN" srcset="https://cdn.filestackcontent.com/blur=amount:5/border/resize=width:400/5aYkEQJSQCmYShsoCnZN 1x, https://cdn.filestackcontent.com/blur=amount:5/border/resize=width:800/5aYkEQJSQCmYShsoCnZN 2x" alt="windsurfer" width="400">
</picture>
To speed up generating of final output (useful when you have a bunch of images on your site) you can optionally disable validation of transformation params by passing additional prop in options:
const options = {
...
useValidator: false,
...
}
To install and work on Adaptiv locally:
git clone git@github.com:filestack/adaptive.git
cd adaptive
npm install
To create build directory:
npm run build
This newly created directory contains
build/
├── browser/ # for the UMD module (usable in HTML script tags)
└── index.umd.js #
├── main/ # for the CommonJS module
├── ... #
└── index.js #
└── module/ # for the ES Module (suitable for bundlers like Webpack and Rollup)
├── ... #
└── index.js #
For more info about available methods and options check browser documentation:
https://filestack.github.io/adaptive/
We follow the conventional commits specification to ensure consistent commit messages and changelog formatting.
Adaptive is joining an ecosystem already populated with many utilities for responsive images. We want to remain flexible while still having some opinions on how to implement picture elements using Filestack conversions, and we know it is hard to cover every use case. Contributions and ideas are welcome that would help improve the usefulness of this library.
Current ideas:
makePictureTree
Construct Filestack URL out of CDN base and handle, with optional security
Just your basic HTML img element. However we can let the user specify a specific width which will incorporate pixel resolutions options in a srcset.
Represent a picture element as a tree where leaf nodes are attributes of one img element and zero or more source elements.
This allows passing the structure into hyperscript-like virtual DOM generators. For example see https://github.com/choojs/hyperx
A source element contains many possible hints for the browser. For each media query + size pair we can construct a source with the proper srcset using the size as the width parameter. For each format a source element can be constructed as well. This means there are (sizes × formats) sources.
R.xprod lets us compute the Cartesian product of two lists.
Construct src attribute for img element. This may contain a resized URL if a fallback size is provided.
Constructs a srcset attribute for source and img elements. Will use resolution descriptors or pixel densities to construct the proper URLs based on the width of the image.
Sort array of keys in a way that 'output' is always the first
First key to be compared in a sort function
Helper that composes makePictureTree with the DOM adapter for generating actual picture elements.
Split an array into many arrays with a provided chunk factor
An original array to be splitted
A number of elements which new arrays will contain
Creates a new list out of the two supplied by creating each possible pair from the lists. It works similar to https://ramdajs.com/docs/#xprod
An array to be processed
Flat elements in array to provided depthness
The array to flatten
A maximum recursion depth
Utility to get numbers from ambiguous types.
A value to be checked
Utility to get unit of width or resolution
A value from which a unit will be extracted
Remove falsey values from object.
An object to be filtered
Based on the provided transform options object create filestack filelink