Mushroom Cards - Build a beautiful dashboard easily 🍄 (Part 1)

Sorry but i am really never going to get the time to help you with this. I suggest you try and sort out as much as you can yourself. And whenever you get stuck post it here. (If its related to a mushroom card) i can then try to help in those individual cases.

Is there a way to achieve the same with a mushroom chips card? Wanting the symbol in top corner showing the zone

How do I combine different effects ? I have the following (non working)

type: custom:mushroom-person-card
entity: person.tim
icon_type: entity-picture
card_mod:
  style:
    mushroom-shape-avatar$: |
      .container:before {
        content: "";
        height: 100%;
        width: 100%;
        background: radial-gradient(rgb(var(--rgb-white)) 60%, transparent calc(60% + 1px)), conic-gradient(rgb(var(--rgb-green)) {{ states('sensor.sm_s911b_battery_level') }}% 0%, transparent 0% 100%);
        border-radius: var(--icon-border-radius);
        position: absolute;
        -webkit-mask-image: radial-gradient(circle calc(var(--icon-size) / 2 - 2px) at 50% 50%, transparent 100%, black 0);
      }

        mushroom-shape-avatar {    
         {{ 'filter: grayscale(100%);' if is_state('person.tim', 'not_home') }}
           }
        ha-card {
         background: none;
         --ha-card-box-shadow: 0px;
            }

The first stanza puts a nice arc around the profile photo to denote battery charge. But I also want the ‘greyscale when away’ and the none background of the 2nd stanza. Obviously mushroom-shape-avatar is declared twice so it wont work (I’ve never understood the trailing $ and | symbols either :-/ )

Thanks.

is it true that after the lst ha update the animated cards not longer works? what its changed again?

No, but you need to update card mod as well + then clear chache on app/browser.

Here is an explanation of how these symbols work.

$ is used when we want to access the shadow-root of an object. like this here:
image
the .shape is within the shadow-root of mushroom-shape-icon so to access it and modify it, we would write this:
image

card_mod:
  style: 
    mushroom-shape-icon$: |
      .shape {
        background: red !important;
      }

you cant just write this, as this wont access the element through the shadow root.
image

card_mod:
  style: |
    .shape {
      background: red !important;
    }

the | is just written to denote that you are done with going through elements and that you will now list your final element. so if i have stacked with multiple shadow-roots. it would look like this:
image

card_mod:
  style:
    mushroom-light-brightness-control$:
      mushroom-slider$:
        .container:
          .slider: |
            .slider-track-active {
              background-color: red !important;
            }

Notice how the last 2 in the stack dont have a $? thats because those elements dont have a shadow-root.
image

Ok. now that you hopefully understand how those symbols work we can look at your specific example.

