How do I set icon_color from a range of color based on percentage value?

What I’m trying to do is calculate the percentage of current temperature within the range of today’s forecast’s high and low, then choose a colour from a defined range and set the icon to the colour.

For example, the colour ranges from #12c2e9 at 0% to #f64f59 at 100%. Their respective RGB values are (18, 194, 233) and (246, 79, 89). I also want the midpoint to be white-ish (240, 240, 240).

So I derived a formula to get the RGB value for a given percentage. Let’s say the percentage is p.

if p <= 0.5:
  r = 18 + p * (240 - 18)
  g = 194 + p * (240 - 194)
  b = 233 + p * (240 - 233)
else:
  r = 240 + p * (246 - 240)
  g = 240 + p * (79 - 240)
  b = 240 + p * (89 - 240)

and with Home Assistant’s template:

{% set p=((states("input_number.test_slider")|int)/100) %}
{% set r_max=246 %}
{% set g_max=79 %}
{% set b_max=89 %}
{% set r_mid=240 %}
{% set g_mid=240 %}
{% set b_mid=240 %}
{% set r_min=18 %}
{% set g_min=194 %}
{% set b_min=233 %}
{% if p <= 0.5 %}
{{ '#%02x%02x%02x' | format((r_min + p * (r_mid - r_min)) | int, (g_min + p * (g_mid - g_min)) | int , (b_min + p * (b_mid - b_min)) | int) }}
{% else %}
{{ '#%02x%02x%02x' | format((r_mid + p * (r_max - r_mid)) | int, (g_mid + p * (g_max - g_mid)) | int , (b_mid + p * (b_max - b_mid)) | int) }}
{% endif %}

which gives me hex value based on the percentage p.

However, when I implement this into the card:

type: custom:mushroom-number-card
entity: input_number.test_slider
icon_color: >-
  {% set p=((states("input_number.test_slider")|int)/100) %}
  {% set r_max=246 %}
  {% set g_max=79 %}
  {% set b_max=89 %}
  {% set r_mid=240 %}
  {% set g_mid=240 %}
  {% set b_mid=240 %}
  {% set r_min=18 %}
  {% set g_min=194 %}
  {% set b_min=233 %}
  {% if p <= 0.5 %}
  {{ '#%02x%02x%02x' | format((r_min + p * (r_mid - r_min)) | int, (g_min + p * (g_mid - g_min)) | int , (b_min + p * (b_mid - b_min)) | int) }}
  {% else %}
  {{ '#%02x%02x%02x' | format((r_mid + p * (r_max - r_mid)) | int, (g_mid + p * (g_max - g_mid)) | int , (b_mid + p * (b_max - b_mid)) | int) }}
  {% endif %}

the icon colour of the card stays white, regardless of the value of the slider.

I’ve searched high and low for this, but I can’t really seem to find anything useful. There are lots of example for icon_color based to states with simple {% if %}{% endif %}, but not for more complex ones like this.

Can anyone help me with this?

Cannot say anything about the template itself & mushrooms - but with a standard Entities card + card-mod it gives some color.
My input_number ranges [0,100], minimal color “#31c1e8” (0%), maximum “#f34d5b” (100%).
No idea why you are having different values; probably we are using input_numbers with diff. ranges.

code
type: entities
entities:
  - entity: input_number.test_level_1
card_mod:
  style: |
    ha-card {
      {% set p=((states("input_number.test_level_1")|int)/100) %}
      {% set r_max=246 %}
      {% set g_max=79 %}
      {% set b_max=89 %}
      {% set r_mid=240 %}
      {% set g_mid=240 %}
      {% set b_mid=240 %}
      {% set r_min=18 %}
      {% set g_min=194 %}
      {% set b_min=233 %}
      {% if p <= 0.5 %}
      {% set COLOR= '#%02x%02x%02x' | format((r_min + p * (r_mid - r_min)) | int, (g_min + p * (g_mid - g_min)) | int , (b_min + p * (b_mid - b_min)) | int) %}
      {% else %}
      {% set COLOR = '#%02x%02x%02x' | format((r_mid + p * (r_max - r_mid)) | int, (g_mid + p * (g_max - g_mid)) | int , (b_mid + p * (b_max - b_mid)) | int) %}
      {% endif %}
      background: {{COLOR}};
    }

Maybe my little share from before can help too.

If you’re not dead set on the min/max requirement you can use it as is, or you can adapt it for your case.

I like this range:


And (as you noticed once) this logic is a perfect example of using a reusable custom template macros.

Yea, I have no idea why it didn’t work. Mushroom’s icon-color supports templating, so I have no idea at all. I have resorted to card-mod at last.

type: custom:mushroom-number-card
entity: input_number.test_slider
card_mod:
  style: 
    mushroom-shape-icon$ : |
      {% macro color_from_range(opacity) %}
        {% set p=((states("input_number.test_slider")|int)/100) %}
        {% set r_max=246 %}
        {% set g_max=79 %}
        {% set b_max=89 %}
        {% set r_mid=240 %}
        {% set g_mid=240 %}
        {% set b_mid=240 %}
        {% set r_min=18 %}
        {% set g_min=194 %}
        {% set b_min=233 %}
        {% if p <= 0.5 %}
        {% set r=((r_min + 2 * p * (r_mid - r_min)) | int) %}
        {% set g=((g_min + 2 * p * (g_mid - g_min)) | int) %}
        {% set b=((b_min + 2 * p * (b_mid - b_min)) | int) %}
        {% else %}
        {% set r=((r_mid + 2 * (p - 0.5) * (r_max - r_mid)) | int) %}
        {% set g=((g_mid + 2 * (p - 0.5) * (g_max - g_mid)) | int) %}
        {% set b=((b_mid + 2 * (p - 0.5) * (b_max - b_mid)) | int) %}
        {% endif %}
        rgba{{ r,g,b,opacity }}
      {%- endmacro -%}
      .shape {
        --shape-color: {{ color_from_range(0.2) }};
      }
    . : |
      {% macro color_from_range(opacity) %}
        {% set p=((states("input_number.test_slider")|int)/100) %}
        {% set r_max=246 %}
        {% set g_max=79 %}
        {% set b_max=89 %}
        {% set r_mid=240 %}
        {% set g_mid=240 %}
        {% set b_mid=240 %}
        {% set r_min=18 %}
        {% set g_min=194 %}
        {% set b_min=233 %}
        {% if p <= 0.5 %}
        {% set r=((r_min + 2 * p * (r_mid - r_min)) | int) %}
        {% set g=((g_min + 2 * p * (g_mid - g_min)) | int) %}
        {% set b=((b_min + 2 * p * (b_mid - b_min)) | int) %}
        {% else %}
        {% set r=((r_mid + 2 * (p - 0.5) * (r_max - r_mid)) | int) %}
        {% set g=((g_mid + 2 * (p - 0.5) * (g_max - g_mid)) | int) %}
        {% set b=((b_mid + 2 * (p - 0.5) * (b_max - b_mid)) | int) %}
        {% endif %}
        rgba{{ r,g,b,opacity }}
      {%- endmacro -%}
      mushroom-number-value-control {
        --slider-color: {{ color_from_range(1) }};
        --slider-bg-color: {{ color_from_range(0.2) }};
      }
      mushroom-shape-icon {
      --card-mod-icon-color: {{ color_from_range(1) }};
      
      }