How to create a CSS variable using card-mod

I saw this amazing plugin called card-mod which gives you the ability to style (almost) any element within the Home Assistant frontend. Since I am a frontend dev, I just love making everything as pretty and interactive as I can.

The problem with card-mod is that it’s quite limiting. If I really wanted to make my dashboard look like some insane Van Gogh, my ‘ui-lovelace.yaml’ file would be 50.000+ lines long. The problem here is that all styling has to be done inside this file.

Let me give an example to demonstrate this. I just wanted a simple animation for a icon in my custom banner-card. This looks like:

ezgif-6-60abc3f8aab1

Even though this isn’t some crazy animation it takes up a lot of space in my lovelace files. For this simple animation I need these lines of code:

- type: custom:banner-card
            background: "rgba(0, 0, 0,0.5)"
            heading: "\U0001F39C Sonos"
            row_size: 4
            style: |
              h2 {
                margin: 28px;
              }
              .overlay-strip {
                border-radius: 0 0 20px 20px;
              }
              @-webkit-keyframes ha-icon {
                16.65% {
                  -webkit-transform: translateX(8px);
                  transform: translateX(8px);
                }
                33.3% {
                  -webkit-transform: translateX(-6px);
                  transform: translateX(-6px);
                }
                49.95% {
                  -webkit-transform: translateX(4px);
                  transform: translateX(4px);
                }
                66.6% {
                  -webkit-transform: translateX(-2px);
                  transform: translateX(-2px);
                }
                83.25% {
                  -webkit-transform: translateX(1px);
                  transform: translateX(1px);
                }
                100% {
                  -webkit-transform: translateX(0);
                  transform: translateX(0);
                }
              }
              @keyframes ha-icon {
                16.65% {
                  -webkit-transform: translateX(8px);
                  transform: translateX(8px);
                }
                33.3% {
                  -webkit-transform: translateX(-6px);
                  transform: translateX(-6px);
                }
                49.95% {
                  -webkit-transform: translateX(4px);
                  transform: translateX(4px);
                }
                66.6% {
                  -webkit-transform: translateX(-2px);
                  transform: translateX(-2px);
                }
                83.25% {
                  -webkit-transform: translateX(1px);
                  transform: translateX(1px);
                }
                100% {
                  -webkit-transform: translateX(0);
                  transform: translateX(0);
                }
              }
              ha-icon {
                display: inline-block;
                vertical-align: middle;
                -webkit-transform: perspective(1px) translateZ(0);
                transform: perspective(1px) translateZ(0);
                box-shadow: 0 0 1px rgba(0, 0, 0, 0);
              }
              ha-icon:hover, ha-icon:focus, ha-icon:active {
                -webkit-animation-name: ha-icon;
                animation-name: ha-icon;
                -webkit-animation-duration: 1s;
                animation-duration: 1s;
                -webkit-animation-timing-function: ease-in-out;
                animation-timing-function: ease-in-out;
                -webkit-animation-iteration-count: 1;
                animation-iteration-count: 1;
              }

So, back to my question. Is there any way for me to split my lovelace file up in multiple pieces? I know it’s possible to do something like “style: !include mystyle.yaml” but this did not seem to work.

Any geniuses out here that can help me out?

edit:
After some more testing, just using “style: !include mystyle.yaml” does work. However, if I wanted to use this as a class for multiple elements, this is going to be a pain… Let’s say I wanted to change the margin on my H2 styling for a specific element, I would have to create another file for that. So this is a temporary fix but not what I was looking for.

For people that are interested in how I temporarily “fixed” it. I just changed style to:

style: !include "./css/wobble.yaml"

In the wobble.yaml file I simply copy pasted everything including the “|”.

Not really sureif this is helpful for you, but take a look at the decluttering card. You can create templates for cards with defaults and then reuse these templates.

1 Like

Thanks for reacting! After reading the docs, the decluttering card seemed like a reasonable solution.

Even though this works a lot better than my temporary solution, it still does not do what I want it to. My goal is to get custom styling using some sort of variables. For instance something like this:

style:
  - class: animation_wobble
  - class: onhover_change_color
  - customstyling: 
      ha-card {
        display: block;
      }

My example below is not what I am looking for, but does work. This uses the decluttering card.
This is where I implement the card:

# Groepen
- type: custom:decluttering-card
  template: banner-card_animation_wobble
  variables:
    - background: rgba(0, 0, 0,0.5)
    - heading: "\U0001F465 Boven"
    - row_size: 1
    - entities:
       - entity: switch.sonosboven_toggle
         name: Alles aan/uit

This is where I create the card variable:

# Decluttering-card.js
decluttering_templates:
  # Custom style animation variables
  banner-card_animation_wobble:
    card:
      type: custom:banner-card
      background: "[[background]]"
      heading: "[[heading]]"
      row_size: "[[row_size]]"
      entities: "[[entities]]"
      style: |
        h2 {
          margin: 28px;
        }
        .overlay-strip {
          border-radius: 0 0 20px 20px;
        }
        @-webkit-keyframes ha-icon {
          16.65% {
            -webkit-transform: translateX(8px);
            transform: translateX(8px);
          }
          33.3% {
            -webkit-transform: translateX(-6px);
            transform: translateX(-6px);
          }
          49.95% {
            -webkit-transform: translateX(4px);
            transform: translateX(4px);
          }
          66.6% {
            -webkit-transform: translateX(-2px);
            transform: translateX(-2px);
          }
          83.25% {
            -webkit-transform: translateX(1px);
            transform: translateX(1px);
          }
          100% {
            -webkit-transform: translateX(0);
            transform: translateX(0);
          }
        }
        @keyframes ha-icon {
          16.65% {
            -webkit-transform: translateX(8px);
            transform: translateX(8px);
          }
          33.3% {
            -webkit-transform: translateX(-6px);
            transform: translateX(-6px);
          }
          49.95% {
            -webkit-transform: translateX(4px);
            transform: translateX(4px);
          }
          66.6% {
            -webkit-transform: translateX(-2px);
            transform: translateX(-2px);
          }
          83.25% {
            -webkit-transform: translateX(1px);
            transform: translateX(1px);
          }
          100% {
            -webkit-transform: translateX(0);
            transform: translateX(0);
          }
        }
        ha-icon {
          display: inline-block;
          vertical-align: middle;
          -webkit-transform: perspective(1px) translateZ(0);
          transform: perspective(1px) translateZ(0);
          box-shadow: 0 0 1px rgba(0, 0, 0, 0);
        }
        ha-icon:hover, ha-icon:focus, ha-icon:active {
          -webkit-animation-name: ha-icon;
          animation-name: ha-icon;
          -webkit-animation-duration: 1s;
          animation-duration: 1s;
          -webkit-animation-timing-function: ease-in-out;
          animation-timing-function: ease-in-out;
          -webkit-animation-iteration-count: 1;
          animation-iteration-count: 1;
        }

Using this solution, you simply use the same card in different places and change all of it’s variables, which is nice, but not the perfect solution (in my opinion).

Again, thanks for reacting! It really did help me :slight_smile:!

1 Like

This might also help

From the same dev as card-mod.

Also you could look at another of his

I think, if you put stuff in card…options, it gets applied to all the sub-cards.

1 Like

You don’t even need the decluttering card. If you want to replicate that style over and over again, use anchors:

Make an anchor section at the top of your file and add your styles.

anchors:
  icon_jiggle: &icon_jiggle:
    style: |
      h2 {
        margin: 28px;
      }
      .overlay-strip {
        border-radius: 0 0 20px 20px;
      }
      @-webkit-keyframes ha-icon {
        16.65% {
          -webkit-transform: translateX(8px);
          transform: translateX(8px);
        }
        33.3% {
          -webkit-transform: translateX(-6px);
          transform: translateX(-6px);
        }
        49.95% {
          -webkit-transform: translateX(4px);
          transform: translateX(4px);
        }
        66.6% {
          -webkit-transform: translateX(-2px);
          transform: translateX(-2px);
        }
        83.25% {
          -webkit-transform: translateX(1px);
          transform: translateX(1px);
        }
        100% {
          -webkit-transform: translateX(0);
          transform: translateX(0);
        }
      }
      @keyframes ha-icon {
        16.65% {
          -webkit-transform: translateX(8px);
          transform: translateX(8px);
        }
        33.3% {
          -webkit-transform: translateX(-6px);
          transform: translateX(-6px);
        }
        49.95% {
          -webkit-transform: translateX(4px);
          transform: translateX(4px);
        }
        66.6% {
          -webkit-transform: translateX(-2px);
          transform: translateX(-2px);
        }
        83.25% {
          -webkit-transform: translateX(1px);
          transform: translateX(1px);
        }
        100% {
          -webkit-transform: translateX(0);
          transform: translateX(0);
        }
      }
      ha-icon {
        display: inline-block;
        vertical-align: middle;
        -webkit-transform: perspective(1px) translateZ(0);
        transform: perspective(1px) translateZ(0);
        box-shadow: 0 0 1px rgba(0, 0, 0, 0);
      }
      ha-icon:hover, ha-icon:focus, ha-icon:active {
        -webkit-animation-name: ha-icon;
        animation-name: ha-icon;
        -webkit-animation-duration: 1s;
        animation-duration: 1s;
        -webkit-animation-timing-function: ease-in-out;
        animation-timing-function: ease-in-out;
        -webkit-animation-iteration-count: 1;
        animation-iteration-count: 1;
      }

Then later on in your card…

- type: custom:banner-card
  background: "rgba(0, 0, 0,0.5)"
  heading: "\U0001F39C Sonos"
  row_size: 4
  <<: *icon_jiggle

Read up on anchors here:

https://blog.daemonl.com/2016/02/yaml.html

3 Likes

Thanks Petro! This is exactly what I was looking for.