Giter Site home page Giter Site logo

alexjoverm / v-lazy-image Goto Github PK

View Code? Open in Web Editor NEW
978.0 11.0 72.0 27.09 MB

Lazy load images using Intersection Observer, apply progressive rendering and css animations.

License: MIT License

JavaScript 66.38% Vue 29.84% HTML 3.78%
vue web-performance lazy-loading javascript

v-lazy-image's Introduction

v-lazy-image

npm npm Donate

A Vue.js component to lazy load an image automatically when it enters the viewport using the Intersection Observer API.

⚠️ Check the practical examples and demos if you are creating a real-world or enterprise project and see how to achieve max performance using responsive images and progressive image loading.

Usage

npm install v-lazy-image

Warning: You'll need to install the w3c Intersection Observer polyfill in case you're targeting a browser which doesn't support it.

For Vue 3, import it and use it like any other component:

<script setup>
  import VLazyImage from "v-lazy-image";
</script>

For Vue 2, import it from v-lazy-image/v2:

import VLazyImage from "v-lazy-image/v2";

export default {
  components: {
    VLazyImage
  }
};

You must pass an src property with the link of the image:

<template>
  <v-lazy-image src="http://lorempixel.com/400/200/" />
</template>

That easy, the image will be loaded as soon as it enters the viewport. See it running in this demo and you'll learn how to use Chrome DevTools to check how it's loaded.

Achieving Max Performance

Just by using v-lazy-image you'll have a performance gain, since the image will be loaded when it's going to be seen.

But you can go to the next level and squeeze your web's performance if you use the next techniques.

Responsive Images

v-lazy-image allows you to use Web Standard's: the srcset attribute on images and the <picture> tag.

"Use Responsive Images with v-lazy-image" shows you how simple it is and see it in action in a demo.

Progressive Image Loading

A technique used by platforms like Spotify, Netflix or Medium to improve Perceived Performance, thus the User Experience.

In "Achieve Max Performance loading your images with v-lazy-image" you'll see what's progressive image loading about, how to apply it in v-lazy-image using the src-placeholder attribute and a demo to see how it plays with a CSS animation.

API

Aside from the following API, you can pass any img attribute, such as alt, and they'll be added to the rendered <img> tag.

Fields marked as (*) are required.

Props

Name Type Default Description
src String (*) - Image src to lazy load when it intersects with the viewport
src-placeholder String ' ' If defined, it will be shown until the src image is loaded.
Useful for progressive image loading, see demo
srcset String - Images to be used for different resolutions
intersection-options Object () => ({}) The Intersection Observer options object.
use-picture Boolean false Wrap the img in a picture tag.

Events

Name Description
intersect Triggered when the image intersects the viewport
load Triggered when the lazy image defined in src is loaded
error Triggered when the lazy image defined in src fails to load

v-lazy-image's People

Contributors

aarongarciah avatar alebarbaja avatar alexjoverm avatar andreynazarov3 avatar anthonygore avatar bovas85 avatar burningdog avatar halfakilo avatar jfght avatar jjragomes avatar jmperez avatar kutyel avatar mschwarzmueller avatar tennox avatar vhoyer avatar vsychov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

v-lazy-image's Issues

event hooks?

this.$Lazyload.$on('loaded', (params) => {
  // do something
  // also needs access to params's src
});

[Feature Request] Full SSR support

Right now the only proper way of using this lib with SSR is to wrap it in tag. But is it possible to implement a full SSR support so images would also properly render to SSR? The issue that exists right now is that if is omitted sometimes intersection observer is not triggered after initial load and images appear hidden although they are already within a viewport

Feature request: src-placeholder with use-picture

Would it be possibile to have the attributes src-placeholder and use-picture working at the same time?

Using Chrome 74, this component:

<v-lazy-image
    src="https://www.example.com/image/square/test-1.jpg"
    srcset="https://www.example.com/image/square_2x/test-1.jpg 2x"
    src-placeholder="https://www.example.com/image/square/placeholder.jpg"
    use-picture
>
    <source type="image/webp" srcset="
        https://www.example.com/image/square/test-1.webp,
        https://www.example.com/image/square_2x/test-1.webp 2x
    ">
</v-lazy-image>

renders an empty picture tag until the image scrolls into viewport:

<picture></picture>

Wouldn't this solution be preferable?

<picture>
    <img scr="https://www.example.com/image/square/placeholder.jpg" class="v-lazy-image">
</picture>

Thanks!

Feature request: class attribute on fallback image in picture tag

Hello,
I would like to use custom CSS classes on the fallback image in the picture tag. As far I see it in the code, it's currently not possible to do this. I imagine something like:

