cristinafsanz
8/2/2019 - 8:50 AM

Progressive image loading

<div
  class="placeholder"
  :data-large="imageIntro"
>
  <img
    :src="imageIntroSmall"
    class="img-small"
  >
  <img
    :src="imageIntro"
    :class="{show: loaded}"
    class="img-large"
    alt=""
    width="335"
    height="294"
  >
  <div style="padding-bottom: 87.76%;" />
</div>
<script>
import prefetchImages from 'prefetch-image'

export default {
  data: function () {
    return {
      loaded: false,
      imageIntro: require('assets/images/intro.jpg'),
      imageIntroSmall: require('assets/images/intro-small.jpg'),
      images: [
        require('assets/images/question-1.jpg'),
        require('assets/images/question-2.jpg'),
        require('assets/images/question-3.jpg')
      ]
    }
  },

  mounted: function () {
    this.progressiveImageIntro()
    this.prefetchAllImages()
  },

  methods: {
    prefetchAllImages() {
      prefetchImages(this.images)
    },

    progressiveImageIntro() {
      const placeholder = document.querySelector('.placeholder')
      const small = placeholder.querySelector('.img-small')
      const large = placeholder.querySelector('.img-large')

      // load small image and show it
      const img = new Image()
      img.src = small.src
      img.onload = function () {
        small.classList.add('loaded')
      }

      // load large image
      const imgLarge = new Image()
      img.src = large.src
      imgLarge.onload = function () {
        imgLarge.classList.add('loaded')
      }
      
      this.loaded = true
    }
  }
.placeholder {
  background-color: #fff;
  background-size: cover;
  background-repeat: no-repeat;
  position: relative;
  overflow: hidden;
}

.placeholder img {
  position: absolute;
  opacity: 0;
  top: 0;
  transition: opacity 1s linear;
}

.placeholder img.loaded {
  opacity: 1;
}

.img-small {
  filter: blur(50px);

  /* this is needed so Safari keeps sharp edges */
  transform: scale(1);
}

.img-large {
  opacity: 0;
  transition: opacity 1s linear;
}

.img-large.show {
  opacity: 1;
}