Fun with custom:button-card

Yeah, as it turns out, mine either. :rofl: I’m sorry, I must have been asleep, when I posted this. :rofl: This is a mix-and-NOT-match between Javascript and HA template language, that can’t work, sorry! :slight_smile:

This should work, hopefully: :laughing:

           [[[
             if (states['input_select.marco_homemode'].state == 'Home') {
               return 'red'; }
             else {
               return 'black'; }
           ]]]

If you experience problems, that the color changes not right away, you might need to use triggers_update as well. :slight_smile:

1 Like

Hey all. Was wondering if someone could assist me. I’m having issues with my custom cards on my iOS companion app.

As you can see my slider progress isn’t filling the entire card. This isn’t the case on my pc or tablet. Anyone have any ideas? Here is my code:

type: custom:button-card
entity: light.living_room_lights
name: Living room
label: |
  [[[ if (entity.state == 'on')
    return (states['sensor.livingroom_count'].state) + ' On • ' + Math.round(entity.attributes.brightness/2.55) + '%';
    return entity.state;
  ]]]
icon: |
  [[[
    if (entity.state == 'on')
      return "fapro:light-group-fill";
      return "fapro:light-group";
  ]]]
size: 26px
show_name: true
show_label: true
custom_fields:
  slider:
    card:
      type: custom:my-slider-v2
      entity: light.living_room_lights
      allowTapping: true
      styles:
        card:
          - height: 100px
        container:
          - width: 360px
          - height: 100px
          - overflow: hidden
          - border-radius: 35px
        track:
          - width: 360px
          - height: 100px
          - background: |
              [[[
                if (entity.state == "on") return "#ffefc9";
                else return "#f2f6fc";
              ]]]
        progress:
          - height: 100px
          - postion: absolute
          - background: '#ffe082'
        thumb:
          - background: none
  button:
    card:
      type: custom:mushroom-chips-card
      chips:
        - type: template
          icon: |-
            {% if is_state(entity, 'off') %}
              mdi:chevron-down 
            {% elif is_state(entity, 'on') %}   
              mdi:chevron-up    
            {% endif %}
          tap_action:
            action: toggle
          entity: input_boolean.living_room_toggle
          icon_color: |-
            {% if is_state('light.living_room_lights', 'off') %}
              31,31,31
            {% elif is_state('light.living_room_lights', 'on') %}   
              115,92,0
            {% endif %}
          card_mod:
            style: |
              ha-card {
               --chip-icon-size: 0.7em;
               --chip-padding: 0px 6px;
               --chip-height: 40px;
               --chip-border-radius: 100px;
              }  
styles:
  grid:
    - grid-template-areas: |
        "i n button"
        "i l button"
    - grid-template-rows: 1fr 1fr
    - grid-template-columns: 68px min-content 2fr
  card:
    - height: 100px
    - width: 360px
    - border-radius: 35px
    - background-color: |
        [[[
          if (entity.state == 'on')
          return "#ffefc9";
          return "#f2f6fc";
        ]]]
  icon:
    - z-index: 1
    - color: |
        [[[
          if (entity.state == 'on')
          return "#735c00";
          return "#1f1f1f";
        ]]]   
  name:
    - z-index: 1
    - pointer-events: none
    - justify-self: start
    - font-weight: 600
    - font-size: 15px
    - margin: 16px 0px 0px 0px
    - color: |
        [[[
          if (entity.state == 'on')
          return "#735c00";
          return "#1f1f1f";
        ]]]  
  label:
    - z-index: 1
    - pointer-events: none
    - justify-self: start
    - text-transform: capitalize
    - font-weight: 500
    - font-size: 14px
    - margin: 0px 0px 13px 0px
    - color: |
        [[[
          if (entity.state == 'on')
          return "#735c00";
          return "#1f1f1f";
        ]]]  
  custom_fields:
    button:
      - z-index: 1
      - justify-self: end
      - padding-right: 24px
    slider:
      - z-index: 0
      - position: absolute
      - width: 360px
      - height: 100px

EDIT: Was able to come up with a fix. Change the slider portion of the code in custom-fields to this:

- z-index: 0
- position: absolute
- top: -10px
- width: 360px
- height: 120px

