Tile card - how to append unit of measure of attribute?

Hi all:
I’m new to tile card and have 2 questions:

  1. Notice for some attributes tile card can find out unit of measure and display them, for example all attributes in a weather entity. However for other entities with raw attribute values I can’t seem to find a way to append the unit. Is there a solution?
  2. Is it possible for tile card to include attribute from other entities? I have a temperature and humidity sensor and would like to display them together. Many thanks

Attributes can have UoM, depends on an integration which creates a sensor.
You can add manually any additional labels like UoM or a state of another entity to any card using a pseudo class like “after/before”, go to main card mod thread - 1st post - link to fantastic post - others - after/before for examples.

1 Like

Hi @Ildar_Gabdullin : thank you will give a try. For my future reference the post is here:

Hope you don’t mind me asking for a different question:
I have extensively used card-mod in picture element card (main floor plan) and bubble card pop-ups which can embed another picture element card. I noticed when I refresh the page or load the page first time from browser, card-mod style doesn’t apply consistently. I can always solve the issue by switch to another HA page (like energy) and switch back then everything works.
Recently I leaned a trick to load by adding card-mod.js to “frondend” in configuration.yaml. So it works better for the top level picture element card (floor plan) which consistently loads the styling. However the secondary pop-up picture element card (via bubble card pop-up) doesn’t get the styling always, and the trick is the same to switch to another HA page and then switch back, everything works again.
I’m trying everything that I can find online to attack this issue but nothing works so far, so would like to ask if you have heard similar issue and what was the solution? Very much appreciated!

Technically, it is better to ask this either in the main card-mod thread (better) or create a separate thread since it is not related to the main topic.
Can say nothing about bubbles.
If you experience issues with INSTANT applying of cardmod - consider using an external JS, find examples in main card-mod thread. (also in that fantastic post)

1 Like

Thanks, external JS do you mean the approach below?

frontend:
  extra_module_url:
    - /lovelace-card-mod/card-mod.js

I have already done it, if you mean something else please let me know.
Otherwise I will create a new post for this issue. Have a great day!

No, it a JS file you write yourself. Check fantastic post , section “others”

1 Like

Will do thanks!

If you are using Frontend module then you are likely now running two versiosn of card_mod so will still see weird issues like card_mod not applying - card_mod should always apply, even if slightly delayed. If it is not applying but does on change view etc, then it is likely due to duplicate card_mod running. See README in v4 beta branch which have an updated readme. This also applies to current release 3.4.5.

In summary if you have both Dashboard resource URL and Frontend module URL, they need to match EXACTLY including ?hacstag...

1 Like

Dear @dcapslock : thank you very much! I tried to update the path in configuration.yaml to match with resources and it indeed loads faster and more consistently now. However one of my pop-up picture element card still doesn’t get (some) styles applied for some reason, other pop-ups to work great now. The most strange part is for this particular pop-up, the complex style like spinning fan and a few icon-labels gets applied, however simple style like set background colour of the card and other icon-labels don’t apply. I suspect something wrong with my yaml. Have no idea how to troubleshoot such issue. The issue can be solved by simply switch to another HA page and switch back, so maybe some conflicting order of load resources. I’m not a UI developer so running out of ideas…

