82

I want to use a svg image from my assets folder in one of my components as a background-image. Here is an example of my component:

<template>
  <div class="container"></div>
</template>

<script>
export default {
  name: 'component'
}
</script>

<style scoped lang="scss">
.container {
  height: 40px;
  width: 40px;
  background-image: url('@/assets/image.svg');
}
</style>

But the image doesn't show. The Path is correct. Where is my mistake? Thanks for your help.

iamrobin.
  • 1,554
  • 3
  • 19
  • 31

7 Answers7

152

As Max Martynov, highlighted in the comments, you should use url('~@/assets/image.svg').

 

Webpack has some specific rules when resolving assets[1].

In order to resolve an alias (@), as you are using, it is mandatory webpack handles the request as a module request. Using the prefix ~ enforces webpack to treat the request as a module request, similar to require('some-module/image.svg').

 

References

  1. https://vuejs-templates.github.io/webpack/static.html#asset-resolving-rules
Community
  • 1
  • 1
j.raymond
  • 1,845
  • 1
  • 15
  • 15
  • 5
    Took me 2 days to get to some straight explanation. For non native english people like me, the docs gets really really freaking difficult. I think vue team took a step away not describing it in an of their free resources. such a simple thing got so much confusing, there is an issue on vue repo with hundreds of comments and reactions about this. Wish I could opvote you a million times. – Abdul Rehman Sep 19 '19 at 11:20
  • @Bsienn, I can't express how much I appreciate your comment! But, I think the praise should be directed to Max and Stackoverflow. I encourage everyone to upvote his comment :) – j.raymond Sep 20 '19 at 15:23
  • Ragaar and Max Thanks, sure provided a solution. both his and your description finally made it work and explained to me why it is the way it is 'Modules/webpack`. This should be first thing in the docs with example somewhere. Many thanks – Abdul Rehman Sep 21 '19 at 06:35
41

I would recommend using style binding. I found this thread really helpful link.

Here an example using bootstrap cards

    <div
      class="card-image"
      :style="{ backgroundImage: 'url(' + require('@/assets/images/cards.jpg') + ')' }">

The image is in src/assets/images/cards.jpg

CarlosZ
  • 1,026
  • 1
  • 9
  • 16
  • This solved the issue for me - went through allot of iterations - but looks like any image being used in an assets folder must be required() to be loaded properly (this is my observation from trial and error - so please don't take it as gospel) – Wally Sep 27 '20 at 08:26
5

Make sure the image extension is lowercase. If the image has an uppercase extension, change it to be lowercase otherwise it won't work.

<style lang="scss">
  .section{
    background-image: url('~@/assets/photos/DSC08611.jpg'); //WORKED!
    background-image: url('~@/assets/photos/DSC08611.JPG'); //DID NOT WORK
  }

</style>
Joe L.
  • 4,433
  • 1
  • 19
  • 14
1

This is what worked for me.

<div
  class="image"
  v-for="(image, imageIndex) in slideshow"
  :key="imageIndex"
  :style="{ backgroundImage: 'url(' + require(`@/assets/${image}`) + ')', width: '300px', height: '200px' }"
></div>

Where slideshow looks like:

data() {
      return {
        slideshow : [
          "MyImages/1.png",
          "MyImages/2.png"
        ]
      }
A Kingscote
  • 294
  • 4
  • 7
0

What worked for me was the following:

  1. Move the desired image to the public folder (myapp/public/assets/myimage.png)
  2. Build the project. This will move the assets from the public folder to the dist folder.

npm run build

  1. Now you can use your image in the component like this:
<div :style="{background: 'url(' + '\'/assets/myimage.png\'' + ') no-repeat 0 3px'}"  ></div>
Manuel Reyes
  • 260
  • 2
  • 10
0

If your vuejs uses file-loader, you'll take advantage of import.

<template>
  <div class="container"></div>
</template>

import image from @/assets/image.svg
<script>
export default {
  name: 'component'
}
</script>

<style scoped lang="scss">
.container {
  height: 40px;
  width: 40px;
  background-image: url(image);
}
</style>
0

If you are using Vue 3 (TypeScript) and Vite 3.2+, in your vite.config.ts, set your base appropriately as shown below.

import { defineConfig } from 'vite';

export default defineConfig({
  base: process.env.NODE_ENV === 'production' ? '/subfolder/' : '/',
});

The base option is used for specifying the base URL of your application, and it automatically handles the resolution of asset paths.

Then if your image, img.jpg, is in public/images folder, you can reference it in your css as:

background-image: url('/images/img.jpg');

Upon building for production, this will be resolved to:

background-image: url('/subfolder/images/img.jpg');