It will push the bar up a bit and over size it to fit.

Thank you so much!

1 Like

Hi all :slight_smile:
How can i display 2 icons in one card?
Say top left: a bulb and a power-icon…

Found a picture online with a card-example i really liked::

card_

How to make my card have booth a light bulb and power-icon, like the picture?

Thanx :slight_smile:

You can do this with a custom_fields. Check out the GitHub read me. It has a few examples that show how to do this.

Hello, all.
I had a custom button, rescalable, that I was using for 1+ year, and something changed on the app or the mobile browser and now I can’t seem to get the buttons back how I wanted them. They seem to display differently on mobile and on desktop chrome.

This is how I inteded the button to look:
image
and in fact, on desktop browser it is shown this way; but on mobile, it shows like this:
image
No matter how I change the margins, it always seems different on mobile vs desktop.
This is the example code:

type: custom:button-card
show_name: false
square: true
aspect_ratio: 1/1
entity: vacuum.roborock
size: 60%
tap_action:
  action: navigate
  navigation_path:
    - aspirador
double_tap_action:
  action: more-info
  entity: vacuum.roborock
hold_action:
  action: more-info
  entity: vacuum.roborock
styles:
  card:
    - margin-top: 20%
    - background-color: |
        [[[
          if (states['vacuum.roborock'].state == 'cleaning') return "#01450d";
          if (states['vacuum.roborock'].state == 'error') return "red";
          if (states['vacuum.roborock'].state == 'paused') return "orange";
          if (states['vacuum.roborock'].state == 'idle') return "yellow";
          if (states['vacuum.roborock'].state == 'returning') return "lightgreen";
          if (states['binary_sensor.roborock_carregar'].state == 'on') return "teal";
          return "#000000";
        ]]]
    - box-shadow: |
        [[[
          if (states['vacuum.roborock'].state == 'cleaning') return 'inset 0px 0px 4px 2px limegreen, 0px 0px 2px 1px limegreen'; return 'inset 0px 0px 4px 2px #444444, 0px 0px 0px 0px #444444';
        ]]]
    - border: 'n'
    - border-radius: 25%
  grid:
    - position: absolute
  custom_fields:
    local:
      - background-color: |
          [[[
            if (states['vacuum.roborock'].state != 'cleaning') return "#dddddd";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'sala') return "gold";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'sala_de_jantar') return "tomato";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'cozinha') return "aquamarine";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'casa_de_banho') return "orchid";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'quarto_principal') return "darkcyan";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'quarto_martim') return "yellowgreen";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'quarto_rafaela') return "deepskyblue";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'hall_quartos') return "antiquewhite";
            if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'casa_de_banho_principal') return "darkviolet";
            return "transparent";
          ]]]
      - border-radius: 50%
      - position: absolute
      - right: 10%
      - top: 7%
      - height: 23%
      - width: 23%
      - font-size: 1px
      - line-height: 1px
    carregar:
      - background-color: |
          [[[
            if (states['binary_sensor.roborock_carregar'].state == 'on') return "red";
            if (states['vacuum.roborock'].attributes.battery < 100) return "yellow";
            return "green";
          ]]]
      - border-radius: 50%
      - position: absolute
      - left: 10%
      - top: 7%
      - height: 23%
      - width: 23%
      - font-size: 1px
      - line-height: 1px
    mopa:
      - background-color: |
          [[[
            if (states['binary_sensor.roborock_mopa_instalada'].state == 'on')
              return "deepskyblue"; return "transparent";
          ]]]
      - border-radius: 40%
      - position: absolute
      - left: 40%
      - bottom: 2%
      - height: 25%
      - width: 25%
      - font-size: 1px
      - line-height: 1px
