How to use images with Vite and Vue

  1. Intro
  2. 1. Public folder
  3. 2. Import files individually
  4. 3. Import images with import.meta.url
  5. 4. Using dynamic images from an API
  6. 5. Dynamic inline background images
  7. Conclusion
  8. Source

Intro

You’ve basically got 3 different ways to do it. Put images in the public folder and reference them normally (just a forward slash and the image name). Import images directly into your view/project and use them in your template. Use the native ESM import.meta.url to assign images to variables, or create a function to use multiple images more easily. I’ll follow up at the end about referencing images from an API.

1. Public folder

The simplest solution is to put your assets into the public folder, and then reference them as you normally would.

1
2
3
4
// add circle.svg to the public directory
// public images are served at the root path so you only need '/' + your image path

<img src="/circle.svg">

2. Import files individually

You can import each image you need as a variable that can then be referenced where you need it. The obvious drawback to this is if you have multiple images.

1
2
3
4
5
6
7
<script setup>
import imgUrl from "./assets/img.png";
</script>

<template>
<img :src="imgUrl" />
</template>

3. Import images with import.meta.url

import.meta.url is a native ESM feature that exposes the current module’s URL. Combining it with the native URL constructor, we can obtain the full, resolved URL of a static asset using relative path from a JavaScript module:

More on this from the Vite docs here.

  1. Similar to example #2, you assign your image path to a constant and then use it in your template. Be aware you have to write out the entire path to the file i.e. ./assets/img.png:
1
2
3
4
5
6
7
<script setup>
const imgUrl = new URL("./assets/img.png", import.meta.url).href;
</script>

<template>
<img :src="imgUrl" />
</template>
  1. Dynamically import images using a function and template literals

I’ve found this to be the most useful approach, especially with multiple images.

Be aware, in the Vite docs, the ./dir/ part of the path is a placeholder — update it to the path and folder of your project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// from the docs
function getImageUrl(name) {
return new URL(`./dir/${name}.png`, import.meta.url).href;
}

// updated with your project's assets folder setup
function getImageUrl(name, ext) {
return new URL(`../assets/img/${name}.png`, import.meta.url).href;
}

// works with svg and other file formats as well
function getImageUrl(name) {
return new URL(`../assets/img/${name}.svg`, import.meta.url).href;
}
  1. You can also define a second parameter in the function so the image extension can be dynamic as well i.e. .jpg, .png, .svg etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
<script setup>
// where 'name' is the actual name of the file, and 'ext' is the extension
// i.e. myjpg.jpg

function getImageUrl(name, ext) {
return new URL(`./assets/img/${name}.${ext}`, import.meta.url).href;
}
</script>

<template>
<img :src="getImageUrl('myjpg', 'jpg')" alt="" />
<img :src="getImageUrl('mysvg', 'svg')" alt="" />
</template>

4. Using dynamic images from an API

Using images from an API doesn’t require any special treatment outside of normal data rendering in Vue. Just make your API request, get your data, and render it in the template.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script setup>
import { ref } from "vue";

// declare an empty array variable to hold your data
const photos = ref([]);

//create a function to fetch your data
function getImages() {
fetch("https://jsonplaceholder.typicode.com/albums/1/photos")
.then((response) => response.json())
.then((data) => {
photos.value = data;
console.log(data);
});
}

getImages();
</script>

<template>
// loop over photos array with some bootstrap classes for styling
<div class="container">
<div class="row">
<div class="col-lg-3" v-for="(item, index) in photos" :key="index">
<img :src="item.url" class="w-100" />
</div>
</div>
</div>
</template>

5. Dynamic inline background images

I’ll add a little extra section here to quickly run over using dynamic background images with inline style tags. I’ll use the same function approach as in example #3.3, but use it inline.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script setup>
// where 'name' is the actual name of the file, and 'ext' is the extension
// i.e. myjpg.jpg

function getImageUrl(name, ext) {
return new URL(`./assets/img/${name}.${ext}`, import.meta.url).href;
}
</script>

<template>
<div class="container">
<div
class="row"
:style="{
background: 'url(' + getImageUrl('myjpg', 'jpg') + ')',
'background-size': 'cover',
}"
>
<div class="col-lg-3">
<h1>Background images!</h1>
</div>
</div>
</div>
</template>

Conclusion

Using images with Vite and Vue seemed like a head scratcher initially. I still don’t fully understand why it’s so counterintuitive when referencing local and/or dynamic assets. But hopefully this gives you a better idea. Again, I found the approach of using a function with dynamic file name and extension parameters to work best for multiple images with different formats. Be sure to check out the Vite docs for more info.

Source

https://medium.com/@andrewmasonmedia/how-to-use-images-with-vite-and-vue-937307a150c0