type: picture-elements
elements:
  - type: image
    image: /local/pictures/nilan_tank.png
    style:
      top: 83%
      left: 78.3%
      width: 22%
  - entity: sensor.nilan_outdoor_temperature
    style:
      color: white
      font-size: 120%
      font-weight: bold
      left: 30.5%
      top: 7.0%
    type: state-label
    title: Outdoor temperature
  - entity: sensor.nilan_outdoor_air_temperature_before_preheat
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 27.5%
      top: 41%
    type: state-label
    title: Outdoor air temperature before preheat
  - entity: sensor.nilan_exhaust_air_temperature_after_heat_exchange
    style:
      color: white
      font-size: 120%
      font-weight: bold
      left: 71.5%
      top: 7.0%
    type: state-label
    title: Exhaust air temperature after heat exchange
  - entity: sensor.nilan_exhaust_air_temperature_after_heat_pump
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 72%
      top: 41%
    title: Exhaust air temperature after heat pump
    type: state-label
  - entity: sensor.nilan_evaporator_temperature
    style:
      color: white
      font-size: 50%
      font-weight: bold
      left: 50%
      top: 32.5%
    type: state-label
    title: Evaporator temperature
  - entity: climate.nilan_ventilation
    attribute: current_temperature
    title: Ventilation thermostat
    suffix: " °C"
    style:
      font-size: 120%
      font-weight: bold
      left: 30.5%
      top: 66.5%
    type: state-label
    card_mod:
      style: |
        :host {
          color: {% if state_attr('climate.nilan_ventilation', 'hvac_action') == 'heating' %}
                    #ffc108;
                  {% elif state_attr('climate.nilan_ventilation', 'hvac_action') == 'cooling' %}
                    #45729e;
                  {% else %}
                    white;
                  {% endif %};
        }
  - entity: sensor.nilan_supply_air_temperature
    title: Supply air
    style:
      color: white
      font-size: 120%
      font-weight: bold
      left: 71.5%
      top: 66.5%
    type: state-label
  - entity: sensor.nilan_humidity
    title: Humidity
    style:
      color: white
      font-size: 120%
      font-weight: bold
      left: 50.0%
      top: 79.2%
    type: state-label
  - entity: climate.nilan_hot_water_electric_heater
    attribute: current_temperature
    suffix: " °C"
    title: Hot water electric heater thermostat
    style:
      font-size: 120%
      font-weight: bold
      left: 66%
      top: 75.5%
    type: state-label
    card_mod:
      style: |
        :host {
          color:
            {% if states('climate.nilan_hot_water_electric_heater') == 'off' %}
              white;
            {% elif state_attr('climate.nilan_hot_water_electric_heater', 'hvac_action') == 'heating' %}
              #ffc108;
            {% else %}
              #45729e;
            {% endif %}
        }
  - entity: climate.nilan_hot_water
    attribute: current_temperature
    suffix: " °C"
    title: Hot water thermostat
    style:
      font-size: 120%
      font-weight: bold
      left: 66%
      top: 86%
    type: state-label
    card_mod:
      style: |
        :host {
          color:
            {% if states('climate.nilan_hot_water') == 'off' %}
              white;
            {% elif state_attr('climate.nilan_hot_water', 'hvac_action') == 'heating' %}
              #ffc108;
            {% else %}
              #45729e;
            {% endif %}
        }
  - type: state-icon
    entity: sensor.nilan_water_compressor1
    title: Hot water compressor running
    style:
      left: 55%
      top: 85.6%
    card_mod:
      style: |
        :host {
          --state-icon-color:
            {% if states('sensor.nilan_water_compressor1') | float > 0 %}
              #ffc108;
            {% else %}
              #45729e;
            {% endif %}
        }
  - entity: climate.nilan_geothermal_heater
    attribute: current_temperature
    suffix: " °C"
    title: Geothermal heating thermostat
    style:
      font-size: 120%
      font-weight: bold
      left: 31%
      top: 91%
    type: state-label
    card_mod:
      style: |
        :host {
          color:
            {% if states('climate.nilan_geothermal_heater') == 'off' %}
              white;
            {% elif state_attr('climate.nilan_geothermal_heater', 'hvac_action') == 'heating' %}
              #ffc108;
            {% else %}
              #45729e;
            {% endif %}
        }
  - entity: binary_sensor.compressor_geothermal_heating
    title: Geothermal compressor running
    style:
      left: 20%
      top: 90.5%
    type: state-icon
  - entity: group.thermostats
    title: All thermostats
    style:
      left: 20%
      top: 83%
    type: state-icon
    card_mod:
      style: |
        :host {
          --state-climate-on-color: 
            {% if states('sensor.wavin_active_channels') | int > 0 %}
              #ffc108;
            {% else %}
              #45729e;
            {% endif %}
        }      
  - type: state-icon
    entity: climate.nilan_ventilation
    icon: mdi:fan
    title: Ventilation
    style:
      top: 57%
      left: 50%
    card_mod:
      style:
        state-badge:
          $:
            ha-state-icon:
              $:
                .: |
                  :host {
                    {% if is_state('binary_sensor.nilan_ventilation_off', 'on') %}
                      --card-mod-icon: mdi:fan-off;
                    {% else %}
                      --card-mod-icon: mdi:fan;
                    {% endif %}
                  }
                ha-icon:
                  $: |
                    ha-svg-icon {
                      {% if is_state('binary_sensor.nilan_ventilation_off', 'on') %}
                        color: #f44336;   /* Red when off */
                        animation: none;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'low' %}
                        color: #45729e;   /* Blue low */
                        animation: rotation 4s linear infinite;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'middle' %}
                        color: #4caf50;   /* Green middle */
                        animation: rotation 2s linear infinite;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'medium' %}
                        color: #ffeb3b;   /* Yellow medium */
                        animation: rotation 1.5s linear infinite;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'high' %}
                        color: #ffc108;   /* Orange high */
                        animation: rotation 1s linear infinite;
                      {% else %}
                        color: #9e9e9e;   /* Grey fallback */
                        animation: none;
                      {% endif %}
                    }

                    @keyframes rotation {
                      0% {
                        transform: rotate(0deg);
                      }
                      100% {
                        transform: rotate(360deg);
                      }
                    }
  - entity: sensor.nilan_inlet_fan_speed
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 77.0%
      top: 52.0%
    type: state-label
    title: Inlet fan speed
  - entity: sensor.nilan_exhaust_fan_speed
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 23.0%
      top: 52.0%
    type: state-label
    title: Exhaust fan speed
  - entity: sensor.nilan_exhaust_filter_days_left
    prefix: "Filter: "
    style:
      font-size: 100%
      font-weight: bold
      left: 50.0%
      top: 20%
    title: Filter change due in days
    type: state-label
    card_mod:
      style: |
        :host {
          color: 
            {% set days = states('sensor.nilan_exhaust_filter_days_left') | int %}
            {% if days == 360 %}
              #f44336
            {% elif days < 10 %}
              #ffc108
            {% else %}
              white
            {% endif %};
        }
  - entity: sensor.utilityroom_nilanplug_current_consumption
    prefix: "Energy: "
    style:
      font-size: 100%
      font-weight: bold
      left: 50.0%
      top: 25%
    title: Current consumption
    type: state-label
    card_mod:
      style: |
        :host {
          color: 
            {% set usage = states('sensor.utilityroom_nilanplug_current_consumption') | float(0) %}
            {% if usage > 1000 %}
              #f44336
            {% elif usage > 200 %}
              #ffc108
            {% else %}
              white
            {% endif %};
        }
  - entity: input_boolean.holiday_mode
    title: Holiday mode
    style:
      font-weight: bold
      left: 56%
      top: 56%
    type: state-icon
  - entity: binary_sensor.utilityroom_nilan_summer_mode
    title: Ventilation summer mode
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 44.0%
      top: 56%
    type: state-icon
  - entity: binary_sensor.nilan_water_4way_valve
    title: Four-way valve
    style:
      left: 32%
      top: 34.2%
    type: state-icon
  - entity: binary_sensor.nilan_compressor_heating_air
    title: Compressor heating air
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 49.5%
      top: 40.5%
    type: state-icon
  - type: state-icon
    entity: binary_sensor.anti_legionella_active
    title: Anti-legionella running
    style:
      font-size: 100%
      left: 78.3%
      top: 80%
    card_mod:
      style:
        state-badge:
          $:
            ha-state-icon:
              $:
                .: |
                  :host {
                    {% if is_state('binary_sensor.anti_legionella_active', 'on') %}
                      display: block;
                    {% else %}
                      display: none;
                    {% endif %}
                  }
                ha-icon:
                  $: |
                    ha-svg-icon {
                        color: #f44336;   /* Red */
                        animation: blink 3s linear infinite;
                    }
                    @keyframes blink {
                      0%, 50%, 100% { opacity: 1; }
                      25%, 75% { opacity: 0; }
                    }
  - type: conditional
    conditions:
      - condition: state
        entity: binary_sensor.anti_legionella_active
        state: "off"
    elements:
      - entity: switch.anti_legionella_manual
        title: Run anti-legionella now
        style:
          left: 78.3%
          top: 80%
        type: state-icon
  - entity: input_text.utilityroom_nilan_hotwater_plan_summary
    style:
      color: white
      font-size: 100%
      font-weight: bold
      left: 75%
      top: 97.5%
      transform: translate(-100%, -100%)
    type: state-label
    title: Hot water heating plan
  - type: custom:hui-element
    card_type: gauge
    entity: sensor.wavin_active_channels
    needle: true
    name: ""
    min: 0
    max: 16
    segments:
      - from: 0
        color: "#45729e"
      - from: 4
        color: "#4caf50"
      - from: 8
        color: "#ffeb3b"
      - from: 12
        color: "#ffc108"
    style:
      left: 30.8%
      top: 83%
      width: 20%
      height: 20%
    card_mod:
      style: |
        ha-card {
          background: none !important;
          box-shadow: none !important;
          border: none  !important;
          font-size: 1.5em !important;
          font-weight: bold !important; 
          --primary-text-color: white !important; /* fallback */
        }       
