Fun with custom:button-card

hello
I used this code for a map:
It works well on PC, however on my iphone this card does not appear.
is there a reason??
I’m looking to develop a specific interface for a project, and suddenly I’m stuck
Can you help me??

type: custom:button-card
name: Change Background
aspect_ratio: 4/1
extra_styles: |
  @keyframes bgswap1 {
    0% {
        background-image: url("/local/background1.jpg");
    }
    25% {
         background-image: url("http:/local/Maison essai HA 1600 500.jpg");
    }
    50% {
      background-image: url("http:/local/Maison essai HA 1600 500.jpg");
    }
    75% {
         background-image: url("http:/local/Maison essai HA 1600 500.jpg");
     }
     100% {
         background-image: url("http:/local/Maison essai HA 1600 500.jpg");
     }
   }
styles:
  card:
    - animation: bgswap1 30s linear infinite
    - background-size: cover
  name:
    - color: white

that looks freaking amazing. would you share the code from your amazon playlist scripts?

thx in advance

Weaver, thank you and please don’t read to much in to the scripting side. These are just simple scripts to push the request through to my Alexa Sound Notification.
I simply chose the playlists my wife listens too in Amazon music and created a script to push.
The playlists themselves are Amazon created and are updated regularly through their AI engine so kept current, ie less repeats.

Its all very basic but effective, and looks good on both my panel/tablet and phone. I am just looking to add a bit more visual feedback, hence my request to find a script/java or some direction to help animate the active playlist icon.

Scripts, i am sure there are more sophisticated ways to pull this info into HA :wink: but if you still want them please let me know, I am happy to share.

Sparky

Hi all, I have a driveway light which can be switched on manually or by a motion sensor. The motion sensor will activate the light for 5 minutes then switch the light off. The automation is triggered only if the light is off to avoid switching off the light when it is manually switched on.

In the dashboard I have the light in a custom button card, I want to add the timer (helper) to the same card (preferred in the background) to show how the lights are triggered and what is the remaining time.

I successfully did it through custom fields but I am unable to lay the two entities on the top of each other, only next to each other. also the card dimensions is not matching the other cards in the same grid.

Can someone assist with animations in this media player card I have made?

The animations are set in start and stop/pause playback however if nothing is playing the start animation always triggers when you open the page.

type: custom:button-card
aspect_ratio: 2.5/1
variables:
  conditional_audio: |
    [[[ 
      return (states['input_select.conditional_audio_media'].state) 
    ]]]
  active_speaker: |
    [[[ 
      return (states['input_text.active_speaker'].state) 
    ]]]
triggers_update: all
entity_picture: |
  [[[ 
    if ((states[variables.active_speaker].state) == 'playing')
      return (states[variables.active_speaker].attributes.entity_picture)
    else return ''
  ]]]
show_entity_picture: true
show_name: true
icon: ' '
name: ' '
show_label: true
tap_action:
  action: navigate
  navigation_path: /lovelace/music
label: >
  [[[ return  `<svg xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:serif="http://www.serif.com/"
  width="100%" height="100%" viewBox="0 0 81 308" version="1.1"
  xml:space="preserve"
  style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
    <g>
        <g transform="matrix(0.723348,-5.68332e-17,0,0.723348,-13.0563,-87.3471)">
            <path d="M83.865,125C109.253,125 129.865,145.612 129.865,171C129.865,196.388 109.253,217 83.865,217C58.477,217 37.865,196.388 37.865,171C37.865,145.612 58.477,125 83.865,125ZM83.865,131.174C105.846,131.174 123.691,149.019 123.691,171C123.691,192.981 105.846,210.826 83.865,210.826C61.885,210.826 44.039,192.981 44.039,171C44.039,149.019 61.885,131.174 83.865,131.174Z" style="fill-opacity:0.2;"/>
        </g>
        <use xlink:href="#_Image1" x="0" y="0" width="64.438px" height="307.929px" transform="matrix(0.991348,0,0,0.99977,0,0)"/>
    </g>
    <defs>
        <image id="_Image1" width="65px" height="308px" xlink:href="data:image/png;base64,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"/>
    </defs>
  </svg>` ]]]
