140

I'm trying to bind the src of an image in an element, but it doesn't seem to work. I'm getting an "Invalid expression. Generated function body: { backgroundImage:{ url(image) }".

The documentation says to use either 'Kebab-case' or 'camel-case'.

<div class="circular" v-bind:style="{ backgroundImage: { url(image) }"></div>

Heres a fiddle: https://jsfiddle.net/0dw9923f/2/

Salman Zafar
  • 3,844
  • 5
  • 20
  • 43
CosX
  • 1,920
  • 2
  • 15
  • 25

19 Answers19

312

The issue is that the value for backgroundImage needs to be a string like this:

<div class="circular" v-bind:style="{ backgroundImage: 'url(' + image + ')' }"></div>

Here's a simplified fiddle that's working: https://jsfiddle.net/89af0se9/1/

Re: the comment below about kebab-case, this is how you can do that:

<div class="circular" v-bind:style="{ 'background-image': 'url(' + image + ')' }"></div>

In other words, the value for v-bind:style is just a plain Javascript object and follows the same rules.

UPDATE: One other note about why you may have trouble getting this to work.

You should make sure your image value is quoted so that the end resulting string is:

url('some/url/path/to/image.jpeg')

Otherwise, if your image URL has special characters in it (such as whitespace or parentheses) the browser may not apply it properly. In Javascript, the assignment would look like:

this.image = "'some/url/path/to/image.jpeg'"

or

this.image = "'" + myUrl + "'"

Technically, this could be done in the template, but the escaping required to keep it valid HTML isn't worth it.

More info here: Is quoting the value of url() really necessary?

David K. Hess
  • 16,632
  • 2
  • 49
  • 73
  • 18
    as of Mar 2016, it also needs to be camel case (`backgroundImage`) not kebab case (`background-image`) even though the docs say it can be either. – andrewtweber Mar 01 '16 at 21:50
  • 2
    If anyone's a goof like me, you might have done `backgroundImage: image` instead of `backgroundImage: 'url('+image+')'`. I got so hung up on the vue syntax that I forgot the `url()`. – bendytree Jun 06 '18 at 15:08
  • Within a Vue component, it worked for me just to say `v-bind:style="{ 'background-image': url(image) }"`, but outside of a component (just on a regular page) it seemed to require putting url in quotes. Does anyone know why that might be? – Keara Jun 25 '18 at 18:04
  • @Keara it doesn't make sense that it ever worked unless you had a function called "url" that produced the right thing in the appropriate scope. Can you put a fiddle together that demonstrates it? – David K. Hess Jun 25 '18 at 18:15
  • 2
    @David I think there actually was a url method that I wrote and forgot about, and that does exactly what I was expecting... that's pretty hilarious. I can't really test it in a fiddle because of the Vue components being in separate files, but I'm sure that's what was causing the weird behavior after all. Thanks! – Keara Jun 26 '18 at 02:33
  • Remember, don't use "-" or any math operation character in prop names – Mahdi Khansari Sep 20 '19 at 22:08
52
<div :style="{'background-image': 'url(' + require('./assets/media/img.jpg') + ')'}"></div>
mohammad nazari
  • 951
  • 8
  • 11
32

Another solution:

<template>
  <div :style="cssProps"></div>
</template>

<script>
  export default {
    data() {
      return {
        cssProps: {
          backgroundImage: `url(${require('@/assets/path/to/your/img.jpg')})`
        }
      }
    }
  }
</script>

What makes this solution more convenient? Firstly, it's cleaner. And then, if you're using Vue CLI (I assume you do), you can load it with webpack.

Note: don't forget that require() is always relative to the current file's path.

Mooncake
  • 1,477
  • 1
  • 22
  • 26
21
<div :style="{ backgroundImage: `url(${post.image})` }">

there are multiple ways but i found template string easy and simple

chougle saud
  • 277
  • 1
  • 3
  • 10
10

I searched in this post but no one posted require with dynamic filename that's why I am posting it.

:style="{ backgroundImage: `url(${require('@/assets/' + banner.image)})` }"
Nisharg Shah
  • 16,638
  • 10
  • 62
  • 73
7

I tried @david answer, and it didn't fix my issue. after a lot of hassle, I made a method and return the image with style string.

HTML Code

<div v-for="slide in loadSliderImages" :key="slide.id">
    <div v-else :style="bannerBgImage(slide.banner)"></div>
</div>

Method

bannerBgImage(image){
    return `background-image: url(${image})`;
},
devzakir
  • 387
  • 3
  • 15
  • 1
    I don't like using `methods` when we don't change the component's state. That's what `computed` are for.. – Narxx Sep 24 '21 at 21:18
  • @Narxx Method is useful, when you have the images in many places and you can fix them all by using the method. wherever you want to fix a background image. You call the method and pass the image as parameter. You are all set! – devzakir May 29 '22 at 07:53
  • You can do the same thing with computed. Computed can also take arguments, although the syntax is slightly different (but not much). Read here: https://stackoverflow.com/questions/40522634/can-i-pass-parameters-in-computed-properties-in-vue-js – Narxx May 30 '22 at 09:21
4

For single repeated component this technic work for me

<div class="img-section" :style=img_section_style >

