Lovelace: Button card

you can define additional logic, if the domain is sensor and use the correct form for theme variables, in case of sensor add attribute device class and their state

example for sensor battery, the correct theme var is:

var(--state-sensor-battery-high-color) 

let class = entity.attributes.device_class;

color = `var(--state-${domain}-${class}-${state}-color);

or use default option for button card

Theme vars are not supported for sensors - at least acc. to Docs (((
Battery is an exclusion.

in the previous post, I made a quick demonstration just for the switch, for more complex cases you can use extra_styles and hardcode your own styles for each domain, avoiding repetitive code. And the variables theme works.

This is possible, but I do not think that this is what OP needed.
Agree that we can provide different ways to solve a problem.

1 Like

Can someone help me understand or debug why the haptic option is not working for me? I’ve used the bubble card buttons before and they do haptics without exposing any settings for them, but I’m unable to get the button card to do any haptics. It’s obviously working on the device since it works with the aforementioned cards, but nothing happens with button cards. Config is just super basic:

  type: custom:button-card
  name: TEST
  tap_action:
    haptic: heavy
    action: navigate
    navigation_path: '#test'

Struggling with creating a header card that’s stuck to the top, with a button at the end of it that will open a menu. The upper card is my old header (bubble card) which shows how it should look, the button under it is my new header (custom button card), but i haven’t found out how to add the menu button at the end or make it stuck at the top of my view.

type: custom:button-card
layout: icon_name
name: Home Assistant
primary: Home Assistant
secondary: ''
icon: mdi:home-assistant
icon_color: white
size: 30%
multiline_secondary: false
tap_action:
  action: none
hold_action:
  action: none
double_tap_action:
  action: none
fill_container: false
card_mod:
  style: |
    ha-card {
      border: none;
      box-shadow: none;
      ha-card-border-width: 0px;
    }
styles:
  card:
    - height: 70px
    - font-weight: bold
    - font-size: 24px
    - background-color: rgba(0, 0, 0, 0.0)
  icon:
    - width: 70%
    - margin-left: '-60%'
  name:
    - margin-left: '-100%'
    - margin-top: 4%

Edit: Nevermind, it was easier to edit the bubble card for a good result.

Now i’m struggling with the text moving around on the card. How do i make the name and state always begin at a specific place on the card? If i copy the card to use with another entity, the name will move further to the right/left depending on how long the text is. The two cards on the bottom is custom buttons, the other ones are bubble buttons which is how it’s supposed to look.

The state of the battery should also always start at the percent.

square : false
type: grid
cards:
  - type: custom:button-card
    layout: icon_state_label
    name: Switchbot 3
    icon: mdi:battery
    color_type: icon
    entity: sensor.curtain_3_8155_batteri
    show_state: true
    show_name: true
    show_label: false
    size: 24px
    state:
      - value: '10'
        operator: <
        color: '#FF0000'
        icon: mdi:battery-10
      - value: '20'
        operator: <=
        color: '#ff6600'
        icon: mdi:battery-20
      - value: '30'
        operator: <=
        color: '#ff9933'
        icon: mdi:battery-30
      - value: '40'
        operator: <=
        color: '#ffcc00'
        icon: mdi:battery-40
      - value: '50'
        operator: <=
        color: '#FFFF00'
        icon: mdi:battery-50
      - value: '60'
        operator: <=
        color: '#FFFF00'
        icon: mdi:battery-60
      - value: '70'
        operator: <=
        color: '#FFFF00'
        icon: mdi:battery-70
      - value: '80'
        operator: <=
        color: '#CCFF33'
        icon: mdi:battery-80
      - value: '90'
        operator: <=
        color: '#66FF33'
        icon: mdi:battery-90
      - value: '100'
        operator: <=
        color: '#279b37'
        icon: mdi:battery-full
    styles:
      grid:
        - grid-template-areas: '"i n s"'
      card:
        - padding: 0%
        - height: 55px
        - background-color: rgba(1, 1, 1, 0.3)
      img_cell:
        - margin-left: 10%
        - border-radius: 24px
        - width: 40px
        - height: 40px
        - align-self: middle
        - justify-self: start
        - background-color: rgba(1, 1, 1, 0.3)
      state:
        - margin-left: 45%
        - align-self: middle
        - justify-self: start
        - font-size: 13px
      name:
        - font-weight: bold
        - margin-left: '-21%'
        - align-self: middle
        - justify-self: start
  - type: custom:button-card
    layout: icon_state_label
    name: Samsung Galaxy S22
    icon: mdi:battery
    color_type: icon
    entity: sensor.sm_s908b_battery_level
    show_state: true
    show_name: true
    show_label: false
    size: 24px
    state:
      - value: '10'
        operator: <
        color: '#FF0000'
        icon: mdi:battery-10
      - value: '20'
        operator: <=
        color: '#ff6600'
        icon: mdi:battery-20
      - value: '30'
        operator: <=
        color: '#ff9933'
        icon: mdi:battery-30
      - value: '40'
        operator: <=
        color: '#ffcc00'
        icon: mdi:battery-40
      - value: '50'
        operator: <=
        color: '#FFFF00'
        icon: mdi:battery-50
      - value: '60'
        operator: <=
        color: '#FFFF00'
        icon: mdi:battery-60
      - value: '70'
        operator: <=
        color: '#FFFF00'
        icon: mdi:battery-70
      - value: '80'
        operator: <=
        color: '#CCFF33'
        icon: mdi:battery-80
      - value: '90'
        operator: <=
        color: '#66FF33'
        icon: mdi:battery-90
      - value: '100'
        operator: <=
        color: '#279b37'
        icon: mdi:battery-full
    styles:
      grid:
        - grid-template-areas: '"i n s"'
      card:
        - padding: 0%
        - height: 55px
        - background-color: rgba(1, 1, 1, 0.3)
      img_cell:
        - margin-left: 10%
        - border-radius: 24px
        - width: 40px
        - height: 40px
        - align-self: middle
        - justify-self: start
        - background-color: rgba(1, 1, 1, 0.3)
      state:
        - margin-left: 45%
        - align-self: middle
        - justify-self: start
        - font-size: 13px
      name:
        - font-weight: bold
        - margin-left: '-21%'
        - align-self: middle
        - justify-self: start
columns: 1

I have the same issue with the stack-in-card. I created many custom cards with the stack in card, but the loading is like loading a website on an old land line.m (back to the 90’s).

I hope the transition to custom button card ,will solve this.

Hello sebbaT, Can you please share the yaml code of your lightcard? That would be great!
Thank you!

Hello pimp1310,
Can you Share the code from the Climate Card?

Hope I’m in the right thread here!
Please help!
How can I place a dividing line in the lower area and a text in the middle underneath?
should look like this!

rafa-test

bild-hilfe

type: custom:button-card
entity: sensor.tennis_atp_rafael_nadal_card
name: false
show_name: false
show_state: false
show_icon: false
styles:
  grid:
    - grid-template-areas: |
        "template template template"
  card:
    - border-radius: null
    - overflow: hidden
    - position: relative
    - padding: 0
    - display: flex
    - flex-direction: column
    - justify-content: center
    - align-items: center
  custom_fields:
    background-images:
      - position: absolute
      - inset: 0
      - display: flex
      - justify-content: space-between
      - align-items: center
      - opacity: 0.3
    foreground-images:
      - position: absolute
      - inset: 0
      - display: flex
      - justify-content: space-between
      - align-items: center
      - z-index: 0
custom_fields:
  template:
    card:
      type: custom:button-card
      name: |
        [[[
          let state = states['sensor.tennis_atp_rafael_nadal'].state;
          if (state === 'PRE') {
            return `Text <br/>${entity.state}<br/> ${entity.attributes.pre_runde_start_zeit}`;
          } else if (state === 'IN') {
            return `${entity.attributes.in_ergebnis_sets}<br/>LIVE ${entity.attributes.in_live_ergebnis_score}<br/>
            <div style="display: inline-block; text-align: right;">
            ${entity.attributes.in_spieler_score}<br/>
            ${entity.attributes.in_gegner_score}</div>`;
          } else if (state === 'POST') {
            return `Ergebnis ${entity.attributes.post_ergebnis_result}<br/>
            <div style="display: inline-block; text-align: right;">
            ${entity.attributes.in_spieler_score}<br/>
            ${entity.attributes.in_gegner_score}</div>`;
          } else if (state === 'NOT_FOUND') {
            return 'Momentan Keine Tennis ATP Spiele';
          }
        ]]]
      styles:
        card:
          - background-color: transparent
          - box-shadow: none
          - font-weight: bold
          - color: white
          - font-size: 16px
  background-images: |
    [[[
      return `
        <img src="/local/sportpng/flagen/spanien.png" alt="Left Back" style="height: 13rem; width: 11rem;">
        <img src="${states['sensor.tennis_atp_alexander_zverev'].attributes.opponent_logo}" alt="Right Back" style="height: 10rem; width: 10rem;">
      `;
    ]]]
  foreground-images: |
    [[[
      return `
        <img src="/local/sportpng/nadal.png" alt="Left Foreg" style="height: 7.5rem; ">
        <img src="https://a.espncdn.com/combiner/i?img=/i/headshots/tennis/players/full/${states['sensor.tennis_atp_alexander_zverev'].attributes.opponent_id}.png" alt="Right Foreg" style="height: 7.5rem; ">
      `;
    ]]]

attempt 2 with the same result

type: custom:button-card
entity: sensor.tennis_atp_card
name: false
show_name: false
show_state: false
show_icon: false
styles:
  grid:
    - grid-template-areas: |
        "template template template"
  card:
    - position: relative
    - padding: 0
  custom_fields:
    images:
      - position: absolute
      - inset: 0
custom_fields:
  template:
    card:
      type: custom:button-card
      name: |
        [[[
            return 'Template Text <br/>';
        ]]]
      styles:
        card:
          - background-color: transparent
          - box-shadow: none
          - font-weight: bold
          - color: white
          - font-size: 16px
  images: |
    [[[
      return `
          <div style="position: absolute; inset: 0; opacity: 0.3; display: flex; justify-content: space-between; align-items: center;">
            <img src="/local/sportpng/flagen/ger.png" alt="Left Background" style="height: 10rem; width: 10rem;">
            <img src="/local/sportpng/flagen/ita.png" alt="Right Background" style="height: 10rem; width: 10rem;">
          </div>
          <div style="position: absolute; inset: 0; display: flex; justify-content: space-between; align-items: center; flex-direction: column;">
            <div style="display: flex; justify-content: space-between; width: 100%;">
              <img src="/local/sportpng/ke.png" alt="Left Foreground" style="height: 7.5rem;">
              <img src="/local/sportpng/be.png" alt="Right Foreground" style="height: 7.5rem;">
            </div>
      `;
    ]]]

Hi all, does anyblody know whether it is possible to get system attributes from the custom button card? I’m trying to get the following attribute from an entity:
{{ device_attr(‘cover.roller_room’, ‘configuration_url’) }}
Is there an equivalent in java of the above jinja2 code?
I tried:
entity.attributes.system_mode == ‘configuration_url’
But it doesn’t work
Many thanks

Try
states[‘sensor.cover.roller_room’].attributes.configuration_url

I actually tried

states[‘cover.roller_room’].attributes.configuration_url

But it dowsn’t work since it’s a system parameter… It doesn’t show up as an attribute of the entity…

Hey all,
I have been racking my brain for a couple of hours / days over this;

This is what it currently looks like on PC, I would like the buttons to be “bigger” on PC as there is blank space at the bottom of the button that the text can take up (and has when I manually set it to a larger size).
image

tl;dr
Basically, I want to know - How do I change the height & width of the buttons depending on the size of the viewport/screen.
I know that Button Cards has extra_styles and I can target the @ media css query but I am not amazing at CSS.

Button Code:

type: custom:button-card
name: Computer
show_icon: false
show_state: true
state_display: blah blah blah (temp value)
styles:
  grid:
    - grid-template-areas: '"switch button" "n n" "s s"'
    - grid-template-rows: min-content min-content
  card:
    - padding: 6px 6px 3px 6px
    - height: 100%
  name:
    - font-size: 16px
    - font-weight: bold
    - color: var(--primary-text-color)
    - margin-top: 10px
    - margin-bottom: 0px
  state:
    - font-size: 12px
    - font-weight: bolder
    - color: var(--secondary-text-color)
    - margin-top: 4px
    - text-wrap: wrap
custom_fields:
  switch:
    card:
      type: custom:button-card
      entity: switch.plug_pc_switch
      template:
        - mini_button
  button:
    card:
      type: custom:button-card
      entity: button.pc_hibernate
      template:
        - mini_button
      styles:
        card:
          - align

Template Code:

button_card_templates:
  mini_button:
    show_name: false
    show_state: false
    variables:
      icon_on: gold
      icon_off: darkgray
      show_borders: false
    styles:
      card:
        - height: 40px
        - width: 40px
        - border: none
        - border-color: red
        - background-color: var(--secondary-background-color)
      icon:
        - transform: scale(0.75)
        - color: |
            [[[
              if(entity?.state == 'on')
                return variables.icon_on
              else
                return variables.icon_off
            ]]]
        - width: 100%
2 Likes

Hi all,

I’m trying to show/hide the name/state of my button depending on the window size.

I was hoping the following would work, but it doesn’t. Does anyone have any ideas?

show_name: "[[[ if (Number(window.innerWidth) <= 1179) return 'false'; else return 'true'; ]]]" 
show_state: "[[[ if (Number(window.innerWidth) <= 1179) return 'false'; else return 'true'; ]]]"

edit: I should add that setting label: does show the correct window size, but I can’t get the comparison to work. I’ve tried with and without Number().

label: "[[[ return window.innerWidth ]]]"

you need to have the button update those templates
considering they will only update on state changes, you’re lost…

unless, you set the triggers_update: option.

I tried something like you do now, but could only reliably have the buttons update using

triggers_update: all

it is not recommended to use that though, as it is rather active, updating on all state changes

For anyone that is interested in the future, after bunch of testing, the problem appears to related to the return 'false' which seems to have a special meaning in javascript.

I would say - “false” is not false because it is a string.