Skip to content

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

Closed
vuejs/component-compiler-utils
#37
@NemoAlex

Description

@NemoAlex

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?

Activity

Krispomoho

Krispomoho commented on Feb 17, 2017

@Krispomoho

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

NemoAlex

NemoAlex commented on Feb 17, 2017

@NemoAlex
Author

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

yyx990803

yyx990803 commented on Feb 19, 2017

@yyx990803
Member

Why not just use CSS instead of inline styles?

blade254353074

blade254353074 commented on Mar 3, 2017

@blade254353074

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

NemoAlex commented on Mar 3, 2017

@NemoAlex
Author

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

blade254353074

blade254353074 commented on Mar 3, 2017

@blade254353074

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

NemoAlex

NemoAlex commented on Mar 3, 2017

@NemoAlex
Author

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

blade254353074

blade254353074 commented on Mar 3, 2017

@blade254353074

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

willChowFront

willChowFront commented on Mar 29, 2017

@willChowFront

@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

shshaw commented on Jul 10, 2017

@shshaw

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

dimitrieh commented on Mar 31, 2018

@dimitrieh

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

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

johnyluyte

johnyluyte commented on May 15, 2018

@johnyluyte

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

PierBover commented on Jun 13, 2018

@PierBover

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

chandregowda commented on Jun 16, 2018

@chandregowda

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"
    };
  },

17 remaining items

onuriltan

onuriltan commented on Dec 30, 2019

@onuriltan

@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

coolternet commented on Mar 7, 2020

@coolternet

@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

kayoderock commented on Jun 15, 2020

@kayoderock

Don't waste time, @onuriltan is right.

arijitnaskar

arijitnaskar commented on Aug 12, 2020

@arijitnaskar

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

pratyushtewari commented on Aug 12, 2020

@pratyushtewari

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

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

arijitnaskar

arijitnaskar commented on Aug 13, 2020

@arijitnaskar

Mine is working with this:

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

nejat-njonjo commented on Mar 28, 2021

@nejat-njonjo

Close this.

EmmyMay

EmmyMay commented on May 11, 2021

@EmmyMay

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

image

nejat-njonjo

nejat-njonjo commented on May 18, 2021

@nejat-njonjo

Solutions were provided above.

VivianS-GitHub

VivianS-GitHub commented on Jul 19, 2021

@VivianS-GitHub

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

kuitao1018 commented on Oct 14, 2021

@kuitao1018

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

Penguin-learning-to-walk

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

@Penguin-learning-to-walk

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

kipropbrian

kipropbrian commented on Oct 18, 2024

@kipropbrian

If you have an issue where background-image works in development but leads to 404 in when you build, just move the image to public.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @PierBover@pratyushtewari@dimitrieh@yyx990803@shshaw

      Issue actions

        background-image in style property, what is the best practice? · Issue #646 · vuejs/vue-loader