Hello there! Today I'll be going over the ever useful 'custom:button-card', creating headers and a few other styling bits and bobs I've used in Home Assistant to create the look and feel of most of my dashboards.

A little heads up before we begin ... Most if not all of these bits will require 'custom:card-mod' to be installed.

Header Cards (with images)

The first thing on the list is how to create and setup 'header/title' cards to place above certain elements in Home Assistant. In order to get this working you'll first need to ensure that you have the 'custom:card-mod' component installed to utilise the CSS wizardry which makes this all possible. The card itself is essentially a 'Markdown' card and looks a little something like this ...

content: >
  # <img width="30" height="30" src='/local/halogo.png'
  style='vertical-align:middle' /> Home Assistant 
style:
  .: |
    ha-card {
      background-color: transparent !important;
      box-shadow: none !important;
    }
  ha-markdown:
    $: |
      h1 {
        font-size: 25px;
       # font-weight: bold;
        text-align: center;
        letter-spacing: '-0.01em';
      }
type: markdown

The first thing to amend for your setup is top part under content.

content: >
  # <img width="30" height="30" src='/local/halogo.png'
  style='vertical-align:middle' /> Home Assistant 

In here the first part states the size and location of the image you want to display in your title. At the end is the title you want to display, 'Home Assistant' in this case. Depending on the theme you're using I'd recommend playing around the with width and height values to see what looks best in your setup.

style:
  .: |
    ha-card {
      background-color: transparent !important;
      box-shadow: none !important;
    }

The next part under style dictates the colour and shadowing of the card. In the instance the background colour of the card is set to transparent and no box shadow effect has been applied. Again, have a dabble with this and see what suits your setup.

  ha-markdown:
    $: |
      h1 {
        font-size: 25px;
       # font-weight: bold;
        text-align: center;
        letter-spacing: '-0.01em';
      }

Finally this section under ha-markdown allows you to set the font size, alignment and all that other good stuff for the title itself. Once that's all been amended and added you should end up with something looking like this ...

'custom:button-card' Animations

The 'custom:button-card' is a fantastic front-end component which I've used quite heavily in my Home Assistant setup in order to create and display certain elements and not just for a simply button. As well as being able to do a plethora of things and ways to display shit, you can also add animations to the card. The first one I ultised was the one documented on their GitHub which was a simple 'blink/flashing' animation to indicate when a state had changed. Digging a bit deeper I managed to add a fair few more ...

So ... In order to add the animation there are a few things you need to include in the 'custom:button-card' config. Here is an example of one of the cards ...

entity: binary_sensor.back_door
extra_styles: |
  @keyframes bounce {
    0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
    40% { transform: translateY(-25px); }
    60% { transform: translateY(-15px); }
  }
name: Back
state:
  - icon: 'mdi:door-closed'
    styles:
      icon:
        - opacity: 0.5
    value: 'off'
  - color: white
    icon: 'mdi:door-open'
    operator: default
    styles:
      card:
        - animation: bounce 1s infinite
type: 'custom:button-card'

The two main parts to get this card all animated and shit are the extra_styles and - animation: values. The example above shows a standard setup for the card, basically triggering the 'bounce' animation if the state changes from offto on (operator: default). The extra_styles values is how it 'moves/animates' the card and the - animation value determines how long and often. Here are the details for each animation:

'Bounce'

...
...
extra_styles: |
  @keyframes bounce {
    0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
    40% { transform: translateY(-25px); }
    60% { transform: translateY(-15px); }
  }
...
...
        - animation: bounce 1s infinite
...
...
..

'Wiggle'

...
...
        extra_styles: |
          @-webkit-keyframes swing
          {
              15%
              {
                  -webkit-transform: translateX(5px);
                  transform: translateX(5px);
              }
              30%
              {
                  -webkit-transform: translateX(-5px);
                 transform: translateX(-5px);
              } 
              50%
              {
                  -webkit-transform: translateX(3px);
                  transform: translateX(3px);
              }
              65%
              {
                  -webkit-transform: translateX(-3px);
                  transform: translateX(-3px);
              }
              80%
              {
                  -webkit-transform: translateX(2px);
                  transform: translateX(2px);
              }
              100%
              {
                  -webkit-transform: translateX(0);
                  transform: translateX(0);
              }
          }
...
...
        - animation: swing 1s ease infinite
...
...
..

'Squeeze'

...
...
        extra_styles: |
          @-webkit-keyframes WidthAni {
            0% {width: 0px}
            10% {width: 100%;left: 0;right: 0}
            20% {width: 5%;left: 95%;}
            25% {width: 5%;left: 95%;}
            35% {width: 100%;left: 0%;}
            45% {width: 0%;}
            100% {width: 0%;}
          }
...
...
        - animation: WidthAni 5.0s infinite ease-in-out
...
...
..

'Glow'

...
...
        extra_styles: |
          @keyframes mymove {
            50% {box-shadow: 0 0 20px red;}
            }
...
...
        - animation: mymove 2s infinite
...
...
..

'Pulse'

