Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to reference different sizes in a template #68

Open
bparticle opened this issue Aug 23, 2018 · 6 comments
Open

How to reference different sizes in a template #68

bparticle opened this issue Aug 23, 2018 · 6 comments

Comments

@bparticle
Copy link

Responsive-loader is generating all my images beautifully with the correct names and sizes, but I can't figure out how to reference other sizes than the default (smallest one) in my template!

// webpack.config file
...
{
  test: /\.(jpe?g|png)$/i,
  loader: 'responsive-loader',
  options: {
    adapter: require('responsive-loader/sharp'),
    sizes: [600, 1200],
    placeholder: true,
    placeholderSize: 50,
    name: '/assets/img/[hash]-[width].[ext]'
  }
},
...

And this is how I'm referencing the images in my template html

  <img src="${require('./assets/img/image_0.jpg')}" alt="">

This gives me the 600px wide image and I would like to get different images based on screen size. Any pointers?

@Melzmr
Copy link

Melzmr commented Aug 25, 2018

@bparticle – do

<script>
  const responsiveImage = require( './assets/img/image_0.jpg');
</script>

And then use in your HTML

<img src={responsiveImage.src} srcset={responsiveImage.srcSet} alt="">

And your srcSet will be set up.

@bparticle
Copy link
Author

@Melzmr Thanks for your reply! Your answer makes perfect sense, and it is one of the options out of many I tried, but somehow nothing works. I'm still scratching my head over this but can't let it go. I'm using Vue.js at the moment and this is the code I'm currently testing:

<template>
<div id="app">
  <h1>{{ greeting }}</h1>
  <p>{{srcTest}}</p>
  <p>{{src}}</p>
  <p>{{srcSet}}</p>
  <img :src="src">
  <br>
</div>
</template>

<script>
const responsiveImage = require("./assets/img/image_0.jpg");

export default {
  name: "app",
  data: function() {
    return {
      greeting: "Hello",
      srcTest: responsiveImage,
      src: responsiveImage.src,
      srcSet: responsiveImage.srcSet
    };
  }
};
</script>

The only positive response I get is the raw responsiveImage reference in the first <p> tag. It's outputting the base64 code that is supposed to contain the image (data:image/jpeg;base64,bW9kdWxlLmV4cG9ydH......). If I put this in the image tag however I get a broken image link. The other tests aren't outputting anything at all (responsiveImage.src and .srcSet).

@jstcki
Copy link
Contributor

jstcki commented Aug 29, 2018

@bparticle looks like you have another loader hijacking your image (probably url-loader?) …

@bparticle
Copy link
Author

@herrstucki That will be the case probably. I think the way vue-cli is implementing its webpack configuration is awkward to say the least. I tried to set it up like this:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

// vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('images')
      .use('responsive-loader')
      .loader('responsive-loader')
      .options({
        adapter: require('responsive-loader/sharp'),
        sizes: [600, 1200],
        placeholder: true,
        placeholderSize: 50,
        name: '/assets/img/[hash]-[width].[ext]'
      });
  },
  configureWebpack: {
    plugins: [
      new BundleAnalyzerPlugin()
    ]
  }
}

But the trouble with that setup is not immediately relevant to this repository I suppose!

@bparticle
Copy link
Author

I found the issue (and it cost me many hours so I hope this may help anyone in the same situation). My images were not displayed due to the preceding slash that I put in the responsive-loader configuration (see previous code example). Also I changed the way I implement the loader in the vue-cli setup. This setup has fixed my problem:

// vue.config.js
module.exports = {
  chainWebpack: config => {
    const imgRule = config.module.rule('images');
    imgRule.uses.clear();
    imgRule
    .use('responsive-loader')
    .loader('responsive-loader')
    .options({
      adapter: require('responsive-loader/sharp'),
      sizes: [600, 1200],
      placeholder: true,
      placeholderSize: 50,
      name: 'assets/img/[hash]-[width].[ext]'
    });
  }
}

So name: 'assets/img/[hash]-[width].[ext]' instead of name: '/assets/img/[hash]-[width].[ext]'.
This is not a vue-cli specific fix so I think it is useful to post back my solution.

@brettinternet
Copy link

brettinternet commented Sep 17, 2020

For other templates using html-loader this can be accomplished by using multiple source elements. Here's a pug example:

picture
    source(media='(min-width: 1024px)', srcset=`${src}?size=1280`)
    source(media='(min-width: 768px)', srcset=`${src}?size=1024`)
    source(media='(min-width: 640px)', srcset=`${src}?size=768`)
    source(media='(min-width: 481px)', srcset=`${src}?size=640`)
    img(src=`${src}?size=481`, loading='lazy', alt=alt)

Multiple source elements are required in this case since html-loader won't transform a single srcset with multiple target resolutions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants