Home > Mobile >  How to create a dynamic background image for components in Vue using props?
How to create a dynamic background image for components in Vue using props?

Time:01-30

Objective

I want to pass the path of an image as a prop to a component. I want the component to use the prop to dynamically generate the background image.

All my images in an assets folder in the Vue src folder. The path looks like '@/assets/images/subject/computers.jpeg'

Problem

No background image appears

This is what renders on the page:

enter image description here

However, nothing shows up

Strange Behaviour

For some reason, adding the exact same path name '@/assets/images/subject/computers.jpeg' in CSS works (Adding it in the <style> tags). It just doesn't work if it's v-bind inline style.

Here is what it looks like in my CSS

enter image description here

The problem with this though, is that it is not dynamically rendered CSS.

I inspected the element further and noticed some strange behavior. As you can see, the inline style is reading the image path as '@/assets/images/subject/computers.jpeg' (element.style in image below).

Whereas adding the path in CSS, changes '@/assets/images/subject/computers.jpeg' to 'http://localhost:8080/img/computers.7f3748eb.jpeg', which then correctly renders the background image.

enter image description here

Question

I suppose my question is twofold:

  1. How would you dynamically render a background image in Vue with props? Or is there a better way to do this?
  2. Why does binding inline styles not resolve the path (keeps using '@'), while adding it directly in the <script> tags does resolve the path?

Solution

Okay, big thank you to tao & Bernard Borg for helping me wrap my head around this.

I was able to solve this using computed properties like so:

const imgSrc = computed(() => require(`@/assets/images/subject/${props.subject.image}`))

Because of the way VueLoader (which is default in Vue) resolves the paths, I couldn't store the '@' path in the prop itself. Instead, the prop is just the image/file name (ex. "computers.jpeg"), and the computed property with require() handles resolving the prepended path to the image.

Afterwards, I added the computed property to my binded inline style like so:

<div  v-bind:style="{ backgroundImage: `url('${imgSrc}')` }">

Voila! It finally works.

TLDR

Pass only the image/file name as a prop, and prepend the path using require() in a computed property.

Cheers

  • Related