custom_fields:
  local: |
    [[[
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'sala')
        return `<ha-icon icon="mdi:sofa" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'sala_de_jantar')
        return `<ha-icon icon="mdi:silverware-variant" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'cozinha')
        return `<ha-icon icon="mdi:chef-hat" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_0' && states['sensor.roborock_quarto_atual'].state == 'casa_de_banho')
        return `<ha-icon icon="fas:toilet" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'quarto_principal')
        return `<ha-icon icon="ios:bed-double-fill" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'quarto_martim')
        return `<ha-icon icon="mdi:bed" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'quarto_rafaela')
        return `<ha-icon icon="mdi:bed-outline" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'hall_quartos')
        return `<ha-icon icon="hue:room-balcony" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      if (states['sensor.roborock_mapa_selecionado_atual'].state == 'piso_1' && states['sensor.roborock_quarto_atual'].state == 'casa_de_banho_principal')
        return `<ha-icon icon="fas:bath" style="width: 90%; height: 90%; color: #111111;"> </ha-icon>`;
      return `<ha-icon icon="mdi:numeric-0" style="width: 90%; height: 90%; color: transparent;"> </ha-icon>`;
    ]]]
  carregar: |
    [[[
      if (states['binary_sensor.roborock_carregar'].state == 'on')
        return `<ha-icon icon="mdi:battery-charging" style="width: 100%; height: 100%; color: #111111;"> </ha-icon>`;
      if (states['vacuum.roborock'].attributes.battery < 100)
        return `<ha-icon icon="mdi:battery-80" style="width: 100%; height: 100%; color: #111111;"> </ha-icon>`;
        return `<ha-icon icon="mdi:battery" style="width: 100%; height: 100%; color: #111111;"> </ha-icon>`;
    ]]]
  mopa: |
    [[[
      if (states['binary_sensor.roborock_mopa_instalada'].state == 'on')
        return `<ha-icon icon="mdi:receipt-text" style="width: 100%; height: 100%; color: #111111;"> </ha-icon>`;
        return `<ha-icon icon="mdi:door-open" style="width: 100%; height: 100%; color: transparent;"> </ha-icon>`;
    ]]]
state:
  - value: docked
    color: lightgray

Any suggestions on how to solve this? Thanks in advance!

EDIT: Found a SOLUTION that works: setting position from top was not consistant, so changed to bottom and now is consistant across browsers; don’t know why, but works, so maybe will help others:
I had:

    carregar:
      - background-color: |
          [[[
            if (states['binary_sensor.roborock_carregar'].state == 'on') return "red";
            if (states['vacuum.roborock'].attributes.battery < 100) return "yellow";
            return "green";
          ]]]
      - border-radius: 50%
      - position: absolute
      - left: 10%
      - top: 7%
      - height: 23%
      - width: 23%
      - font-size: 1px
      - line-height: 1px

Changed to:

    carregar:
      - background-color: |
          [[[
            if (states['binary_sensor.roborock_carregar'].state == 'on') return "red";
            if (states['vacuum.roborock'].attributes.battery < 100) return "yellow";
            return "green";
          ]]]
      - border-radius: 50%
      - position: absolute
      - left: 10%
      - bottom: 65% # <---- CHANGED on both custom_fields
      - height: 23%
      - width: 23%
      - font-size: 1px
      - line-height: 1px

They are now alligned.

I’m trying so hard to have the card background change according the the entity lights rgb. But no success. Can you guys help me out?

                
                - background: >
                    [[[
                      return "rgb(${state_attr('light.smart_bulb_office_desk','rgb_color')[0]}, ${state_attr('light.smart_bulb_office_desk','rgb_color')[1]}, ${state_attr('light.smart_bulb_office_desk','rgb_color')[2]})";
                    ]]]