image: /local/pictures/nilan.png
card_mod:
  style: |
    ha-card {
      background:#8A9A5B;
    }

So I can take a look, can you point out specifically what is not working from your config?

Thank you and not supposed to get you spend lots of time checking my configuration, I’m very sorry about that. So what works:

  1. The spinning fan with below code:
  - type: state-icon
    entity: climate.nilan_ventilation
    icon: mdi:fan
    title: Ventilation
    style:
      top: 57%
      left: 50%
    card_mod:
      style:
        state-badge:
          $:
            ha-state-icon:
              $:
                .: |
                  :host {
                    {% if is_state('binary_sensor.nilan_ventilation_off', 'on') %}
                      --card-mod-icon: mdi:fan-off;
                    {% else %}
                      --card-mod-icon: mdi:fan;
                    {% endif %}
                  }
                ha-icon:
                  $: |
                    ha-svg-icon {
                      {% if is_state('binary_sensor.nilan_ventilation_off', 'on') %}
                        color: #f44336;   /* Red when off */
                        animation: none;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'low' %}
                        color: #45729e;   /* Blue low */
                        animation: rotation 4s linear infinite;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'middle' %}
                        color: #4caf50;   /* Green middle */
                        animation: rotation 2s linear infinite;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'medium' %}
                        color: #ffeb3b;   /* Yellow medium */
                        animation: rotation 1.5s linear infinite;
                      {% elif state_attr('climate.nilan_ventilation', 'fan_mode') == 'high' %}
                        color: #ffc108;   /* Orange high */
                        animation: rotation 1s linear infinite;
                      {% else %}
                        color: #9e9e9e;   /* Grey fallback */
                        animation: none;
                      {% endif %}
                    }

                    @keyframes rotation {
                      0% {
                        transform: rotate(0deg);
                      }
                      100% {
                        transform: rotate(360deg);
                      }
                    }

