Search code examples
vue.jsvuejs3

Vue3 - possible to bind prop to background-image in style?


Say I have the following component:

<template>
  <q-layout view="lHh lpR lFf">
    <q-page-container>
      <div class="image-container">
        Image Container
      </div>
      <slot />
    </q-page-container>
  </q-layout>
</template>

<script lang='ts' setup>
  const props = defineProps({
    image: { type: String, required: true, default: '' },
  });
  // console.log(image);
</script>

<style lang="scss" scoped>
  .image-container {
    display: none;

    @media (min-width: $breakpoint-sm-min) {
      background: v-bind("props.image") no-repeat left center fixed;
      display: block;
      background-size: cover;
      height: 100%;
      width: auto;
    }
  }
</style>

I can verify that the prop comes through as a string correctly, and according to the docs I can use v-bind to more easily insert dynamic values to the styles.

The image doesn't show up though, and I see this when I open the inspector: enter image description here

I've also tried variations of wrapping the v-bind inside of url(), but nothing appears to be working. Is this just not yet possible with Vue3?

Note: I am currently using Vue v3.2.29.


Solution

  • Thanks to @tony19 in the comments, we figured out that I wasn't too far off. Essentially, rather than trying to use url() in the css, I've moved that up to the parent that is passing down the prop.

    Parent.vue

    <template>
      <Child :image="`url(${image})`">
        ...
      </Child>
    </template>
    

    Child.vue

    <template>
      <q-layout view="lHh lpR lFf">
        <q-page-container>
          <div class="image-container">
            Image Container
          </div>
          <slot />
        </q-page-container>
      </q-layout>
    </template>
    
    <script lang='ts' setup>
      const props = defineProps({
        image: { type: String, required: true, default: '' },
      });
    </script>
    
    <style lang="scss" scoped>
      .image-container {
        display: none;
    
        @media (min-width: $breakpoint-sm-min) {
          background: v-bind("props.image") no-repeat left center fixed;
          display: block;
          background-size: cover;
          height: 100%;
          width: auto;
        }
      }
    </style>