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

background-image in style property, what is the best practice? #646

Closed
NemoAlex opened this issue Feb 15, 2017 · 39 comments · May be fixed by vuejs/component-compiler-utils#37
Closed

background-image in style property, what is the best practice? #646

NemoAlex opened this issue Feb 15, 2017 · 39 comments · May be fixed by vuejs/component-compiler-utils#37

Comments

@NemoAlex
Copy link

In .vue template, we usually use img tag to show a image, like

<img src="./link/to/image.png">

which is OK.
However sometime we need to use background-image within inline style property:

<div style="background-image: url(./link/to/image.png)"

But it's not working, somehow I need to write it like this:

<div :style="{'background-image': 'url(' + require('./link/to/image.png') + ')'}">

or the ES2015 way:

<div :style="{'background-image': `url(${require('./link/to/image.png')})`}">

which is still not neat.
So I'm just wondering is there any better way to do this?

@Krispomoho
Copy link

I have met the same question, especially the image can't be converted as base64

@NemoAlex
Copy link
Author

Maybe it's a bad idea to use base64 image in style property, it makes HTML kinda ugly.

@yyx990803
Copy link
Member

Why not just use CSS instead of inline styles?

@blade254353074
Copy link

Required images is transformed to base64 DataURI is due to the limit option of url-loader.
You can reduce the limit, may be 10000 (bytes). It's useful to reduce the number of requests.

Then, vue-loader is piping <style></style> to the corresponding loader (depends on your config).
Such as scss-loader, postcss-loader, css-loader, style-loader, and css-loader will piping the results to url-loader and file-loader.
So you can just write css to instead of inline styles:

url(image.png) => require('./image.png')
url(~module/image.png) => require('module/image.png')

@NemoAlex
Copy link
Author

NemoAlex commented Mar 3, 2017

@yyx990803 @blade254353074 I know what we CAN. But it's a little bit annoying to do these workarounds.

@blade254353074
Copy link

For reducing requests, url-loader limit option must be configured......Although it's annoying.

@NemoAlex
Copy link
Author

NemoAlex commented Mar 3, 2017

@blade254353074 I believe the size limitation is not relevant in this conversation.

@blade254353074
Copy link

@NemoAlex But you said "base64 image in style property makes HTML kinda ugly"...

@willChowFront
Copy link

@yyx990803 I have the same issue .I need change this background-image frequently by data in component, in css , i can't find a way to solve it

@shshaw
Copy link

shshaw commented Jul 10, 2017

This isn't really vue-loader's fault, but I kept running into a similar issue where an image URL contained a space, so the style was invalid and would not appear on the element.

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>

@dimitrieh
Copy link

for Googlers, I had success with (using Nuxt):

:style="{ backgroundImage: 'url(' + require(@/assets/img/${page.image}) + ')' }"

@johnyluyte
Copy link

for Googlers, I has success with (same using Nuxt):

:style="{ backgroundImage: 'url(' + require('@/assets/imgs/bg'+backgroundId+'.png') + ')' }"

@dimitrieh 's answer is indeed correct, but his Template literals was "absorbed" by github's Markdown parser. If you copy his code from his comment directly, the code is not going to work.

However if you are using ES2015 you should be using Template literals. My code here is just for understanding the concept.

@PierBover
Copy link

Again, for Googlers...

In my case (an old Vue project) the problem seemed to be that the image wasn't being bundled by Webpack, even if the URL was right. Using require(...) returns the correct URL in the final bundle, but will also "tell Webpack" to bundle the image.

@chandregowda
Copy link

I placed the image inside public/img/<image.jpg> and then referred the image path mentioned in data property

<div class="text-center mb-4" :style="{ backgroundImage: url('${bgImage}')}">

data() {
    return {
      bgImage: "/img/virtual-mac.jpg"
    };
  },

@steelegg
Copy link

steelegg commented Jul 15, 2018

我没有找到更好的方法
I didn't find a better way.
但这样也可以解决我的问题
But it can also solve my problem.
如下:
as follows

