Green-to-red icon color gradient template (battery percentage)

In the past I have added templates to set the color of an icon based on a battery percentage. While this works, in this example, it is only limited to three colors.

variables:
  var_color: |-
    [[[ 
    var battery_level=entity.state;
    if (battery_level > 70) return 'lime';
    else if (battery_level >= 30) return 'yellow';
    else return 'red';
    ]]]

Obviously, it would not be hard to scale to add more colors. I’ve seen examples posted here in the forum that include as many as a dozen variables. But I wanted to make something better.

A while back I came across a Javascript snippet that converted a percentage to a HEX value for color ranging from red-to-green. (Javascript color scale from 0% to 100%, rendering it from red to yellow to green · GitHub) I wanted to incorporate something like it but didn’t know what I was doing or have the time.
image

So, here is what I adapted and applied the template to a custom:button-card and Mushroom Template Card:

custom:button-card

type: custom:button-card
entity: sensor.s22_ultra_battery_level
show_state: true
variables:
  var_color: |-
    [[[ 
      var percentage = entity.state;
      var r = 0; var g = 0; var b = 0;
      if (percentage < 50 ) {
        var r = 255;
        var g = parseInt(5.1 * percentage);
      } else {   
        var g = 255;
        var r = parseInt(510 - 5.10 * percentage);
      }
      var h = r * 0x10000 + g * 0x100 + b * 0x1;
      return '#' + ('000000' + h.toString(16)).slice(-6);
    ]]]
styles:
  icon:
    - color: '[[[ return variables.var_color ]]]'

image

Mushroom Template Card (I had to change the formula a little bit in this example. I believe the numbers were being rounded differently than the Javascript example and caused numbers greater than 96% to calculate incorrectly. I also customized the icon in this example. The custom:button-card inherits its icon from the entity but the Mushroom Template Card does not. The icon will show the appropriate icon for percentage and charging indicators.)

type: custom:mushroom-template-card
entity: sensor.s22_ultra_battery_level
primary: '{{ state_attr(entity, "friendly_name").title() }}'
secondary: '{{ states(entity) + "%" }}'
layout: vertical
icon: |
  {% set battery_level = states(entity) | int // 10 * 10 %}   
  {% set charging_state = states('sensor.s22_ultra_charger_type') %}   
  {% set is_charging = is_state('binary_sensor.s22_ultra_is_charging', 'on') | iif(True, False) %}  
  {% set map = {"none":"", "ac":"charging-", "wireless":"charging-wireless-"} %}  
  {% set charging = map[states('sensor.s22_ultra_charger_type')] %} 
  {% if battery_level == 100 and is_charging == True %} mdi:battery-charging   
  {% elif battery_level == 100 %} mdi:battery      
  {% elif battery_level >= 10 %} mdi:battery-{{charging}}{{battery_level}}    
  {% elif battery_level >= 0 %} mdi:battery-{{charging}}outline     
  {% else %} mdi:battery-unknown     
  {% endif %} 
icon_color: |-
  {% set percentage = states(entity) | int %}
  {% set r, g, b = 0, 0, 0 %}
  {% if (percentage <= 51) %}
    {% set r = 255 %}
    {% set g = (5.0 * percentage) | round | int %}
  {% else %}
    {% set g = 255 %}
    {% set r = (505 - 4.89 * percentage) | round | int %}
  {% endif %}
  {{ "#%0x" | format( r * 0x10000 + g * 0x100 + b * 0x1 ) }}

image

Source:
(Javascript color scale from 0% to 100%, rendering it from red to yellow to green · GitHub)

// License: MIT - https://opensource.org/licenses/MIT
// Author: Michele Locati <[email protected]>
// Source: https://gist.github.com/mlocati/7210513
function perc2color(perc) {
	var r, g, b = 0;
	if(perc < 50) {
		r = 255;
		g = Math.round(5.1 * perc);
	}
	else {
		g = 255;
		r = Math.round(510 - 5.10 * perc);
	}
	var h = r * 0x10000 + g * 0x100 + b * 0x1;
	return '#' + ('000000' + h.toString(16)).slice(-6);
}
5 Likes

That is really nice and might by useable elsewhere to.

Personally, I find those gradients to be used optimally when actually showing that scale completely and not on an individual icon ( like the battery now). The scale shows it’s power (the actual full gradient) while a single icon only holds, well, a single color :wink:

Couldn’t t we try and show this on let’s say the background scale of the gauge card?

Thomas posted something like that but I’ve never been able to get that working.
This might be another way to do so .

Have to look up the other post
Found it Gauge Card: how to get a gradually changing color? - #12 by thomasloven

Nice work! I just successfully added your code to a card_mod: tweak to style the battery icons as secondary entities in a custom:multiple-entity-row card which doesn’t support icon_color:

decluttering_templates:
  iblinds:
    card:
      type: vertical-stack
      cards:
        - type: custom:mushroom-title-card
          title: ''
          subtitle: '[[display_name]]'
          alignment: center
        - type: entities
          entities:
            - entity: cover.[[blind]]
              type: custom:multiple-entity-row
              name: ' '
              show_state: false
              card_mod:
                style:
                  hui-generic-entity-row$state-badge:
                    $: |
                      ha-state-icon {
                        {% if is_state(config.entity, 'open') %}
                          --card-mod-icon-color: green;
                          --card-mod-icon: phu:blind-tilt-open;
                        {% else %}
                          --card-mod-icon-color: orange;
                          --card-mod-icon: phu:blind-tilt-closed
                        {% endif %}
                      }
                  hui-generic-entity-row>div>div:nth-child(2)>div>state-badge:
                    $: |
                      ha-state-icon {
                        --card-mod-icon-color:
                          {% set percentage = states('sensor.[[blind]]_battery_level')|int %}
                          {% set r, g, b = 0, 0, 0 %}
                          {% if (percentage <= 51) %}
                            {% set r = 255 %}
                            {% set g = (5.0 * percentage) | round | int %}
                          {% else %}
                            {% set g = 255 %}
                            {% set r = (505 - 4.89 * percentage) | round | int %}
                          {% endif %}
                          {{ "#%0x" | format( r * 0x10000 + g * 0x100 + b * 0x1 ) }}
                      }
              entities:
                - entity: sensor.[[blind]]_battery_level
                  name: Battery
                  unit: ' '
                - entity: sensor.[[blind]]_battery_level
                  name: false
                  icon: true
          show_header_toggle: false
          state_color: false
          card_mod:

Armed with the above information, I have just successfully added an icon_color: template using custom-ui-only and my battery icons are now colored everwhere, including more info!

configuration.yaml:

home_assistant:
  customize_glob:
    sensor.*_battery:
      templates: &battery_color
        icon_color: >
            var r = Math.min(255, Math.round(510 - 5.10 * Number(state)));
            var g = Math.min(255, Math.round(5.10 * Number(state)));
            var h = r * 0x10000 + g * 0x100;
            return '#' + ('000000' + h.toString(16)).slice(-6);
#          return 'rgb(' + r + ',' + g + ',0)';

    sensor.*_battery_level:
      templates: *battery_color

image

Very nice…. Would be good it applies to all battery icons… even mushroom chipcards.

1 Like