Best practice for responsive images?



  • Hello all

    I was wondering if there are accepted best practices for responsive images?

    I have a custom component like so:

    Vue.component('responsive-image', {
      template: '<img :srcset="imgsrc" />',
      props: {
        src: {
          type: String,
          required: true
        },
        w: {
          type: Number,
          required: true
        }
      },
      computed: {
        imgsrc: function () {
          return `~assets/img/lg/${this.src}.jpg w${this.w}, ~assets/img/md/${this.src}.jpg w${this.w * 0.5}, ~assets/img/sm/${this.src}.jpg w${this.w * 0.25}`
        }
      }
    })
    

    Which is used like so:

    <div>
      <responsive-image src="my-image" w="800" />
    </div>
    

    I have a grunt task to generate the 50% and 25% images automatically

    Any better ideas? Thanks!



  • looks cool to me.
    a few rough ideas to improve on it:

    • what about making it a vue single file component ?
    • what about high-dpi displays ?
    • what about sizing by height instead of width? (as an alternative)

    I could very well see a polished version of this getting into quasar as q-img



  • @spectrolite Having it like this makes it available globally, but at the moment I am using it as a single file component

    Regarding Hight dpi and sizing by height: this uses the srcset property, not src
    That means that I simply tell the browser what image widths are available and where, the browser figures out the best one and gets that one. So at no point am I deciding witch image width a client gets

    Cheers



  • The problem with srcset is that it is not supported by IE and (current) Edge versions (http://caniuse.com/#feat=srcset). So we would need a polyfill for these.
    https://github.com/scottjehl/picturefill/blob/master/dist/picturefill.min.js

    And without having used it, but shouldn’t the template be:

    <picture>
     <source :srcset="imgsrc">
     <img :src="fallbackSrc">
    </picture>
    

    Also, did you test if webpack inserts the correct path if you return the string?

    But a q-img components seems like a great idea. Maybe we could even extend the webpack config to automatically generate smaller versions of images and insert these instead on relying on another build system. :)
    I found this loader which looks promising: https://github.com/herrstucki/responsive-loader



  • @rstoenescu please consider this for 0.15. Do you need it to be a github issue?


  • Admin

    Yes, make it a github ticket pls. Accepting a PR if someone is willing. Thanks!



  • Here is the link to the issue on Github: https://github.com/quasarframework/quasar/issues/777
    At the moment I do not have time for a PR, but maybe I will experiment with it later on. :)



  • Here is a proposal. Also posted this on #777

    <template lang="html">
      <img
      :src="`/img/md/${src}`"
      :alt="alt"
      :srcset="imgsrc"
      :sizes="imgsize"
      >
    </template>
    
    <script>
    const xsBreakpoint = '576px',
      smBreakpoint = '768px',
      mdBreakpoint = '992px',
      lgBreakpoint = '1200px'
    
    export default {
      props: {
        src: {
          required: true,
          type: String
        },
        w: { // Width, in pixels, of our original image.
          required: true,
          type: Number
        },
        alt: {
          type: String
        },
        size: {
          type: Number
        },
        xsSize: {
          type: Number
        },
        smSize: {
          type: Number
        },
        mdSize: {
          type: Number
        },
        lgSize: {
          type: Number
        }
      },
      computed: {
        imgsrc () {
          let imgsrc = ''
    
          imgsrc += `/img/lg/${this.src}.jpg ${this.w}w, `
          imgsrc += `/img/md/${this.src}.jpg ${this.w * 0.5}w, `
          imgsrc += `/img/sm/${this.src}.jpg ${this.w * 0.25}w`
    
          return imgsrc
        },
        imgsize () {
          let imgsize = ''
    
          if (this.xsSize !== undefined) imgsize += `(max-width: ${xsBreakpoint}) ${this.xsSize}vw, `
          if (this.smSize !== undefined) imgsize += `(max-width: ${smBreakpoint}) ${this.smSize}vw, `
          if (this.mdSize !== undefined) imgsize += `(max-width: ${mdBreakpoint}) ${this.mdSize}vw, `
          if (this.lgSize !== undefined) imgsize += `(max-width: ${lgBreakpoint}) ${this.lgSize}vw, `
          imgsize += `${this.size}vw`
    
          return imgsize
        }
      }
    }
    </script>
    


  • Thank you @benoitranque for specifying this! :slight_smile:
    The only change I would make is to let webpack generate the imgsrc strings during the build and also actually build the smaller images.


Log in to reply
 

Looks like your connection to Quasar Framework was lost, please wait while we try to reconnect.