-
Notifications
You must be signed in to change notification settings - Fork 2
Lazy load responsive background images
$lazy can be used to lazy load responsive background images, both in HTML and in stylesheets using its $lazybg extension. This Wiki shows how to lazy load responsive background images.
To create responsive background images requires an advanced HTML filter and a solution to generate responsive images from a background-image
source file. The Style.Tools PHP library and CMS plugins provide an advanced image editing solution based on Sharp.js that can easily generate optimized responsive images with support for Google WebP. The Style.Tools image editing solution can generate +100 responsive images simultaneously in a few seconds.
The following example shows how to generate responsive images using the Style.Tools PHP library.
/**
* Setup Style.Tools HTML filter
*/
\StyleTools\HTML::add_filter('pre', function ($HTML) {
// background images
$HTML = preg_replace_callback('#<div[^>]+background(-image[^>]+|\s*:\s*)url\s*\(\s*([^\)]+)\)[^>]+>#smi', function ($matches) {
$tag = $matches[0];
$img_src = trim($matches[2], ' \'"');
// local images only
if ($img_src && !preg_match('#^(http(s)?:|//)#Ui', $img_src)) {
// sizes for the responsive background image
$sizes = array(
array(411,514),
array(553,514),
array(768,462),
array(1024,425),
array(1280,425),
array(1440,425)
);
// generate responsive images
$imgs = array();
foreach ($sizes as $size) {
try {
$img = \StyleTools\Images::optimize($img_src, json_decode('{
"optimize": [{
"method": "api",
"arguments": [{
"url": "https://europe-west1-xxx.cloudfunctions.net/optimize-images",
"headers": {
"x-styletools-security-key": "xxx"
},
"options": {
"handlers": [{
"type": "flatten",
"arguments": [{
"background": {
"r": 255,
"g": 255,
"b": 255
}
}]
}, {
"type": "jpeg"
}, {
"type": "imagemin",
"plugins": [{
"plugin": "mozjpeg",
"options": {
"quality": 95
}
}]
}]
}
}]
}],
"webp": {
"quality": 95
},
"srcset": "auto",
"srcset_resize": {
"fit": "cover",
"height": "aspect"
},
"default_format": "jpg",
"src_tags": {
"img": [
"src",
"srcset"
]
},
"path": {
"root": "/i/",
"hash_filename": {
"attr": "alt"
},
"hash_extension": "jpg"
}
}', true));
$imgs[] = array($img,$size[0]);
} catch (\Exception $err) {
\StyleTools\Error::add($err);
}
}
$tag = \StyleTools\HTML::attr('data-rzbg', $tag, htmlentities(json_encode($imgs), ENT_COMPAT, 'utf-8'));
}
return $tag;
}, $HTML);
return $HTML;
});
The result of the above HTML filter is the following:
<!-- before -->
<div style="background-image:url('/image.jpg');">...</div>
<!-- after -->
<div data-rzbg='[["/i/image-w411.jpg",411],["/i/image-w553.jpg",553],...]'>...</div>
The following $lazy code shows how to lazy load the responsive background images with support for view-port changes.
// lazy load *[data-zbg] elements
$lazy('[data-zbg]', function(el) {
function render_responsive_bg(e) {
if (e) {
if (e.matches) {
// media query still matches
return;
}
mqMatch.removeListener(render_responsive_bg);
}
var match;
bg.forEach(function(i) {
if (!match) {
if (i[1]) {
mqMatch = window.matchMedia(((!isNaN(parseInt(i[1]))) ? '(max-width: ' + i[1] + 'px)' : i[1]));
if (mqMatch.matches) {
match = i[0];
mqMatch.addListener(render_responsive_bg);
} else {
mqMatch = false;
}
} else {
match = i[0];
}
}
});
if (match) {
// optional: convert to WebP
// The $lazy+webp extension provides the method $zwebp() that can convert image URLs to .webp.
match = $zwebp(match);
// render responsive background image
el.style.backgroundImage = 'url(' + match + ')';
// optional: apply requestAnimationFrame timing method from $async
//$async.time('requestAnimationFrame', function() {
// el.style.backgroundImage = 'url(' + bg + ')';
//});
}
}
var mqMatch;
var bg = el.getAttribute('rzbg');
if (bg) {
// parse responsive background image JSON
bg = JSON.parse(bg);
// render
render_responsive_bg();
// optional, sanitize HTML
el.removeAttribute('data-rzbg');
}
});