<v-lazy-image :src="require('~/assets/images/logos/aws.png')" img-class="img-fluid d-block" use-picture>
    <source :srcset="require('~/assets/images/logos/aws.png?webp')" type="image/webp" />
    <source :srcset="require('~/assets/images/logos/aws.png')" type="image/png" />
</v-lazy-image>

Which will be rendered as:

<picture>
    <source srcset="/_nuxt/assets/images/logos/aws.webp" type="image/webp"> 
    <source srcset="/_nuxt/assets/images/logos/aws.png" type="image/png">
    <img src="/_nuxt/assets/images/logos/aws.png" class="img-fluid d-block v-lazy-image v-lazy-image-loaded">
</picture>

Would this be possible? Does the solution make sense or will be there any problems in the future?

Thank you in advance!

License

It would be good to add a license so developers have clearance around this.

Image dimensions warning message

I'm getting a warning message when using this library on the Nuxt client-only block

[Intervention] An <img> element was lazyloaded with loading=lazy, but had no dimensions specified. Specifying dimensions improves performance. See https://crbug.com/954323

webpack aliases path

Hi, component dont work with webpack aliases path like <v-lazy-image src="~/assets/my-image.png"/>?

Allow customization of class names via props

It would pretty neat IMO to have the possibility of configuring the CSS classes used by the component, specifically v-lazy-image and v-lazy-image-loaded. How about two props to enable customization and give them a default value with the names you are already using? Maybe className and classNameLoaded?

Add Polyfill intersection-observer

Hi I have a problem when using this library when on a Safari Browser. Namely the problem of the absence of fire observer-intersections on safari. can you add it to this library?

Not working when dynamically changing src on already mounted image

It doesn't seem to work when dynamically changing the image (in case of a caroussel for example).

I've checked your code and it seems you are not watching the src prop change. Your computed property has the src as dependency but nothing seems to reset the intersected data which make the next loading not work properly (I mean withou any lazy load or anything).

mobileSize

When i use the v-lazy-image in size of mobile with android 7 or less than one
v-lazy-image does not show image in my mobile
please help me
thank you

Missing `alt` attibute

MDN: This attribute defines the alternative text describing the image. Users will see this text displayed if the image URL is wrong, the image is not in one of the supported formats, or if the image is not yet downloaded.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-alt

Cannot PR it right now but basically add it to props:

props: {
    alt: {
      type: String,
      default: ""
    }
  }

and to render:

render(h) {
    return h("img", {
      attrs: { 
       src: this.srcImage,
       alt: this.alt
      },
      class: {
        "v-lazy-image": true,
        "v-lazy-image-loaded": this.loaded
      }
    });
  }

Sorry not sure if render works as in my example since I've never used the render function before :)

Attribute Inheritance

Would be very useful to be able to pass dynamic attributes (or a least class property) to v-lazy-image component, for example to add a custom class to rendered img tag:

So this code:

<v-lazy-image class="my-custom-class" ...>

Would generates a img tag with my custom class:

<img class="v-lazy-image v-lazy-image-loaded my-custom-class" ... />

Thanks!

max-height not working

If I use max-height in the component it does not work. max-width works as expected. Any idea?

Is v-lazy-image SEO optimized?

I use Nuxt to SSR the content of my page. When I look at rendered page content I see that all my images are just black 1px image which is used in the src-placeholder attribute. Is it needed to provide a fallback with regular img inside noscript tag when v-lazy-image is used or it automatically handles clients that don't support scroll similar to how lazysizes does it?

Picture tag not working with media breakpoint

Hi @alexjoverm , I'm using v-lazy-image to lazy load some banners that use the picture tag. I've followed the readme to set this up, and while the picture images do lazy load as expected at mobile dimensions, they are not lazy loading at desktop dimensions above the media breakpoint.

Here is how I am using it:

<v-lazy-image :src="mobileImg"
                  :alt="altText"
                  :intersection-options="{rootMargin: '10%'}"
                  use-picture>
        <source :srcset="desktopImg" :media="breakpointQuery" />
    </v-lazy-image>

which is rendering as:

<picture>
    <source srcset="/path/to/mobileImage.jpg" media="(min-width: 800px)">
    <img src="/path/to/desktopImage.jpg" class="v-lazy-image v-lazy-image-loaded" alt="Alt">

</picture>

So at screen sizes below 800px, all of the picture tags lazy load the mobile images. But at screen sizes above 800px, all picture tags are requesting/loading the desktop images upon page load. Have you seen this issue?

@anthonygore I saw your involvement in getting the picture tag supported. Have you run across this issue yet? Can you guys reproduce this?

Feature request: error css-class

Hey,

Could u add a css-class like "v-lazy-image-error" when the image loading fails?
I tried to add it myself with the error function but v-lazy-image is overwriting the classes.

thank u :)

