Vanilla-lazyload: CSS background without data-bg

Created on 29 Oct 2020  路  10Comments  路  Source: verlok/vanilla-lazyload

I like vanilla-lazyload and I would like to use it as extensivelly as possible.

In regard to the support for CSS background:
Could the script work if we specify the url of the image only in the CSS?

Images are specified in the HTML so it seems straightforward to let the mechanism of the script rely on the attribute (which is in the HTML itself)

CSS backgrounds I have two cases:

1) image URL specified in the HTML (style attribute) => data-bg attribute is OK!
1) image URL specified in the CSS => could the script work without specifing a data-bg attribute? What if we leave it empty?

This way we can fully control CSS-backgrounds (with a great fallback) in a CSS-only way:

HTML
<div class="banner lazy">

CSS

.banner  { ... }
.banner.loaded, .no-js .banner { ...聽}

Does this make sense?

Awaiting feedback Question

Most helpful comment

Aaaaand, done!
You got it in version 17.3.0.

That was easy!

All 10 comments

I tried to obtain some effectv relying on the "data-was-processed" value, which is apparently deprecated since
Version 17. I'd love some feedback on this

1) Could this "add css class only" approach work? (I was inspired by https://web.dev/lazy-loading-images/)

2) What value of "data-ll-status" could I use to replace data-was-processed="true"?

3) Is there any chance to get this "behaviour" working for vanilla-lazyload? Or would it "break things" so much in the current implementation? I imagine that you rely on the presence and correctness of "data-bg" attribute to make it work...

.banner { ... }
.banner[data-was-processed=true] { APPLY BACKGROUND }

After updating vanilla-lazyload to the latest version, I found that the "CSS-only approach" works; it relies on
data-ll-status="entered" attribute value.

HTML

Hey @bomastudioweb ,
sorry for the very late reply!

I can see you've found a solution, after a couple of days!
Yes that works, but I wouldn't rely on the data-ll-status attribute, because it's meant to be an attribute used by my script itself, and it could change in the future.

A much more solid solution would be to use the callback_enter callback to set a visible class in your DOM element, exactly like it's suggested on the web.dev article you mentioned.

So you'd do:

new LazyLoad({
  "elements_selector": ".lazy-background",
  "callback_enter": el => el.classList.add("visible")
});

or, in ES5

new LazyLoad({
  "elements_selector": ".lazy-background",
  "callback_enter": function(el) {
    el.classList.add("visible")
  }
});

Then you'd apply your CSS background image only to the .visible elements.

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

What do you think?

Hi @verlok ,

that sounds like a pretty good solution.

Would you see it as an improvement for your script to have a way that provide this behaviour out of the box, as a fundamental part of the job, without adding any JS at all? Just asking...

I try to make it clearer. Would you suggest the following as a standard way to use your script?

IMAGES
.lazy class to detect them
data-src="IMAGE-URL"
.loaded class added by your script

INLINE CSS BACKGROUNDS
.lazy class to detect them
data-bg="IMAGE-URL"
.loaded class added by your script

CSS BACKGROUNDS
.lazy-background to detect them
"IMAGE-URL" specified in CSS
.visible class added by your script

As an example... this is how I would write JS for ".lazy" (images and css background using data-src) and ".lazy-background" (css backgrounds specified in css)

//LAZY IMG
var LazyImg = new LazyLoad({
    elements_selector: ".lazy",
    callback_finish: function (element) {
        window.finish = 1;
    }
});

//LAZY CSS BACKGROUNDS
var LazyBg = new LazyLoad({
    elements_selector: ".lazy-background",
    callback_enter: function(element) {
        element.classList.add("visible")
    }
});

//SCROLLING CONTAINER (EXAMPLE!!!)
var LazyOwl = new LazyLoad({
    container: document.querySelector(".owl-carousel")
});

Hey @bomastudioweb

Would you see it as an improvement for your script to have a way that provide this behaviour out of the box, as a fundamental part of the job, without adding any JS at all? Just asking...

Not sure, because the usage you propose is a very specific corner case I guess. I can only guess, but I think the vast majority of the users use vanilla-lazyload on regular img images, iframes, videos, and inline background images.

On the other side, to implement "lazy CSS backgrounds" on the user side costs very few lines of code.
The code you proposed and I report below already works today without any change.

// LAZY IMG
var LazyImg = new LazyLoad({
    elements_selector: ".lazy",
    callback_finish: function (element) {
        window.finish = 1;
    }
});

// LAZY CSS BACKGROUNDS
var LazyBg = new LazyLoad({
    elements_selector: ".lazy-background",
    callback_enter: function(element) {
        element.classList.add("visible")
    }
});

I'm closing this for now. Feel free to reopen if you need any more information.

If you鈥檙e happy with my support, the documentation and the effort I鈥檝e been putting on this project in the latest years, I hope you might want to buy me a coffee to show your appreciation. Or sponsor me, if you're a fan.

Open-source software is great for everyone, but it takes passion and time to grow and evolve.
Thank you for thinking about it.

Have a nice day!

Thank you for your replies. Though this recipe is very easy to cook, I disagree it's a very specific case.

See this example (still a WIP)
This is the perfect use case for background images in CSS: we need decorative (not essential) images as backgrounds of some banners. These are merely for creating an atmosphere on the website, we use <img> tag for essential images (products, recipes, etc.). We think CSS is the perfect place for "storing" these images as it's a part of the style layer and it doesn't influence the content (markup).

Just my 2cents... Thank you for your software and your support!

Ciao @bomastudioweb,
yes you're right, CSS is the right place to store those background images' URLs, and LazyLoad is the perfect way to reveal it.

I've seen the websited you linked (btw, it's beautiful) and yes, you convinced me.
I'm thinking of adding an option to make LazyLoad apply a class to the elements that entered the viewport. Something like class_entered.

So instead of using

.banner-agente[data-ll-status=entered] {
  background-image: url('banner-agenti.jpg');
}

you would simply do

.banner-agente.entered {
  background-image: url('banner-agenti.jpg');
}

What do you think?

PS: Grazie mille per il caff猫!

Aaaaand, done!
You got it in version 17.3.0.

That was easy!

I think it's great!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

briwg picture briwg  路  8Comments

nicomollet picture nicomollet  路  4Comments

broguinn picture broguinn  路  6Comments

starfishpatkhoo picture starfishpatkhoo  路  6Comments

gerdneuman picture gerdneuman  路  8Comments