card mod has a built in fuction to let you reset yourself back to style: | which is what you need for both ha-card { and mushroom-shape-avatar {

it is using .: if you use it at the right indentation (same line as anything you first place under style:

so like this:

card_mod:
  style:
    mushroom-shape-avatar$: |
      .container:before {
        content: "";
        height: 100%;
        width: 100%;
        background: radial-gradient(rgb(var(--rgb-white)) 60%, transparent calc(60% + 1px)), conic-gradient(rgb(var(--rgb-green)) {{ states('sensor.sm_s991b_battery_level') }}% 0%, transparent 0% 100%);
        border-radius: var(--icon-border-radius);
        position: absolute;
        -webkit-mask-image: radial-gradient(circle calc(var(--icon-size) / 2 - 2px) at 50% 50%, transparent 100%, black 0);
      }
    .: |
      mushroom-shape-avatar {    
        {{ 'filter: grayscale(100%);' if is_state(config.entity, 'not_home') }}
      }
      ha-card {
        background: none;
        --ha-card-box-shadow: 0px;
      }

note where the .: starts is the exact same place as where you initial mushroom-shape-avatar$: | starts. basically treat writing .: | as writting a whole new style: | again.

you can also use it like this (this gets more complex, so feel free to ignore if you dont fully understand it :slight_smile: ):

card_mod:
  style:
    mushroom-state-info$:
      .container: |
        .primary {
          --primary-text-color: #001eff;
        }
        .secondary {
          --secondary-text-color: #00ddff;
        }
      .: |
        .container {
          display: flex;
          flex-direction: row !important;
          align-items: baseline;
          gap: 10px;
        }

here my .: doesnt start at the same indentation as the first entry under style. it starts at the same entry as under when i declared .container: | reason being is if i wanted to access stuff under .container (like .primary and .secondary) then i cant also access .container (there are other ways to do it, but for illustration purposes this is true), so i put the .: | underneath the mushroom-state-info$: | as i still want to be in the shadow-root of the element as otherwise i cant access .container at all. then i just style the container the way i want.
image

6 Likes

Thank you so Much its work

Thanks for the detailed explanation Dimitri. I appreciate it. I don’t completely understand it (the card works though) but I have a slightly better understanding of $ and | (something I found pretty much impossible to google without hitting a CSS text book at page 1)

Thats quite alright, we all tend to learn piece by piece :slight_smile:

something you might be interested to look a bit more into as well is the ::before that you are using in your css. it is what is called a pseudo element. basically you are creating another element that inherits its placement from what you used before the ::before. there is also ::after and many others, but before and after as the most common. and as you might expect, they may render before or after the element that you base it off :slight_smile:

Achieve what exactly? Can you send a screenshot of exactly what you want?

That works for me too Dimitri, thanks a lot for your help !!

1 Like

Here is a working example of restriciton card

This is when the door is locked

and when it is unlocked

type: custom:layout-card
square: false
columns: 1
cards:
  - type: custom:restriction-card
    restrictions:
      pin:
        code: 1234
    exemptions:
      - user: ianid
    card:
      type: custom:mushroom-template-card
      secondary: null
      primary: >
        {% if is_state('binary_sensor.ewelink_contactsensor',
        'on') %}
          Door is Open
        {% elif is_state('binary_sensor.ewelink_contactsensor',
        'off') %}
           Door is Locked
        {% else %}   

        {% endif %} 
      entity: entity.entity
      icon: null
      tap_action:
        action: call-service
        service: script.turn_on
        target:
          entity_id: script.house_door
      fill_container: false
      multiline_secondary: false
      layout: vertical
      picture: /local/png/dot2.png
      card_mod:
        style:
          mushroom-state-info$: |
            .primary {
              font-size: 16px !important;
              position: relative;
              overflow: visible !important;
              margin-top: 30px;  
              margin-left: -12px;       
              --primary-text-color: rgb(var(--rgb-white));  
              font-weight: bold;
              text-overflow: ellipsis;  
              text-align: left;   
              width: 130px;       
              background: rgb(0,100,182);              
              text-indent: 5px;      
              border-radius: 5px;
            }
            .secondary {
              font-size: 14px !important;
              position: static;
              text-align: center;   
              margin-left: -18px; 
              border-radius: 5px;
              margin-right: 2px;  
              background: rgb(0,100,182);     
              text-indent: 10px;   
              flex-wrap: wrap !important;
              --secondary-text-color: var(--amber-color); 
            } 
          mushroom-shape-avatar$: |
            .picture {            
              border-radius: 0px !important;    
              margin-top: 0px;       
              margin-left: 0px;           
              margin-bottom: auto;  
            }
          mushroom-shape-icon$: |
            .shape {
              position: relative;
              border-radius: 0px !important;
            }
          .: >
            ha-card {

            {% if
            is_state('binary_sensor.ewelink_contactsensor',
            'on') %}
              background:  url( '/local/png/live/door-open.png' ) no-repeat center 0px;
              background-position: center;
              background-repeat: no-repeat;
              background-size: cover;
              background-blend-mode: hard-light;
              flex-wrap: wrap !important;
              position: relative;
            {% elif
            is_state('binary_sensor.ewelink_contactsensor',
            'off') %}
                background:  url( '/local/png/live/door-closed4.png' ) no-repeat center 0px;
                background-position: center;
                background-repeat: no-repeat;
                background-size: cover;
                background-color: rgba(150,58,27, 0.9);
                position: relative;
               {% else %}  
                background:  url( '/local/png/11.png' ) no-repeat center 0px;
                background-position: center;
                background-repeat: no-repeat;
                background-size: cover;
                background-color: #1a1a2a;, 1.25);
                position: relative;
                } 
              {% endif %} 
              --secondary-text-color: grey;
              box-shadow: none !important;
              background-color: rgba(250,130,43, 0.9); 
              height: 170px !important;      
            }  

            :host {
              --mush-icon-size: 70px;
            }       
layout_type: custom:vertical-layout
  

hi,
how can we this make work?

type: custom:mushroom-template-card
primary: ''
icon: mdi:kettle-steam
icon_color: |-
  {% if is_state('switch.keuken_boiler', 'on') %}
   red
  {% endif %}
entity: switch.keuken_boiler
fill_container: true
layout: vertical
card_mod:
  style:
    mushroom-shape-icon$: |
      ha-state-icon {
        {{'animation: boil 500ms infinite;' if is_state(config.entity, 'on') }}
      }
      @keyframes boil {
        0%, 100% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        10% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); clip-path: polygon(0 0, 66% 10%, 67% 30%, 88% 52%, 100% 100%, 0 100%); }
        20% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        30% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        40% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        50% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        60% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        70% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        80% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
        90% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      }