Feature request: ablility to set the height/width for the images

It would be great to be able to set the height/width of the image including the placeholder image.

This is because e.g. on my website I use smaller versions of the same images as placeholders; as such, the width/height of the placeholder would need to be set to match that of the main image.

inheritAttrs: false

Hi! I ran into the problem that v-lazy-image does not inherit attributes. For what reasons does the library specify inheritAttrs: false? Is there a way to pass attributes?

Doesn't work if image is in no-ssr component

If the image is in a component, it will never load if it is in the screen when the page initialy load. If i scroll past the content and come back, it will load and trigger the Observer and replace the image.

Feature: Medium-style blur effect

There's article https://alligator.io/vuejs/progressive-image-rendering/
A guy uses this library and makes blur effect with svg filter.
I tried to use it in my project but it seems to not be working on iOS devices at all, also problems with Firefox and Edge.
So I guees this should be implemented in this library the way like medium does this - with <canvas> element. There's already blur library https://github.com/flozz/StackBlur, just need to implement transition effect.

crossorigin attribute

I'm using this in a media gallery where I'm using a crossorigin="anonymous" tag so that I can use the selected image on to a canvas.

Is there any way to pass the crossorigin property to the image tag upon loading?

Thanks.

Support responsive images

Would be great to support the srcset attribute to use responsive images. I will open a PR with this :)

img srcset error

Props


<browser-window
	browserImagePath="/img/assets/"
	browserImageName="nameFile"
	browserImageTitle="txt title"
	browserImageAlt="some text"
></browser-window>

Page


<v-lazy-image
	:srcset="`${browserImagePath}${browserImageName}-512.jpg 512w, 
			  ${browserImagePath}${browserImageName}-992.jpg 992w,
			  ${browserImagePath}${browserImageName}-1400.jpg 1400w,`"
	:src="`{browserImagePath}${browserImageName}.png`"
	:alt="`${browserImageAlt}`"
	use-picture
>

<!-- webp -->

<source :srcset="`${browserImagePath}${browserImageName}-512.webp 512w, 
				  ${browserImagePath}${browserImageName}-992.webp 992w,
				  ${browserImagePath}${browserImageName}-1400.webp 1400w,`"
:alt="`${browserImageAlt}`" 

/>

Same error you can see here

nuxt/content#601

Not working on Safari

I'm running into a problem when I open my project in Safari.

Safari doesn't support:

  • intersectionObserver which results in the following error:
    ReferenceError: Can't find variable: IntersectionObserver

Does anybody else encounter this problem, and is there a workaround?

Thnx

Basic Configuration with local images

hi there,
First of all, plugin si working amazing with cdn images, but when I try to apply it with local images, is not working at all.

Album example

Vue logo

path is correct because I have 2 images with same src.

Thanks in advance

New release

Would be good to have a release with the latest changes.

Image carousel loads all the images

I have an image carousel, with some images outside the viewport. Since this is horizontal, it appears that the images are all loaded as they are within the vertical boundary.

Here's an example. All the images are loaded:

+ Screen  +
|         |  |         |  |         |
|  Loads  |  |  Loads  |  |  Loads  |
|         |  |         |  |         |
+ Screen  +

|         |
|  Waits  |
|         |

|         |
|  Waits  |
|         |

Is there a way to make it check for horizontal viewport collision too?

Start loading image before it comes into view?

Is it possible to have images start loading before they come into view? Right now, it seems like it begins to load the image as soon as it is scrolled into the view. Is it possible to start loading the image 100px or 200px (any custom value) ahead of time? this would help minimize the amount of time the placeholder is seen while the real image is downloaded. Is there some sort of padding setting to allow this?

Bug: undefined srcset with use-picture

Heyho 👋

The following code will result in an undefined undefined value for the srcset of the source slot.
Using a string instead (:srcset="'https://googlechrome.github.io/samples/picture-element/images/butterfly.webp'") is a workaround to avoid that issue.

    <v-lazy-image
      use-picture
      srcset="
        https://cdn-images-1.medium.com/max/800/1*xjGrvQSXvj72W4zD6IWzfg.jpeg,
        https://cdn-images-1.medium.com/max/1200/1*xjGrvQSXvj72W4zD6IWzfg.jpeg 1.5x,
        https://cdn-images-1.medium.com/max/1600/1*xjGrvQSXvj72W4zD6IWzfg.jpeg 2x
      "
      src="https://cdn-images-1.medium.com/max/800/1*xjGrvQSXvj72W4zD6IWzfg.jpeg"
    >
      <source
        type="image/webp"
        srcset="https://googlechrome.github.io/samples/picture-element/images/butterfly.webp"
      />
    </v-lazy-image>

CSB: https://codesandbox.io/s/3097oj4rlp

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.