Search code examples
syntaxsvelte

Can I set svelte style css attribute values using variables passed in to a component


I want to create a svelte component that receives the name and path of an image. I want to have the component set the image as the "background-image" using CSS.

I've tried the following which does not seem to work...

Component called in App.svelte:

<Image image_url='./images/image1.jpg' />

Image.Svelte

<script>
export let image_url;
</script>

<style>
.image{
    position:relative;
    opacity: 0.70;
    background-position:bottom;
    background-size: cover;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-image: url({image_url});
    min-height: 100%;
}
</style>

<div class="image">
  <p>some text</p>
</div>

When I inspect the component the css for background_image is:

background-image: url({image_url});

Is it possible to have the variable converted in the CSS?


Solution

  • No. Component styles are shared between all instances of a component, either because they're statically extracted to a .css file, or because they're injected into a single <style> element that all components reference. If it were possible to put variables directly inside the component's <style>, it would mean that Svelte would need to create encapsulated styles per-instance, which would be detrimental to performance and would consume a lot more memory.

    There are two ways to approach this. The first is to use inline styles for anything that can change per-instance:

    <script>
    export let image_url;
    </script>
    
    <style>
    .image{
        position:relative;
        opacity: 0.70;
        background-position:bottom;
        background-size: cover;
        background-repeat: no-repeat;
        background-attachment: fixed;
        /* background-image: url({image_url}); */
        min-height: 100%;
    }
    </style>
    
    <!-- <div class="image"> -->
    <div class="image" style="background-image: url({image_url});">
      <p>some text</p>
    </div>
    

    The second, particularly if you need to use values in multiple places, is to use CSS variables:

    <script>
    export let image_url;
    </script>
    
    <style>
    .image{
        position:relative;
        opacity: 0.70;
        background-position:bottom;
        background-size: cover;
        background-repeat: no-repeat;
        background-attachment: fixed;
        /* background-image: url({image_url}); */
        background-image: var(--image);
        min-height: 100%;
    }
    </style>
    
    <!-- <div class="image"> -->
    <div class="image" style="--image: url({image_url});">
      <p>some text</p>
    </div>