computed: {
            img_section_style: function(){
                var bgImg= this.post_data.fet_img
                return {
                    "color": "red",
                    "border" : "5px solid ",
                    "background": 'url('+bgImg+')'
                }
            },
}
Salman Zafar
  • 3,844
  • 5
  • 20
  • 43
coder618
  • 848
  • 1
  • 9
  • 12
4

Try encodeURI()

The issue I had was due to special chars and/or whitespace in the URL I was attempting to use.

So I had to change this:

:style="{ backgroundImage : 'url(' + item.media.url + ')' }"

To this:

:style="{ backgroundImage : 'url(' + encodeURI(item.media.url) + ')' }"

AJB
  • 7,389
  • 14
  • 57
  • 88
3

Binding background image style using a dynamic value from v-for loop could be done like this.

<div v-for="i in items" :key="n" 
  :style="{backgroundImage: 'url('+require('./assets/cars/'+i.src+'.jpg')+')'}">
</div>
Abdelsalam Shahlol
  • 1,621
  • 1
  • 20
  • 31
3

I experienced an issue where background images with spaces in the filename where causing the style to not be applied. To correct this I had to ensure the string path was encapsulated in single quotes.

Note the escaped \' in my example below.

<div :style="{
    height: '100px',
    backgroundColor: '#323232',
    backgroundImage: 'url(\'' + event.image + '\')',
    backgroundPosition: 'center center',
    backgroundSize: 'cover'
    }">
</div>
William
  • 8,007
  • 5
  • 39
  • 43
3

The accepted answer didn't seem to solve the problem for me, but this did

Ensure your backgroundImage declarations are wrapped in url( and quotes so the style works correctly, no matter the file name.

ES2015 Style:

<div :style="{ backgroundImage: `url('${image}')` }"></div>

Or without ES2015:

<div :style="{ backgroundImage: 'url(\'' + image + '\')' }"></div>

Source: vuejs/vue-loader issue #646

bmatovu
  • 3,756
  • 1
  • 35
  • 37
3

I use the VUE options (~@/)

I defined a class

<template>
   <v-container class="bgExampleClass" fuild>
      <!-- Content-->
   </v-container>
</template>
<script></script>
<style>
  .bgExampleClass{
    background-image: url('~@/assets/imgs/backgroundExample.jpg');
  }
</style>
Ronald Coarite
  • 4,460
  • 27
  • 31
2

Based on my knowledge, if you put your image folder in your public folder, you can just do the following:

   <div :style="{backgroundImage: `url(${project.imagePath})`}"></div>

If you put your images in the src/assets/, you need to use require. Like this:

   <div :style="{backgroundImage: 'url('+require('@/assets/'+project.image)+')'}">. 
   </div>

One important thing is that you cannot use an expression that contains the full URL like this project.image = '@/assets/image.png'. You need to hardcode the '@assets/' part. That was what I've found. I think the reason is that in Webpack, a context is created if your require contains expressions, so the exact module is not known on compile time. Instead, it will search for everything in the @/assets folder. More info could be found here. Here is another doc explains how the Vue loader treats the link in single file components.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Liang
  • 105
  • 8
1

the easiest wat to add background image by style tag in vuejs is

<style>
.somediv {
 background-image: url('~@/image-path')
}
</style>

you need to add `~` before source alias
Sagar Davara
  • 408
  • 7
  • 13
1

A solution I'd recommend, without modifying too much of your fiddle code, only requires a simple tweak:

To quote a snippet of the Vue.js v2 documentation;

In-template expressions are very convenient, but they are meant for simple operations. Putting too much logic in your templates can make them bloated and hard to maintain.

As it applies to this very case, (assuming the value/state of the image data property isn't likely to change), using a computed property will keep your template cleaner and more maintainable. See refactor --

<!-- HTML -->
<div id="app"></div>
// JS
var template = "<div class=\"circular\" v-bind:style=\"imageUrl\"></div>";

var el = document.querySelector("#app");
var data = {
    image: "http://1.bp.blogspot.com/-8PfnHfgrH4I/TylX2v8pTMI/AAAAAAAAJJ4/TICBoSEI57o/s1600/search_by_image_image.png"
};
new Vue({
    el: el,
    replace: false,
    template: template,
    data: data,
    computed: {
        imageUrl: function() {
            return {'background-image': `url(${this.image})`}
        }
    }
})
tony19
  • 125,647
  • 18
  • 229
  • 307
David_
  • 31
  • 3
1
<template>
  <section :style="banner"></section>
</template>
<script>
import banner from "@/assets/images/banners/rectangle1.png";
export default {
  data() {
    return { banner: { backgroundImage: `url('${banner}')` } };
  },
};
</script>
STREET MONEY
  • 534
  • 4
  • 8
0

I had to add .default after require for this to work:

:style="{ backgroundImage: `url(${require('@/media/bg-1.jpg').default})` }"
Hafez Divandari
  • 8,381
  • 4
  • 46
  • 63
0

This also works:


    let path = require(`@/assets/images/${this.linkToImage}`);
    variableName = `background-image: url('${path}'); `

0

It worked for me

<div class="project" v-for="(project, index) in projects" :key="index">
      <div class="project-img">
        <div class="img-wrapper" :style="{ backgroundImage: `url(${project.imgUrl})` }">
        </div>
      </div>
    </div>


imgUrl: 'http://localhost:8080/img/lp-nike-1280x800.19e4d289.png'
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 19 '23 at 01:41