...
...
        extra_styles: |
          @keyframes pulse {
            0% {
              -moz-box-shadow: 0 0 0 0 rgba(255,0,0, 0.7);
              box-shadow: 0 0 0 0 rgba(255,0,0, 0.7);
            }
            70% {
                -moz-box-shadow: 0 0 0 10px rrgba(240,52,52, 0.9);
                box-shadow: 0 0 0 10px rgba(240,52,52, 0.7);
            }
            100% {
                -moz-box-shadow: 0 0 0 0 rgba(240,52,52, 0);
                box-shadow: 0 0 0 0 rgba(240,52,52, 0);
            }
...
...
        - animation: pulse 1s infinite
...
...
..

'Grower'

...
...
        extra_styles: |
          @keyframes ball-scale {
            from {
              transform: scale(1);
              box-shadow: 0 8px 6px -6px #6C7A89;
            }
            to {
              transform: scale(1.25);
              box-shadow: 0 10px 6px -6px #6C7A89;
            }
          }
...
...
        - animation: ball-scale 2s ease-in-out infinite
...
...
..

'custom:button-card' Gap Card

As mentioned above, I tend to use the 'custom:button-card' quite a bit on my dashboards and in this case I found it handy for creating a 'gap' between my vertical stacks. Another feature of this card is the ability to setup a 'blank card' which as it sounds, allows you to create a card with nothing in it. In order to create this gap I've simply added a blank card at the start and end of each horizontal stack within the vertical stack, make sense? In the example below, I've set the width to 25px and ensured to follow the same config throughout which then provides me with a nice and even gap between the vertical stacks.

color_type: blank-card
name: false
styles:
  card:
    - width: 25px
type: 'custom:button-card'
..

Here is a short example of a horizontal stack within a vertical stack, adding a gap of each side of a glance card.

cards:
  - type: horizontal-stack
    cards:
      - color_type: blank-card
        name: false
        styles:
          card:
            - width: 25px
        type: 'custom:button-card'
      - type: glance
        entities:
          - entity: binary_sensor.garage_door
      - color_type: blank-card
        name: false
        styles:
          card:
            - width: 25px
        type: 'custom:button-card'
type: vertical-stack
..

In the screenshot above, I've even gone the opposite direction and changed the width to height in order to create a gap vertically between certain elements (elements under 'Push Notifications' are separated in places)

color_type: blank-card
name: false
styles:
  card:
    - height: 5px
type: 'custom:button-card'
..

'card-mod' Title Wrapping

This one isn't major but I thought it's worth mentioning. You ever find that a title on a card sometimes is too long and ends up cutting out ('Ground Floor Hal..')? Well, with the 'custom:card-mod' you are able to effectively 'wrap' the text and create a 'second line' Simple add <br/> between the text of the title and now it'll separate the text between two lines. Check out the before and after images below ...

Themes

I'm not going to go too much into Themes in Home Assistant as there are plenty of guides and shit out there already. For my setup I've used and modified an existing theme called 'Noctis'. You can find the config for my theme here. What I would say is that it's worth playing around with certain elements such as fonts and background images in order to get something that suits your needs. One of the questions I get the most is 'where did you get your background from?'. Well my friend, I used this site here to generate mine. If you want to go balls deep and use an animated background, check out this GitHub to get yours setup.

'customize.yaml' Assigning Images/Icons to Entities

Again, not a major thing to mention but handy if you don't know already. Within 'customize.yaml' you are able to assign images to entities. Cool right? An easy one to setup in general, ensure you have an image that ideally has a transparent background (usually a .png file) and placed in your '/www' folder then simply add the following in your 'customize.yaml' file ...

 sensor.hass_docker_addon_fd74094e_zabbix_agent_status_up:
  entity_picture: /local/zabbix.png
  friendly_name: Docker Zabbix Status
  
 sensor.hass_docker_addon_core_mosquitto_status_up:
  entity_picture: /local/mqtt.png
  friendly_name: Docker Mosquitto Status
  
 sensor.hass_docker_addon_a0d7b954_influxdb_status_up:
  entity_picture: /local/influxdb.png
  friendly_name: Docker InfluxDB Status 

Restart Home Assistant and like magic your entity will now display the desired image! Fucking A!

Amend (not change) an Entity Value

Do you have an entity value that you wish to amend rather than change? Sure in most cases you'd want to change a value from 'on' to 'Open' or 'Online for example, but sometimes certain entities include an annoying bit of text such as 'Up 4 hours' when all you need/want is '4 hours'. The example of 'Up 4 hours' was exactly the issue I had with several of my Docker sensors which provided me with an uptime value on each container. When I got these added into glance cards however, I'd find the values were too long for the card itself and ended up with 'Up 4 ho...". To sort this out I needed to create a template sensor just like so...

platform: template
sensors:
  hass_docker_homeassistant_status_up:
    friendly_name: "Home Assistant Status"
    value_template: "{{ states.sensor.hass_docker_homeassistant_status.state|replace('Up','') }}"

The key bit in this config is the ...state|replace('Up','') which basically replaces the word Up with sweet noting ''. Once added and done a good old restart of Home Assistant, the new sensor appears without the Up! Like magic eh?

So that's all I've got to mention right now. Hopefully you'll find something useful to add to your Home Assistant. If you've got any issues or I've made a mistake somewhere be sure to hit me up on Reddit and let me know. For now I bid you adieu!