<div  :style="{'background-image':'url('+backgroundUrl+');'}">
 data() {
         return { backgroundUrl:require('~/static/img/ads.png') }
        },

or

data(){
         return { backgroundUrl:'http://timgsa.baidu.com/timg?image&quality=80&size=b10000_10000&sec=1532246957&di=5c7453291ff3ca5963cca9c40a0be2ca&imgtype=jpg&src=http%3A%2F%2Fimg6.bdstatic.com%2Fimg%2Fimage%2Fpcindex%2Ftongmengpctufanbingbing.jpg' }
}

@Ubunfu
Copy link

Ubunfu commented Sep 3, 2018

I was able to accomplish what I believe is a similar end goal by using a computed property to build a collection of individual CSS attributes (dynamic or not), and then assign the whole group to the DOM element as an inline style.

Template:

<div class="movie-wrapper" :style="styles">
</div>

Computed Props:

<script>
const BACKDROP_BASE = 'https://image.tmdb.org/t/p/w1280';
export default {
    computed: {
        styles() {
            return {
                'background-image': `url(${BACKDROP_BASE}/${this.movie.backdrop_path})`,
                'background-repeat': 'no-repeat',
                'background-size': 'cover'
            }
        }
    }
}

And I could still attach additional properties with normal CSS, but it looks like any properties assigned via the computed property may take precedence as I think they are applied on top of the regular CSS.

Regular CSS:

<style scoped>
.movie-wrapper {
    position: relative;
    padding-top: 50vh;
}
</style>

@vitortraut95
Copy link

vitortraut95 commented Oct 5, 2018

Vue.filter('ifEmptyFoto',  function(value) {
      if (!value || value == "") { return 'images/foto_padrao.jpg'; }
      else return value;
})
Vue.filter('bgImage',  function(value) {
      return 'background-image: url('+ value +');';
})

<div class="foto" :style="caminhoImagem | ifEmptyFoto| bgImage"></div>

UncleBill added a commit to UncleBill/component-compiler-utils that referenced this issue Oct 26, 2018
UncleBill added a commit to UncleBill/component-compiler-utils that referenced this issue Oct 28, 2018
UncleBill added a commit to UncleBill/component-compiler-utils that referenced this issue Oct 31, 2018
@terryjohnpaul
Copy link

terryjohnpaul commented Dec 5, 2018

body
{background-image: url(image link);
background-size:cover;
} 

//place it in style tag..it worked for me

@adoniskrasniqi
Copy link

Why not just use CSS instead of inline styles?

Dynamic data.

@onuriltan
Copy link

onuriltan commented Jan 16, 2019

Hello everyone, if you want to use css background property from your assests, you can use it as follows;
background-image: url('~@/assets/img.jpeg');
If you want to know how this works, you can read it from here. Hope this helps :)

@Seanmclem
Copy link

I had to format mine like this with url('')
@import url('https://fonts.googleapis.com/css?family=Montserrat:400,700');

@jaeyholic
Copy link

I had difficulties with how to set dynamic background images in nuxt but i did it and it worked perfectly.

In SCRIPT
computed: {
service() {
return this.services.find(service => service.id === this.id)
},
backgroundURL() {
return require(~/assets/img/bgheads/${this.service.head})
}
}

In HTML

{{service.name}}

just in case if someone is also finding the same problems i faced. it took me some hours to figure it out

@Farb
Copy link

Farb commented Dec 17, 2019

image
image

I did it,but I fell it is annoying! It would be better if I can wirte the picture path directly! 😄

@pratyushtewari
Copy link

pratyushtewari commented Dec 26, 2019

#646 (comment)

Hello everyone, if you want to use css background property from your assests, you can use it as follows;
background-image: url('~@/assets/img.jpeg');
If you want to know how this works, you can read it from here. Hope this helps :)

We need to put this into the nuxt documentation. Please!

@onuriltan
Copy link

#646 (comment)

Hello everyone, if you want to use css background property from your assests, you can use it as follows;
background-image: url('~@/assets/img.jpeg');
If you want to know how this works, you can read it from here. Hope this helps :)

We need to put this into the nuxt documentation. Please!

