Reputation: 453
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?
Upvotes: 35
Views: 38987
Reputation: 9695
You can now pass css variables directly as props: https://svelte.dev/docs#template-syntax-component-directives---style-props
<Image --background-image='url(./images/image1.jpg)' />
In Image.svelte
background-image: var(--background-image, url(./images/default.jpg));
Upvotes: 19
Reputation: 693
I was able to achieve what you are asking for in the following way:
<script>
export let image_url;
</script>
<div class="image" style="--image_url: url({image_url})">
<p>some text</p>
</div>
<style>
.image{
background-image: var(--image-url);
}
</style>
The in the html part of the component has access to the props, so can pass the prop to style as a CSS variable. The CSS variable can then be used in the background_image directly.
Upvotes: 1
Reputation: 2867
Think of Svelte block as a CSS black box. You can't use javascript variables in the same way that you can't use them in a css file in the browser.
But...since it's a CSS box, you can always use scss and compile your block using a svelte preprocessor like this one. Then you can just do
<script>
export let image_url;
</script>
<style lang="scss">
@import "my/path/to/variables";
.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>
Upvotes: 0
Reputation: 29585
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>
Upvotes: 81