ng-lazyload-image icon indicating copy to clipboard operation
ng-lazyload-image copied to clipboard

[feature-request]: Allow background-image with gradients

Open GregOnNet opened this issue 4 years ago • 3 comments

Hello @tjoskar,

thank you for providing this neat library. Currently, I try to do something like this:

TEMPLATE

  <div [lazyload]="backgroundImageWithGradient"></div>

COMPONENT

@Component({ ... })
export class SomeComponent {
  imageUrl
  backgroundImageWithGradient = `linear-gradient(rgba(0,0,0,0.45), rgba(0,0,0,0.7)), url(' + this.imageUrl + ')`;
}

Of course, this fails, since [lazyload] expects an image URL. It would help me if I could do something like shown above in order to define a gradient on top of the loaded image.

What do you think about it?

GregOnNet avatar Jan 17 '21 13:01 GregOnNet

Hi @GregOnNet,

This is a great idea. I see a few different options here:

  1. Check wherever lazyload is a URL or CSS-style and act accordingly. I do, however, think this will be hard and probably introduce bugs.
  2. Introduce a new flag that is telling that the string is CSS, something like: <div [lazyload]="backgroundImageWithGradient" resourceType="css"></div>. But i'm not sure about that.
  3. Use a custom hook (this should be possible today):
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { LazyLoadImageModule, IntersectionObserverHooks, Attributes, LAZYLOAD_IMAGE_HOOKS } from 'ng-lazyload-image';
import { AppComponent } from './app.component';

export class LazyLoadImageHooks extends IntersectionObserverHooks {
  setLoadedImage(att: Attributes) {
    if (att.element.dataset.backgroundWithGradient) {
      att.element.style.backgroundImage = att.element.dataset.backgroundWithGradient;
    } else {
      super.setLoadedImage(att);
    }
  }
}

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, LazyLoadImageModule],
  providers: [{ provide: LAZYLOAD_IMAGE_HOOKS, useClass: LazyLoadImageHooks }],
  bootstrap: [AppComponent],
})
export class MyAppModule {}

And then using the following template: <div [lazyload]="imageUrl" [attr.data-background-with-gradient]="backgroundImageWithGradient"></div>

I do however think this should be supported out of the box but I'm not sure how. There is an old, open, PR where we have discussed similar issues.

tjoskar avatar Jan 17 '21 15:01 tjoskar

Hi,

thanks for the hint. I will try the hook.

Concerning the API. I agree it would be nice to have this feature out-of-the-box. Maybe it could be delivered as a separate Directive:

<div [lazyBackground]="imageUrl" [lazyBackroundGradient]="{
  position: "below"|"above",
  definition: "linear-gradient(rgba(0,0,0,0.45), rgba(0,0,0,0.7))"
}">

GregOnNet avatar Jan 19 '21 08:01 GregOnNet

I think it will be hard to implement this so it scales. What if I want to add no-repeat after the image url, like:

background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1)), url('...') no-repeat;

And I believe it exists more edge cases. Maybe we can use a template, something like this:

<div [lazyBackground]="imageUrl" [styleToApply]="linear-gradient(rgba(0,0,0,0.45), rgba(0,0,0,0.7)), url('$IMAGE_URL$')">

But should that style also be used for the default/error-image?

tjoskar avatar Feb 07 '21 14:02 tjoskar