```

Hey this is aweomse! I am not super familiar with booleans, what type of Boolean did you create to get the status of your Sonos speakers?

A very simple way would be like this:

entity: light.whatever_name
color_type: card
color: var(--button-card-light-color)

Have you tried adding “- justify-items: center” to your custom_fields styling?

Ok I managed to solve this (to have an element in the card in the same color as the light)

- color: >
    [[[
      return `rgb(${states["light.smart_bulb_office_desk"].attributes.rgb_color[0]},${states["light.smart_bulb_office_desk"].attributes.rgb_color[1]},${states["light.smart_bulb_office_desk"].attributes.rgb_color[2]})`;
    ]]]
1 Like

Hi everyone,
Both labels temp + hum don’t follow the color scheme when changing the state of the light (on/off).
I’d like both to have the yellow background and the text color changed to black, just like the name of the room.
I declared both custom_fields under state:, still the formatting remains.

Here’s the code (again) so far:

room_card:
    hold_action:
      action: more-info
      haptic: medium
    custom_fields:
      light:
        card:
          type: custom:button-card
          entity: '[[[ return entity.entity_id ]]]'
          show_name: false
          show_label: false
          tap_action:
            action: toggle
            haptic: medium
          state:
            - value: 'on'
              icon: mdi:lightbulb
            - value: 'off'
              icon: mdi:lightbulb-off
            - value: unavailable
              icon: mdi:lightbulb-question
              styles:
                icon:
                  - color: var(--contrast6)
            - value: unknown
              icon: mdi:lightbulb-question
              styles:
                icon:
                  - color: var(--contrast6)
          styles:
            icon:
              - width: 24px
              - height: 24px
      temp:
        card:
          type: custom:button-card
          entity: '[[[ return variables.var_a ]]]'
          label: >-
            [[[ return parseFloat(states[variables.var_a].state).toFixed(0) +
            states[variables.var_a].attributes.unit_of_measurement;  ]]]
          show_name: false
          show_label: true
          layout: icon_label
          icon: mdi:thermometer
          tap_action:
            action: more-info
            haptic: medium
          styles:
            icon:
              - width: 18px
              - height: 18px
              - color: var(--orange)
            label:
              - justify-self: start
              - font-size: 15px
            card:
              - height: a
              - width: 70px
      hum:
        card:
          type: custom:button-card
          entity: '[[[ return variables.var_b ]]]'
          label: >-
            [[[ return parseFloat(states[variables.var_b].state).toFixed(0) +
            states[variables.var_b].attributes.unit_of_measurement;  ]]]
          show_name: false
          show_label: true
          layout: icon_label
          icon: mdi:water-percent
          tap_action:
            action: more-info
            haptic: medium
          styles:
            icon:
              - width: 18px
              - height: 18px
              - color: var(--blue)
            label:
              - justify-self: start
              - font-size: 15px
            card:
              - height: a
              - width: 70px
    styles:
      grid:
        - grid-template-areas: '''i light'' ''n n'' ''temp hum'''
        - grid-template-columns: 1fr 1fr
        - grid-template-rows: 35% min-content min-content
      card:
        - background: var(--contrast2)
        - padding: 16px
        - '--mdc-ripple-press-opacity': 0
        - height: 115px
      img_cell:
        - justify-self: start
        - width: 24px
      icon:
        - width: 24px
        - height: 24px
        - color: var(--contrast8)
      name:
        - justify-self: start
        - font-size: 17px
        - margin: 4px 0 12px 0
        - color: var(--contrast8)
      custom_fields:
        temp:
          - justify-self: end
          - filter: opacity(90%)
          - margin: 4px 6px 12px
        hum:
          - filter: opacity(90%)
          - margin: 4px 0px 12px
    state:
      - value: 'on'
        styles:
          card:
            - background: var(--yellow)
          icon:
            - color: var(--black)
          name:
            - color: var(--black)
          custom_fields:
            temp:
              - color: var(--black)
            hum:
              - color: var(--black)
      - value: 'off'
        styles:
          icon:
            - color: var(--contrast20)
          name:
            - color: var(--contrast20)
          custom_fields:
            temp:
              - color: var(--contrast20)
            hum:
              - color: var(--contrast20)

Result so far:

Quick bump to this one … anybody? Thanks!

Just a fast question. Is it me or doesnt work mediaquerys ??
On the tab and laptop the button is spot on, but on mobile I want to skip the i from image.

You have not defined your cutom fields bankground colors anywhere, neither their initial colors or in the on/off state. If you add - background: none under styles it should do the trick. As for the black text I’m not sure tbh. You might be better of using if else templates under the styling instead.

Can you help me with hot to get this style of button-card? Its actual weather icon, outdoor / indoor temp.
image

To show both temperatures its ok, but how to show actual weather icon next to them?
And I wish to use emoji icon, so something like this:
cloudy": “:cloud:”,
“sun”: “:sun_with_face:”,
“fog”: “:fog:”,
“hail”: “:cloud_with_lightning_and_rain:”,

type: custom:button-card
entity: weather.myplace
size: 30%
show_name: false
show_label: true
show_icon: false
styles:
  card:
    - height: 300px
layout: label
label: |
  [[[ 
    var indoor = states['sensor.indoor_temperature'].state;
    var outdoor = states['sensor.outdoor_temperature'].state;
    var icon = "<ha-icon icon='mdi:thermometer' class='yellow'></ha-icon>" + indoor + '°C | ' + outdoor + '°C';
    return icon;
  ]]]

@radekD Something like this should work

  [[[ 
    var weather = states['weather.your_sensor'].state;
    var indoor = states['sensor.indoor_temperature'].state;
    var outdoor = states['sensor.outdoor_temperature'].state;
    var icons = "mdi:ab-testing";     
    if (weather == 'sunny')
      var icons = "mdi:weather-sunny";
        if (weather == 'fog')
          var icons = "mdi:weather-fog";
            if (weather == 'partlycloudy')
              var icons = "mdi:weather-partly-cloudy";
                if (weather == 'cloudy')
                  var icons = "mdi:weather-cloudy";
    else (weather == 'wind')
      var icons = "mdi:weather-windy";
    return  `<ha-icon icon="${icons}"</ha-icon>` + indoor + '°C | ' + outdoor + '°C';
  ]]]

Thanks!
I make some small correction, here is finall code (if someone need):

type: custom:button-card
entity: weather.myplace
show_name: false
show_label: true
show_icon: false
aspect_ratio: 10/1
tap_action:
  action: more-info
styles:
  label:
    - justify-self: start
    - padding-left: 10px
label: |
  [[[ 
    var weather = states['weather.myplace'].state;
    var indoor = states['sensor.indoor_temperature'].state;
    var outdoor = states['sensor.outdoor_temperature'].state;
    var icons = "mdi:ab-testing";
      if (weather == "cloudy")
        icons = "mdi:weather-cloudy";
      if (weather == "fog")
        icons = "mdi:weather-fog";
      if (weather == "hail")
        icons = "mdi:weather-hail";
      if (weather == "lightning")
        icons = "mdi:weather-lightning";  
      if (weather == "lightning-rainy")
        icons = "mdi:weather-lightning-rainy"; 
      if (weather == "partycloudy")
        icons = "mdi:weather-partly-cloudy"; 
      if (weather == "pouring")
        icons = "mdi:weather-pouring";
      if (weather == "rainy")
        icons = "mdi:weather-rainy";
      if (weather == "snowy")
        icons = "mdi:weather-snowy";
      if (weather == "snowy-rainy")
        icons = "mdi:weather-snowy-rainy";
      if (weather == "sunny")
        icons = "mdi:weather-sunny";
      if (weather == "windy")
        icons = "mdi:weather-windy";

        
    return  `<ha-icon
      icon="${icons}"
      style="width: 22px; height: 22px;">
      </ha-icon>` + indoor + '°C | ' + outdoor + '°C';
  ]]]

It look like this:
image

There is only small problem - emoji icon not work :frowning:

1 Like

Is there a way to flash card border with a different color when the card is tapped?

Thank you.

Edit: This is the card-mod yaml I have been using to flash the button-card border but feels like it should be translatable in to native button-card settings, but have not been successful. Thanks!


    card_mod:
      style: |
        ha-card {
          transition: border 0.5s;
        }
        ha-card:active {
          animation: flashBorder 0.5s;
        }
        @keyframes flashBorder {
          0%, 100% { border-color: gold; }
          100% { border-color: gold; }
        }

1 Like

Hello,
Thank you so much for these, very helpful.
I am new to this and not sure where to put these and trying to organize them in into different files:

In configuration.yaml I have added this line:
button_card_templates: !include button_card_templates.yaml

and in the button_card_templates.yaml I have added the button templates like this:

standard:
hold_action:
action: toggle

… rest of the lines removed here

wide:
template: standard
styles:
grid:

… rest of the lines removed here

It doesn’t pass the validation and says:

Integration error: button_card_templates - Integration ‘button_card_templates’ not found.

I can’t see what I am doing wrong.

Any help from anyone here is appreciated. Thank you.