Lovelace: Button card

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.

I’m not sure how to return anything in javascript (at least in button card, anyway) without it being in quotes based on all the examples provided in the repo.

Either way, I read that return false means ‘do not return anything’.

Definitely not. Do you have a source for that? Maybe you’re confusing the truthy and falsy values in YAML with this.

Regarding you original problem: Did you try changing'false' to false and 'true' to true?

Just this should do:

"[[[ return Number(window.innerWidth) > 1179); ]]]"

EDIT: show_name and show_state doesn’t support templating (see the docs).

2 Likes

Hi Pieter,

thanks for your reply - appreciated.

No, not confusing with YAML - I definitely read it whilst researching Javascript on stackoverflow or w3schools, but cannot find it now - maybe I misinterpreted the text. Thanks for correcting me.

thanks!

Well, that’s embarrassing, but I can see how I missed it. It doesn’t actually state that it doesn’t support templating, but all the options that do support tempting, explicitly state it. Thanks for pointing that out!

1 Like

Code for this card? Thanks

Hello esteemed tinkerers,

I’m a years-long user of button card but have not kept up with things in the past several years (kids!) and a recent HA update broke several cards that were working fine for years… they broke sometime between 2024.06 and 2024.10. I’m not up to speed on HA’s breaking changes.

I make heavy use of templating + decluttering cards and I’ve isolated the problem to the section below (remove it and the card functions). Have there been any breaking changes to HA over the past few months that would required a re-write here?

Lovelace Error:

ButtonCardJSTemplateError: TypeError: Cannot read properties of undefined (reading 'state') in 'if (states['sensor.chi'].state == "[[state2-2]]") return `<ha-icon icon="mdi:signal-dis...'

Relevant section of the broken card:

        custom1: |
          [[[
            if (states['[[sensor1-2]]'].state == "[[state1-2]]") 
              return `<ha-icon
                icon="mdi:[[icon1-2]]"
                style="width: 25px; height: 25px; color: steelblue;">
                </ha-icon><span>[[prefix1]]<span>${states['[[sensor1-1]]'].state}[[suffix1]]</span></span>`
            else 
              return `<ha-icon
                icon="mdi:[[icon1-1]]"
                style="width: 25px; height:25px; color: steelblue;">
                </ha-icon><span>[[prefix1]]<span>${states['[[sensor1-1]]'].state}[[suffix1]]</span></span>`
          ]]]  

I continue to look on my own but I’ve come up blank so far and don’t have as much time to dig (again, kids!) so I’ve come to the brain trust for ideas.

Thank you.