extra_styles: |
  @keyframes record_rotation {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
  @keyframes handle_rotation {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(14deg); }
  }
custom_fields:
  bg: |
    [[[
      return " "
    ]]]
  media_controls:
    card:
      type: custom:button-card
      show_state: true
      show_label: true
      state_display: |
        [[[
          var active_speaker_media_artist = (states[variables.active_speaker].attributes.media_artist);
          var active_speaker_media_title = (states[variables.active_speaker].attributes.media_title);
          if (((states[variables.active_speaker].state) == 'playing') && (active_speaker_media_artist != '')) return active_speaker_media_artist +" <br> "+ active_speaker_media_title;
          else if (((states[variables.active_speaker].state) == 'playing') && (active_speaker_media_title != '')) return active_speaker_media_title;
          else return "Idle";
        ]]]
      custom_fields:
        forward:
          card:
            type: custom:button-card
            icon: mdi:skip-next
            styles:
              card:
                - margin-top: 25px
                - border-radius: 0
                - background-color: transparent
                - box-shadow: none
            tap_action:
              action: call-service
              service: media_player.media_next_track
              service_data:
                entity_id: '[[[ return variables.active_speaker ]]]'
        backward:
          card:
            type: custom:button-card
            icon: mdi:skip-previous
            styles:
              card:
                - margin-top: 25px
                - border-radius: 0
                - background-color: transparent
                - box-shadow: none
            tap_action:
              action: call-service
              service: media_player.media_previous_track
              service_data:
                entity_id: '[[[ return variables.active_speaker ]]]'
        play:
          card:
            type: custom:button-card
            icon: |
              [[[ 
                  if ((states[variables.active_speaker].state) == "playing") return "mdi:pause"
                  else return "mdi:play"
              ]]]
            styles:
              card:
                - margin-top: 25px
                - border-radius: 0
                - background-color: transparent
                - box-shadow: none
            tap_action:
              action: call-service
              service: media_player.media_play_pause
              service_data:
                entity_id: '[[[ return variables.active_speaker ]]]'
      styles:
        grid:
          - grid-gap: 10px
          - grid-template-areas: '"s s s" "backward play forward"'
          - grid-template-rows: 1fr
          - grid-template-columns: 1fr 1fr 1fr
          - margin: 0
          - padding: 0
        card:
          - background-color: transparent
          - box-shadow: none
          - border: 0
styles:
  grid:
    - grid-template-areas: '"i n l media_controls"'
    - grid-template-rows: 1fr
    - grid-template-columns: 50% auto
    - margin: 0
    - padding: 0
  card:
    - padding: 0
  img_cell:
    - grid-column: i / l
    - padding: 0
    - margin: 0
  icon:
    - z-index: 3
    - clip-path: circle(50% at 50% 50%)
    - transform: scale(0.8)
  name:
    - padding: 0
    - margin: 0
    - width: 75%
    - height: 90%
    - background: center center / cover no-repeat
    - background-image: url("/local/images/vinyl-record2.png")
    - z-index: 1
    - grid-column: i / l
  label:
    - z-index: 2
    - width: 25%
    - height: 70%
    - position: absolute
    - left: 30%
    - top: 10%
    - transform-origin: 65px 15px
  custom_fields:
    bg:
      - background: center center/cover no-repeat
      - height: 100%
      - width: 100%
      - position: absolute
      - z-index: 0
      - margin: 0
      - padding: 0