the boil is not shaking

Thanks a lot @berkans ! Works like a charm. Nice cards btw !

1 Like

Cant have ha-state-icon under mushroom-shape-icon$: | anymore.

Just do it like this instead:

card_mod:
  style: |
    ha-state-icon {
      {{'animation: boil 500ms infinite;' if is_state(config.entity, 'on') }}
    }
    @keyframes boil {
      0%, 100% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      10% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); clip-path: polygon(0 0, 66% 10%, 67% 30%, 88% 52%, 100% 100%, 0 100%); }
      20% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      30% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      40% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      50% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      60% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      70% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      80% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
      90% { transform: translate({{ range(-20, 20) | random / 10 }}px, {{ range(-20, 20) | random / 10 }}px) rotate({{ range(-15, 15) | random }}deg); }
    }

its work thank you

:wink:

Have you tried to read the “new” guide from Dimitri? He reworked the guides from @rhysb to take care of recent updates in Mushromm and HA core.

See here, maybe this helps a little further with your problem.

PS: between us, the idea posting in the other thread and then delete it, my full respect! Really, great idea and thanks for understanding. And you forced me to write an answer here! Really, my full respect! :+1: :+1: :rofl: :rofl:

1 Like

Hi Patrick,

Thanks for replying - Here’s the card mod change I’ve made, seems to work great now.

card_mod:
  style: |
    ha-card {

      /* Set padding of card */
      padding: 8px 8px 12px;

      /* Move card up to match header card */
      margin-top: -8px;

      /* Styling of card background */
      background: color-mix(in srgb, var(--card-background-color) 40%, var(--primary-background-color)) !important;
      border-radius: var(--ha-card-border-radius, 12px) var(--ha-card-border-radius, 12px) 0px 0px ;

      transition: all 0s;

       /* Make card sticky at top of page */
      :host {
      position: sticky;
      z-index: 9;
      top: 0px;
      }
      
    }

Just me being picky but i would do this to fix your syntax:

card_mod:
  style: |
    ha-card {
      /* Set padding of card */
      padding: 8px 8px 12px;

      /* Move card up to match header card */
      margin-top: -8px;

      /* Styling of card background */
      background: color-mix(in srgb, var(--card-background-color) 40%, var(--primary-background-color)) !important;
      border-radius: var(--ha-card-border-radius, 12px) var(--ha-card-border-radius, 12px) 0px 0px ;

      transition: all 0s;
    }
    /* Make card sticky at top of page */
    :host {
      position: sticky;
      z-index: 9;
      top: 0px;
    }
2 Likes

Just to be sure I am understanding mushroom correctly, I can only assume that anything in actions/tap actions cannot be templated variables. Simplified example:

decluttering_templates:
  mode_chip:
    card:
      type: custom:decluttering-card
      template: mode_chip_settings
      variables:
        - ip: '{{state_attr(''sensor.limitless_led_aliases'',''wifi_static_ip'')}}'
        - device_id: >-
            {{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('[[entity]]','friendly_name')][1]}}
        - remote_type: >-
            {{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('[[entity]]','friendly_name')][0]}}
        - group_id: >-
            {{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('[[entity]]','friendly_name')][2]}}
        - button: '[[button]]'
  mode_chip_settings:
    card:
      type: custom:mushroom-chips-card
      chips:
        - type: template
          entity: '[[entity]]'
          icon: mdi:numeric-[[button]]
          content_info: none
          tap_action:
            action: call-service
            service: script.limitlessled_set_mode
            service_data:
              ip: '[[ip]]'
              device_id: '[[device_id]]'
              remote_type: '[[remote_type]]'
              group_id: '[[group_id]]'
              mode: '[[button]]'
  mode_chip_test:
    card:
      type: markdown
      content: '[[ip]],  [[device_id]],  [[remote_type]],  [[group_id]],  [[button]]'
views:
  - title: Home
    cards:
      - type: custom:decluttering-card
        template: mode_chip
        variables:
          - entity: light.pergola_leds
          - button: 1
title: Regular Playground

From the above, I set several variables using templates in the decluttering template “mode_chip”.
Now if I use those variables to fill into a mushroom card inside a second decluttering template “mode_chip_settings” it does not work at all except for the icon populated from button.

Image of card:

image

Clicking results in this error:

Client error. Url: http://{{state_attr('sensor.limitless_led_aliases','wifi_static_ip')}}/gateways/{{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('light.pergola_leds','friendly_name')][1]}}/{{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('light.pergola_leds','friendly_name')][0]}}/{{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('light.pergola_leds','friendly_name')][2]}}?blockOnQueue=true. Error: Cannot connect to host {{state_attr('sensor.limitless_led_aliases','wifi_static_ip')}}:80 ssl:default [Name or service not known]

Which is totally obvious that the strings that are templates are passed in and not the result of the templates. It is passiing in the string that represents the template but it does not get executed because mushroom does not allow templates for those fields.

However if I pass those exact same variables into markdown to be sure I got them correct, they work just fine. All I do is change the second template in the above example to “mode_chip_test”:

image

This shows that when used in markdown, the templated values are rendered, but used in a mushroom card inside tap_action, the templates are not executed.

Although maybe they would be if I used [[ … ]] and not {{ …}} as I would note that the error shows that [[entity]] was replaced. I just do not see how to execute it all.

I know I can pass in a simple string, because the colored dots in the image below use this:

      type: custom:mushroom-chips-card
      chips:
        - type: entity
          entity: '[[entity]]'
          icon: none
          content_info: none
          tap_action:
            action: call-service
            service: light.turn_on
            data:
              transition: 0
              brightness: 255
              color_name: '[[colorname]]'
            target:
              entity_id: '[[entity]]'

So the “coloname” and “entity” passed in as simple strings work.

Is this correct?
Workaround ideas?

I have seen card-templater mentioned, but that does not work as far as I can see:

  mode_chip:
    card:
      type: custom:card-templater
      card:
        type: custom:decluttering-card
        template: mode_chip_test
        variables:
          - ip_template: '{{state_attr(''sensor.limitless_led_aliases'',''wifi_static_ip'')}}'
          - device_id_template: >-
              {{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('[[entity]]','friendly_name')][1]}}
          - remote_type_template: >-
              {{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('[[entity]]','friendly_name')][0]}}
          - group_id_template: >-
              {{state_attr('sensor.limitless_led_aliases','group_id_aliases')[state_attr('[[entity]]','friendly_name')][2]}}
          - button: '[[button]]'

Results in this:

image

And I have no idea where the “-” comes from.

Note: I already use button-card templates for this and it is all fine, was just hoping for a mushroom-ized solution to make it easier to apply my card_mod animations.

Ultimately I was trying to make this all work 100% mushroom with nice animations. What is not done are the ten buttons in each row that set modes for the lights and control the speed of those lights: