How to reference to an image by name specified in setting?

AI-generated summary

The discussion revolves around referencing an image by name specified in settings for a theme component. fbpbdmin is trying to use an image in SCSS, where the image name is defined in about.json and selected through a setting in settings.yml.

The initial attempt to use an if-else statement in SCSS proved cumbersome, and an alternative approach using a function was attempted. However, this function returned an incorrect URL.

Arkshine suggested using interpolation to directly reference the setting, which partially solved the issue. However, it was discovered that the url() function requires a variable, not a string.

After further attempts, Arkshine proposed an alternative solution using JavaScript to set a custom CSS property with the image URL. This approach involves accessing the theme_uploads object and setting the custom property using the selected image’s URL.

This solution is demonstrated with an example, showcasing how to set the custom property using JavaScript and reference it in CSS.

in a theme component, which shows an image (hat) on screen

to use an image in scss, it works with its asset name directly like this,
these images are defined in about.json

{
  "name": "christmas-decorations",
  "about_url": "",
  "license_url": "",
  "author": "",
  "assets": {
    "red-hat1": "assets/decorations/red-hat1.png",
    "red-hat2": "assets/decorations/red-hat2.png",
    "squirrel2": "assets/decorations/squirrel2.png",
  }
}

to use these images in scss, it works well if use the asset name directly as this

background: transparent url($red-hat1) top left no-repeat;

I want to add a setting to pick an image.
in settings.yml, I have this, to select a hat image to show on screen

hat_type:
  default: red-hat1
  type: enum
  choices:
    - red-hat1
    - red-hat2
    - squirrel2

I could do if else in the scss to use the image, but this if else block could be too long …

    @if $hat_type == "red-hat1" {
      background: url($red-hat1) no-repeat center;  
    } @else if $hat_type == "red-hat2" {
      background: url($red-hat2) no-repeat center;  
    } @else if $hat_type == "squirrel2" {
      background: url($squirrel2) no-repeat center;  
    } 

I tried to use a function in scss

 background: url(get_image($hat_type)) no-repeat center;  

@function get_image($name){
  @return "assets/decorations/" + $name + ".png"
}

but this get a url as
https://www.domain.com/stylesheets/assets/decorations/squirrel2.png
this doe not work, it should be resolved as this instead…
https://www.domain.com/uploads/db9860/original/3X/9/1/91d36fdb030047c6390f9ca85604fdbfd2e3fc12.png

could someone give a hint, thanks a lot :slight_smile: …

I believe you can use the setting directly using interpolation.

background: transparent URL("$#{$hat_type}") top left no-repeat;

thanks Arkshine.

with this syntax, I picked sequirrel2 for the hat_type in settings.

background: transparent url("$#{$hat_type}") top left no-repeat;

in the web page, checked the styles, it is converted into this…

guess
inside the function url(), it needs to be a variable $squirrel2,
while “$#{$hat_type}”, this gives a string $squirrel2… ?


and I tried this

background: transparent url("assets/decorations/#{$decoration_image}.png") top left no-repeat;

it is rendered as this, still not right
image

Try adding a / to the beginning of that assets path.

thanks @Firepup650
tried to add a / before assets, it does not fly either, it adds a / in the middle,
but it does not convert it into the real url, should be something like
https://www.domain.com/uploads/db9860/original/3X/9/1/91d36fdb030047c6390f9ca85604fdbfd2e3fc12.png

You’re right; I thought it worked on my side, but I guess not. :thinking:

Here an alternative: setting a custom CSS property via js.

document.documentElement.style.setProperty(
  "--hat-url",
  `url(${settings.theme_uploads[settings.hat_type]}`
);
body {
  background: var(--hat-url);
}

settings.theme_uploads will contain a list of your uploads.
For example:
image

Then, based on your setting, you set the custom property.

Note that, from my testing, it doesn’t work doing url(var(--hat-url)), that’s why I passed the url() directly in the custom property.