state:
  - operator: template
    value: |
      [[[
        if ((states[variables.active_speaker].state) != "playing") return "True";
      ]]]
    styles:
      name:
        - transition: all 2s ease-out
      icon:
        - transition: all 2s ease-out
      label:
        - animation-iteration-count: 1
        - animation: handle_rotation 2s normal backwards
  - operator: template
    value: |
      [[[
        if ((states[variables.active_speaker].state) == "playing") return "True";
      ]]]
    styles:
      name:
        - animation-delay: 30s
        - animation: record_rotation 4s infinite linear
      icon:
        - animation-delay: 30s
        - animation: record_rotation 4s infinite linear
      label:
        - animation-delay: 30s
        - animation-iteration-count: 1
        - animation: handle_rotation 2s normal forwards
      custom_fields:
        bg:
          - filter: blur(30px) brightness(0.75)
          - background-image: |
              [[[
                return `url("${states[variables.active_speaker].attributes.entity_picture}")`
              ]]]

@Mmohab, without your yaml it’s hard to say what to change. One thing to consider is using position absolute to get it out of the layout flow and a z-index to push it under or over, depending on the overlapping effect you want.

@eximo84, it can be tricky on page load to know when to start the animation. I have had partial success using logic to examine how long ago the state changed as part of deciding whether to show the animation. I say partial success because the last changed time is based on the Home Assistant clock and the logic is running in the browser and comparing to the browser’s clock, so there can be a time delta if the clocks are not exactly in sync. That may not be an issue for your case, but keep it in mind.

Thanks for the response, may be a simple example of a two entities on the top of each other on the whole card would be enough for me to start with. I can then play with the opacity based on the state

Any chance you could share your actual dashboard code? Thanks!

@efaden, I would if it was a single file, but I’ve done my dashboards in yaml mode and they are split into many subdirectories and separate files for each part. It’s also changed a lot since the original post and isn’t directly comparable. Easier if you ask about specific parts you need help with.

@Mmohab, you’re on the right track with custom fields. You just need to manage the CSS properties to get the layout you need. The key is using position: absolute and left, right, top or bottom properties to position where you want relative to the edges. With the overlay using absolute positioning the main button entity should show normally instead of getting moved by the overlay. It’s like putting them in different layers where they don’t affect each other.

1 Like

I’m trying to make a single button that is the size of your standard button that has the icon above the name above three “sub buttons” in a horizontal row. Specifically for my garage door, I want to have the door above open/close/crack buttons.

I tried to modify your container… just can’t seem to get it to work… (i’ll work on the trigger actions later)… just trying to get the layout correct.

Updated: … new code below.

Got a lot further… but am really stuck trying to get the sub buttons to be smaller and ideally make the entire garage door button match the size of the other standard buttons. Thoughts?

Untitled

              - type: custom:button-card
                aspect_ratio: 1/1
                entity: cover.double_garage_door
                template: standard
                color_type: icon
                tap_action:
                  action: more-info
                state:
                  - operator: template
                    value: >
                      [[[ return states['sensor.double_garage_door_position'].state == 'Open' ]]]
                    icon: mdi:garage-open-variant
                    color: green
                    label: Opened
                  - operator: template
                    value: >
                      [[[ return states['sensor.double_garage_door_position'].state == 'Cracked' ]]]
                    icon: mdi:garage-alert-variant
                    label: Opened
                    color: yellow
                  - operator: default
                    icon: mdi:garage-variant
                    label: Closed
                    color: red
                styles:
                  card:
                    - padding: 0
                  name:
                    - border-radius: 0.4em 0.4em 0 0
                    - padding: 0.1em
                    - width: 100%
                    - font-weight: bold
                  grid:
                    - grid-template-areas: '"i" "n" "buttons"'
                    - grid-template-columns: 1fr
                    - grid-template-rows: 1fr min-content min-content
                  custom_fields:
                    buttons:
                      - background-color: "rgba(0,0,0,0.3)"
                      - margin: 0
                      - padding: 0.3em
                custom_fields:
                  buttons:
                    card:
                      type: horizontal-stack
                      cards:
                        - entity: cover.double_garage_door
                          name: Open
                          template: standard
                          icon: "mdi:garage-open-variant"
                          type: "custom:button-card"
                        - entity: cover.double_garage_door
                          name: Crack
                          template: standard
                          icon: "mdi:garage-alert-variant"
                          type: "custom:button-card"
                        - entity: cover.double_garage_door
                          name: Close
                          template: standard
                          icon: "mdi:garage-variant"
                          type: "custom:button-card"