The colour of state-labels seems to work, an example:

  - type: state-label
    entity: climate.livingroom_thermostat
    title: Living Room Thermostat
    attribute: current_temperature
    suffix: °C
    style:
      top: 62%
      left: 66%
      border-radius: 50%
      text-align: center
      background-color: rgba(255, 255, 255, 0.1)
      backdrop-filter: blur(1px)
      opacity: 100%
      font-weight: bold
      font-size: 13px
    card_mod:
      style: |
        :host {
          color:
            {% if state_attr('climate.livingroom_thermostat', 'hvac_action') == 'heating' %}
              #ffc108;
            {% else %}
              #45729e;
            {% endif %}
        }
    tap_action:
      action: more-info
    double_tap_action:
      action: none
    hold_action:
      action: more-info

What doesn’t work:

  1. Font size are overly enlarged for all labels
  2. The background for the card also doesn’t apply:
card_mod:
  style: |
    ha-card {
      background:#8A9A5B;
    }

A workaround I found now is to wrap the whole thing into “custom:mod-card”

type: custom:mod-card
card_mod:
  style: |
    :host {
      --ha-card-background: transparent !important;
    }
    ha-card {
      background: #8A9A5B !important;
    }
card:
  type: picture-elements
  elements:
    - type: image
      image: /local/pictures/nilan_tank.png
      style:
        top: 83%
        left: 78.3%
        width: 22%