Let me try it with Nuxt! Then I can send a pr to nuxt docs :)

@onuriltan
Copy link

#646 (comment)

Hello everyone, if you want to use css background property from your assests, you can use it as follows;
background-image: url('~@/assets/img.jpeg');
If you want to know how this works, you can read it from here. Hope this helps :)

We need to put this into the nuxt documentation. Please!

Let me try it with Nuxt! Then I can send a pr to nuxt docs :)

Actually Next Team stated about this issue in the docs, I read it carefully in order to catch the info :)
image

@pratyushtewari
Copy link

@onuriltan I saw this on nuxt, but your solution had both ~ and @ together and which is not mentioned in the nuxt documentation.

In the sass and css files I need to use the "@" path.
In the scoped css inside the vue files I need to use your solution the "~@" together.

@onuriltan
Copy link

onuriltan commented Dec 30, 2019

@pratyushtewari actually I tried those

  1. ~assets/img.jpeg = worked
  2. @assets/img.jpeg = didn't work
  3. ~@/assets/img.jpeg = worked

Yes the guide is a little bit misleading, I can open a pr but just in english language :)

@coolternet
Copy link

@pratyushtewari actually I tried those

  1. ~assets/img.jpeg = worked
  2. @assets/img.jpeg = didn't work
  3. ~@/assets/img.jpeg = worked

Yes the guide is a little bit misleading, I can open a pr but just in english language :)

it doesn't work for me

@kayoderock
Copy link

Don't waste time, @onuriltan is right.

@arijitnaskar
Copy link

This is Working for me:

:style="
    { backgroundImage: 'url(' + require('../assets/images/bg1.jpg') + ')'}"

But This is throwing compile error:

:style="
   { backgroundImage: 'url(' + require('../assets/images/bg1.jpg') + ')' ,
   backgroundSize:'cover'}"

Can someone help please.

Error:

Errors compiling template:

  invalid expression: Unexpected token ':' in

    
    { backgroundImage: 'url(' + require('../assets/images/bg1.jpg') + ')' ,
    backgroundSize:'cover'}

@pratyushtewari
Copy link

@arijitnaskar - Can you try this and see if this works?

:style="{ backgroundImage: url('" + require('../assets/images/bg1.jpg') + "') , backgroundSize: cover}"

@arijitnaskar
Copy link

Mine is working with this:

:style="
    [{ backgroundImage: 'url(' + require('../assets/images/bg1.jpg') + ')' 
   },{backgroundSize:'100%'},{backgroundPosition:'center bottom'}]"

@nejat-njonjo
Copy link

Close this.

@EmmyMay
Copy link

EmmyMay commented May 11, 2021

I am having this same issue. The path is resolving correctly but not as a string.

image

@nejat-njonjo
Copy link

Solutions were provided above.

@VivianS-GitHub
Copy link

I was able to accomplish what I believe is a similar end goal by using a computed property to build a collection of individual CSS attributes (dynamic or not), and then assign the whole group to the DOM element as an inline style.

Template:

<div class="movie-wrapper" :style="styles">
</div>

Computed Props:

<script>
const BACKDROP_BASE = 'https://image.tmdb.org/t/p/w1280';
export default {
    computed: {
        styles() {
            return {
                'background-image': `url(${BACKDROP_BASE}/${this.movie.backdrop_path})`,
                'background-repeat': 'no-repeat',
                'background-size': 'cover'
            }
        }
    }
}

And I could still attach additional properties with normal CSS, but it looks like any properties assigned via the computed property may take precedence as I think they are applied on top of the regular CSS.

Regular CSS:

<style scoped>
.movie-wrapper {
    position: relative;
    padding-top: 50vh;
}
</style>

how if hving multiple image?

@kuitao1018
Copy link

:style="{ 'background-image': 'url(' + ImgData + ')' }"

@Penguin-learning-to-walk
Copy link

Penguin-learning-to-walk commented Jan 30, 2023

мне помогло следующее :
<footer class="footer-area bg-img background-overlay" style="background-image: url('src/assets/img/bg-img/4.jpg');">

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

Successfully merging a pull request may close this issue.