@efaden, I see what you are trying to do now. Your approach manipulating the grid looks good.

Some things you can try depending on what you want:

  • add aspect_ratio: 1/2 to each of the 3 nested button cards to make them half as tall (if you’re ok with the icon being smaller)
  • shrink your first grid row, either by changing 1fr to something else or maybe by styling the icon to a different size or playing with the padding around the icon

I’ll give that a try in a bit. Thanks. Ideally I’d love all the buttons to be the same size so there is a uniform look. Eg the garage and the lights are all the same big square… For now.

That sounds great, a sample code would be really helpful

Tried a bunch of things… even tried putting it inside of a layout card to control it a bit more. Is there a way to get the button to “fill” the space of its container? I just can’t seem to get the sizes to be the same. Really open to any suggestions…

For anyone curious… was finally able to get it to work. Basically used layout card to make a grid layout. The key was setting “height: 100%” in my button-card template to force the buttons to use the space provided by the grid.

I’m trying out templates for the first time and I’m attempting to turn as much of the following into a template as possible as I have five gates and I’m constantly tweaking so a template would make life much easier.

I’ve got most of it working but I’m stuck on the two custom_fields sections as I don’t know how to return a variable in those sections. I’ve defined the card at the bottom just in case I’ve not done that correctly either. Can anyone assist please?

color: green
color_type: icon
custom_fields:
  notification: |
    [[[ return states['sensor.steel_gate_battery'].state ]]]
entity: binary_sensor.steel_gate
icon: mdi:gate
name: Steel
size: 50%
state:
  - color: red
    icon: mdi:gate
    styles:
      icon:
        - animation: blink 5s ease infinite
    value: 'on'
  - color: green
    icon: mdi:gate
    value: 'off'
  - color: orange
    icon: mdi:gate-alert
    styles:
      icon:
        - animation: blink 3s ease infinite
    value: unavailable
styles:
  card:
    - border-radius: 10%
    - background-color: '--paper-card-background-color'
  custom_fields:
    notification:
      - background-color: |
          [[[
            if (states['sensor.steel_gate_battery'].state >= 98)
              return "green";
            return "red";
          ]]]
      - border-radius: 50%
      - position: absolute
      - left: 75%
      - top: 5%
      - height: 25px
      - width: 25px
      - font-size: 12px
      - line-height: 23px
      - color: var(--text-color)
  grid:
    - position: relative
type: custom:button-card

image

    cards:
      - template: gates
        entity: binary_sensor.steel_gate
        variables:
          e_n_value: states.sensor.steel_gate_battery.state
        type: custom:button-card

Cracked it!

button_card_templates:
  gates:
    color: green
    color_type: icon
    custom_fields:
      notification: |
        [[[ return (states[variables.e_n_value].state) ]]]
    size: 50%
    variables:
      notification_entity: n_e_value
    state:
      - color: red
        icon: mdi:gate
        styles:
          icon:
            - animation: blink 5s ease infinite
        value: 'on'
      - color: green
        icon: mdi:gate
        value: 'off'
      - color: orange
        icon: mdi:gate-alert
        styles:
          icon:
            - animation: blink 3s ease infinite
        value: unavailable
    styles:
      card:
        - border-radius: 10%
        - background-color: '--paper-card-background-color'
      custom_fields:
        notification:
          - background-color: |
              [[[
                if ((states[variables.e_n_value].state) >= 95)
                  return "green";
                return "red";
              ]]]
          - border-radius: 50%
          - position: absolute
          - left: 75%
          - top: 5%
          - height: 25px
          - width: 25px
          - font-size: 12px
          - line-height: 23px
          - color: var(--text-color)
      grid:
        - position: relative
    cards:
      - template: gates
        entity: binary_sensor.steel_gate
        variables:
          e_n_value: sensor.steel_gate_battery
        type: custom:button-card