......
......

If mod-card works then you will find v4 (in beta) should work fine without mod-card. I say that the timimg of ha-card being available may have to do with loading of image. v4 will patch via hui-card which contains picture elememts card where v3.4.5 patches from ha-card which is in shadow root of picture elements card.

2 Likes

you can also try if using a setter for the fan-mode helps

{% set ventilation = states('binary_sensor.nilan_ventilation_off') %}
{% set fan_mode = state_attr('climate.nilan_ventilation', 'fan_mode') %}
{% if is_state(ventilation, 'on') %}
  color: #f44336;   /* Red when off */
  animation: none;
{% elif fan_mode == 'low' %}
  color: #45729e;   /* Blue low */
  animation: rotation 4s linear infinite;
{% elif fan_mode == 'middle' %}
  color: #4caf50;   /* Green middle */
  animation: rotation 2s linear infinite;
{% elif fan_mode == 'medium' %}
  color: #ffeb3b;   /* Yellow medium */
  animation: rotation 1.5s linear infinite;
{% elif fan_mode == 'high' %}
  color: #ffc108;   /* Orange high */
  animation: rotation 1s linear infinite;
{% else %}
  color: #9e9e9e;   /* Grey fallback */
  animation: none;
{% endif %}
}

its always wise to make those templates as robust as possible. using a setter like this assures there wont be timing problems inside the template itself

personally, I’d take out these comments inside the /* */ escapers, to be sure that wont break the interpreter under the multiline pipe. just incase…
if must be use the jinja comments

{% set ventilation = states('binary_sensor.nilan_ventilation_off') %}
{% set fan_mode = state_attr('climate.nilan_ventilation', 'fan_mode') %}
{# Red when off #}
{% if is_state(ventilation, 'on') %}
  color: #f44336;
  animation: none;
{# Blue low #}
{% elif fan_mode == 'low' %}
  color: #45729e;
  animation: rotation 4s linear infinite;
{# Green middle #}
{% elif fan_mode == 'middle' %}
  color: #4caf50;
  animation: rotation 2s linear infinite;
{# Yellow medium #}
{% elif fan_mode == 'medium' %}
  color: #ffeb3b;
  animation: rotation 1.5s linear infinite;
{# Grey fallback #}
{% elif fan_mode == 'high' %}
  color: #ffc108;
  animation: rotation 1s linear infinite;
{# Grey fallback #}
{% else %}
  color: #9e9e9e;
  animation: none;
{% endif %}
}

You’ll see the difference in the dev tools template editor
but, this has evolved a lot out of the original topic…

1 Like

Thank you both! Will refactor the code further.

1 Like