Does the lazysizes bgset plugin support selective image types? For example, on a regular image I might use the code:
<picture>
<source srcset="/large.webp" type="image/webp">
<source srcset="/large.jp2" type="image/jp2">
<img srcset="/large.jpg">
</picture>
And I would like to do something similar with a background image loaded with the bgset plugin. For example:
<a href="/weblink" data-bgset-webp="/large.webp" data-bgset-jp2="/large.jp2" data-bgset-jpg="/large.jpg" class="lazyload">
<div class="content">
<p>Some text</p>
</div>
</a>
Is something like this possible? Or am I being dense and there's an easier way to achieve this functionality for inline background images?
I was able to hack a solution together by adding Modernizr and modifying the bgset plugin:
addEventListener('lazybeforeunveil', function(e){
var set, image, elem;
if(e.defaultPrevented || !(set = e.target.getAttribute('data-bgset')) || !(set = e.target.getAttribute('data-bgwebp')) || !(set = e.target.getAttribute('data-bgjxr')) || !(set = e.target.getAttribute('data-bgjp2'))){return;}
Modernizr.on('webp', function (result) {
if (result && (set = e.target.getAttribute('data-bgwebp'))) {
elem = e.target;
image = document.createElement('img');
image.alt = '';
image._lazybgsetLoading = true;
e.detail.firesLoad = true;
createPicture(set, elem, image);
setTimeout(function(){
lazySizes.loader.unveil(image);
lazySizes.rAF(function(){
lazySizes.fire(image, '_lazyloaded', {}, true, true);
if(image.complete) {
proxyLoad({target: image});
}
});
});
}
else {
Modernizr.on('jpegxr', function (result) {
if (result && (set = e.target.getAttribute('data-bgjxr'))) {
elem = e.target;
image = document.createElement('img');
image.alt = '';
image._lazybgsetLoading = true;
e.detail.firesLoad = true;
createPicture(set, elem, image);
setTimeout(function(){
lazySizes.loader.unveil(image);
lazySizes.rAF(function(){
lazySizes.fire(image, '_lazyloaded', {}, true, true);
if(image.complete) {
proxyLoad({target: image});
}
});
});
}
else {
Modernizr.on('jpeg2000', function (result) {
if (result && (set = e.target.getAttribute('data-bgjp2'))) {
elem = e.target;
image = document.createElement('img');
image.alt = '';
image._lazybgsetLoading = true;
e.detail.firesLoad = true;
createPicture(set, elem, image);
setTimeout(function(){
lazySizes.loader.unveil(image);
lazySizes.rAF(function(){
lazySizes.fire(image, '_lazyloaded', {}, true, true);
if(image.complete) {
proxyLoad({target: image});
}
});
});
}
else {
if ((set = e.target.getAttribute('data-bgset'))) {
elem = e.target;
image = document.createElement('img');
image.alt = '';
image._lazybgsetLoading = true;
e.detail.firesLoad = true;
createPicture(set, elem, image);
setTimeout(function(){
lazySizes.loader.unveil(image);
lazySizes.rAF(function(){
lazySizes.fire(image, '_lazyloaded', {}, true, true);
if(image.complete) {
proxyLoad({target: image});
}
});
});
}
}
});
}
});
}
});
});
To use this hack, add the attributes data-bgwebp for webp, data-bgjxr for JPEG XR, and data-jp2 for JPEG 2000 to your background images.
@aFarkas : As you are far more skilled at JavaScript, is this something you can add to the bgset plugin (or a separate plugin)?
I figured out a better way to utilize Webp, JPEG XR, and JPEG 2000 without needing Modernizr. Simply add sources for the different image types to the picture element created by the bgset plugin:
var createPicture = function(webps, jxrs, jp2s, sets, elem, img) {
var picture = document.createElement('picture');
var sizes = elem.getAttribute(lazySizesConfig.sizesAttr);
var ratio = elem.getAttribute('data-ratio');
var optimumx = elem.getAttribute('data-optimumx');
if(elem._lazybgset && elem._lazybgset.parentNode == elem){
elem.removeChild(elem._lazybgset);
}
Object.defineProperty(img, '_lazybgset', {
value: elem,
writable: true
});
Object.defineProperty(elem, '_lazybgset', {
value: picture,
writable: true
});
webps = webps.replace(regWhite, ' ').split(regSplitSet);
jxrs = jxrs.replace(regWhite, ' ').split(regSplitSet);
jp2s = jp2s.replace(regWhite, ' ').split(regSplitSet);
sets = sets.replace(regWhite, ' ').split(regSplitSet);
picture.style.display = 'none';
img.className = lazySizesConfig.lazyClass;
if(sets.length == 1 && !sizes){
sizes = 'auto';
}
webps.forEach(function(webp){
var source = document.createElement('source');
source.setAttribute('type', 'image/webp');
if(sizes && sizes != 'auto'){
source.setAttribute('sizes', sizes);
}
if(webp.match(regSource)){
source.setAttribute(lazySizesConfig.srcsetAttr, RegExp.$1);
if(RegExp.$2){
source.setAttribute('media', lazySizesConfig.customMedia[RegExp.$2] || RegExp.$2);
}
}
picture.appendChild(source);
});
jxrs.forEach(function(jxr){
var source = document.createElement('source');
source.setAttribute('type', 'image/vnd.ms-photo');
if(sizes && sizes != 'auto'){
source.setAttribute('sizes', sizes);
}
if(jxr.match(regSource)){
source.setAttribute(lazySizesConfig.srcsetAttr, RegExp.$1);
if(RegExp.$2){
source.setAttribute('media', lazySizesConfig.customMedia[RegExp.$2] || RegExp.$2);
}
}
picture.appendChild(source);
});
jp2s.forEach(function(jp2){
var source = document.createElement('source');
source.setAttribute('type', 'image/jp2');
if(sizes && sizes != 'auto'){
source.setAttribute('sizes', sizes);
}
if(jp2.match(regSource)){
source.setAttribute(lazySizesConfig.srcsetAttr, RegExp.$1);
if(RegExp.$2){
source.setAttribute('media', lazySizesConfig.customMedia[RegExp.$2] || RegExp.$2);
}
}
picture.appendChild(source);
});
sets.forEach(function(set){
var source = document.createElement('source');
if(sizes && sizes != 'auto'){
source.setAttribute('sizes', sizes);
}
if(set.match(regSource)){
source.setAttribute(lazySizesConfig.srcsetAttr, RegExp.$1);
if(RegExp.$2){
source.setAttribute('media', lazySizesConfig.customMedia[RegExp.$2] || RegExp.$2);
}
}
picture.appendChild(source);
});
if(sizes){
img.setAttribute(lazySizesConfig.sizesAttr, sizes);
elem.removeAttribute(lazySizesConfig.sizesAttr);
elem.removeAttribute('sizes');
}
if(optimumx){
img.setAttribute('data-optimumx', optimumx);
}
if(ratio) {
img.setAttribute('data-ratio', ratio);
}
picture.appendChild(img);
elem.appendChild(picture);
};
var proxyLoad = function(e){
if(!e.target._lazybgset){return;}
var image = e.target;
var elem = image._lazybgset;
var bg = image.currentSrc || image.src;
if(bg){
elem.style.backgroundImage = 'url(' + (regBgUrlEscape.test(bg) ? JSON.stringify(bg) : bg ) + ')';
}
if(image._lazybgsetLoading){
lazySizes.fire(elem, '_lazyloaded', {}, false, true);
delete image._lazybgsetLoading;
}
};
addEventListener('lazybeforeunveil', function(e){
var webp, jxr, jp2, set, image, elem;
if(e.defaultPrevented || !(webp = e.target.getAttribute('data-bgwebp')) || !(jxr = e.target.getAttribute('data-bgjxr')) || !(jp2 = e.target.getAttribute('data-bgjp2')) || !(set = e.target.getAttribute('data-bgset'))){return;}
elem = e.target;
image = document.createElement('img');
image.alt = '';
image._lazybgsetLoading = true;
e.detail.firesLoad = true;
createPicture(webp, jxr, jp2, set, elem, image);
setTimeout(function(){
lazySizes.loader.unveil(image);
lazySizes.rAF(function(){
lazySizes.fire(image, '_lazyloaded', {}, true, true);
if(image.complete) {
proxyLoad({target: image});
}
});
});
});
@aFarkas : Can you implement this improvement to the bgset plugin?
@frontalot
Yes and no. I would prefer a string solution that is built on top of the current version.
Your code predefines the priority of the types and makes fixes all types (no possibility to add new ones).
I would suggest something like this:
image-200.webp [(max-width: 480px)][type=image/webp] | image-200.jpg [(max-width: 480px)] | image-300.webp [(max-width: 700px)][type=image/webp] |image-300.jpg [(max-width: 700px)] | image-400.jpg [type=image/webp] | image-400.jpg
@aFarkas,
Any progress on this? I would love to be able to load a webp image as a background image when possible and then default to a png for browsers that don't support webp.
@aFarkas
+1 for this feature.
I will add this feature till next Monday. Please note the following: You should already be able to do this using a normal image and placing it - using position: absolute - in the background. The object-fit polyfill for IE should be also handy in some situations.
In case you use the bgset plugin to get better support for object-fit I highly recommend to use the object-fit polyfill instead.
@aFarkas
Any update on this? Can't wait to start using this in future projects :D
I was looking for webp support when using bgset plugin because using a picture with position: absolute feels like an ugly workaround. That brought me to this issue.
+1 for this feature – would be a huge improvement of the plugin!
@aFarkas do you need any help on this?
any updates? Would be awesome to have this feature...
Sorry guys. I just added this feature to the master branch. Please give it a try, if ti is ok I will make a new release.
Most helpful comment
@aFarkas
+1 for this feature.