Is anyone interested in some icon animations?
Hello, I’ve tried it but I’m breaking my head it doesn’t come out, how do you do it? how do you leave the separators on the left and right? Only a central column and assigning a tab?
Forgive me
Bit of a rhetorical question I think…
Asking this again — how are you all getting the menu icon/button to work? If I put my page in kiosk mode, it no longer opens the menu. Mushroom Cards - Build a beautiful dashboard easily 🍄 - #3130 by alpacalypse
Mushroom Animations - Part 1
I thought I’d share some CSS animations I’ve been working on for Mushroom cards.
All these CSS animations require Thomas Lovén’s card_mod
. This can be installed via HACS.
There are a few, so I’ll probably add them gradually. Make sure to return to this post so you don’t miss out.
Built-in Mushroom Animations
There are two built-in animations for Mushroom cards that can be used without specifying any @keyframes
. These are spin
, which is used for the rotating fan, and pulse
, which fades in and out.
Built-in Spin Animation:
Spin Animation
type: custom:mushroom-template-card
primary: Spin
icon: mdi:fan
icon_color: teal
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: spin 1s linear infinite;
}
Built-in Pulse Animation:
Pulse Animation
type: custom:mushroom-template-card
icon: mdi:pulse
icon_color: red
primary: Pulse
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: pulse 2s ease-in-out infinite;
}
Animated Mushroom Cards
Mushroom Media Player Card:
Media Player Animated Icons
type: custom:mushroom-media-player-card
entity: media_player.currently_playing
icon: mdi:play
use_media_info: true
use_media_artwork: false
show_volume_level: false
media_controls:
- play_pause_stop
- previous
- next
volume_controls:
- volume_buttons
- volume_set
fill_container: false
card_mod:
style: |
mushroom-shape-icon {
display: flex;
{% set media_type = state_attr(config.entity, 'media_content_type') %}
{% if media_type == 'tvshow' %}
--card-mod-icon: mdi:television-classic;
animation: flicker 1s linear infinite alternate;
{% elif media_type == 'movie' %}
--card-mod-icon: mdi:movie-roll;
animation: spin 2s linear infinite reverse;
{% elif media_type == 'music' %}
--card-mod-icon: mdi:music;
animation: beat 1.3s ease-out infinite both;
{% elif media_type == 'playlist' %}
--card-mod-icon: mdi:music;
animation: beat 1.3s ease-out infinite both;
{% else %}
--card-mod-icon: mdi:play;
{% endif %}
}
@keyframes flicker {
0%, 31.98%, 32.98%, 34.98%, 36.98%, 39.98%, 67.98%, 68.98%, 95.98%, 96.98%, 97.98%, 98.98%, 100% { --icon-color: rgba(var(--rgb-indigo), 1); }
32%, 33%, 35%, 36%, 37%, 40%, 68%, 69%, 96%, 97%, 98%, 99% { --icon-color: rgba(var(--rgb-indigo), 0.6); }
}
@keyframes beat {
0%, 60% { --icon-symbol-size: 21px; }
5%, 17%, 57% { --icon-symbol-size: 22px; }
10%, 20%, 51% { --icon-symbol-size: 23px; }
25%, 45% { --icon-symbol-size: 24px; }
30%, 39% { --icon-symbol-size: 25px; }
33% { --icon-symbol-size: 26px; }
}
ha-card {
{% if not is_state(config.entity, 'off') %}
background: rgba(var(--rgb-card-background-color), 0.6) url( '{{ state_attr(config.entity, "entity_picture") }}' ) center no-repeat;
background-size: cover;
background-blend-mode: overlay;
{% endif %}
}
Mushroom Climate Card:
Climate Animated Icons
type: custom:mushroom-climate-card
entity: climate.office_air_conditioner
hvac_modes:
- heat_cool
- heat
- cool
- fan_only
- dry
show_temperature_control: true
collapsible_controls: false
name: Air Conditioner
card_mod:
style: |
mushroom-shape-icon {
{% if is_state(config.entity, 'heat_cool') %}
--card-mod-icon: mdi:autorenew;
animation: spin 3s ease-in-out infinite alternate;
{% elif is_state(config.entity, 'heat') %}
--card-mod-icon: mdi:fire;
animation: heat 2s infinite;
{% elif is_state(config.entity, 'cool') %}
--card-mod-icon: mdi:snowflake;
animation: cool 6s ease-in-out infinite;
{% elif is_state(config.entity, 'dry') %}
--card-mod-icon: mdi:water-percent;
animation: dry 1.5s linear infinite;
{% elif is_state(config.entity, 'fan_only') %}
--card-mod-icon: mdi:fan;
animation: spin 1s linear infinite;
{% else %}
--card-mod-icon: mdi:air-conditioner;
{% endif %}
display: flex;
}
@keyframes cool {
0%, 100% { transform: rotate(25deg); }
25% { transform: rotate(-25deg); }
50% { transform: rotate(50deg); }
75% { transform: rotate(-50deg); }
}
@keyframes heat {
0%, 100% { --icon-color: rgba(var(--rgb-red), 1); }
10%, 90% { --icon-color: rgba(var(--rgb-red), 0.8); }
20%, 80% { --icon-color: rgba(var(--rgb-red), 0.6); }
30%, 70% { --icon-color: rgba(var(--rgb-red), 0.4); }
40%, 60% { --icon-color: rgba(var(--rgb-red), 0.2); }
50% { --icon-color: rgba(var(--rgb-red), 0); }
}
@keyframes dry {
0%, 100% { --icon-symbol-size: 21px; }
10%, 90% { --icon-symbol-size: 22px; }
20%, 80% { --icon-symbol-size: 23px; }
30%, 70% { --icon-symbol-size: 24px; }
40%, 60% { --icon-symbol-size: 25px; }
50% { --icon-symbol-size: 26px; }
}
Mushroom Card Icon Animations
Boil Animation
type: custom:mushroom-template-card
primary: Boil
icon: mdi:kettle-steam
icon_color: red
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: boil 500ms infinite;
}
@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); }
}
Fire Animation
type: custom:mushroom-template-card
primary: Fire
icon: mdi:fire
icon_color: red
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: fire 1.5s infinite;
transform-origin: 50% 85%;
}
@keyframes fire {
0% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
5% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
10% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
15% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
20% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
25% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
30% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
35% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
40% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
45% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
50% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
55% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
60% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
65% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
70% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
75% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
80% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
85% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
90% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
95% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-red)); opacity: {{range(7, 10) | random / 10}}; }
100% { transform: rotate({{range(-20, 20) | random / 10}}deg) scaleY({{range(9, 12) | random / 10}}); color: rgb(var(--rgb-deep-orange)); opacity: {{range(7, 10) | random / 10}}; }
}
Shower Animation
type: custom:mushroom-template-card
icon: mdi:shower-head
icon_color: light-blue
primary: Shower
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: clip 0.7s ease-out infinite;
}
@keyframes clip {
0% {clip-path: inset(0 0 45% 0); }
100% { clip-path: inset(0 0 0 0); }
}
Sprinkler Animation
type: custom:mushroom-template-card
icon: mdi:sprinkler
icon_color: cyan
primary: Sprinkler
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: sprinkle 2s linear infinite;
transform-origin: 29% 88%;
}
@keyframes sprinkle {
0%, 15%, 30%, 45%, 60%, 100% { clip-path: inset(0 55% 0 0); transform: rotate(0deg); }
1%, 16%, 31%, 46% { clip-path: inset(0 0 0 0); transform: rotate(-10deg); }
6%, 21%, 36%, 51% { transform: rotate(2deg); }
}
Washing Machine Animation
type: custom:mushroom-template-card
icon: mdi:washing-machine
icon_color: amber
primary: Washing Machine
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: shake 400ms ease-in-out infinite, drum 2s ease infinite;
transform-origin: 50% 110%;
}
@keyframes shake {
0%, 100% { transform: translate(0, 0) rotate(0); }
20% { transform: translate(0.4px, -0.4px) rotate(-4deg); }
40% { transform: translate(-0.4px, 0.4px) rotate(4deg); }
60% { transform: translate(0.4px, 0.4px) rotate(-4deg); }
80% { transform: translate(-0.4px, -0.4px) rotate(4deg); }
}
@keyframes drum {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 34% 68%, 60% 41%, 71% 56%, 65% 74%, 47% 79%, 32% 69%, 35% 100%, 100% 100%, 100% 0); }
}
Dishwasher Animation
type: custom:mushroom-template-card
icon: mdi:dishwasher
icon_color: blue
primary: Dishwasher
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: bounce 1.5s ease-in-out infinite, wash 1s ease-in-out infinite;
transform-origin: 50% 75%;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {transform: translateY(0); }
40% { transform: translateY(-1.2px) rotate(5deg); }
60% { transform: translateY(-1.1px) rotate(-4deg); }
}
@keyframes wash {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 36% 74%, 31% 43%, 61% 40%, 71% 69%, 62% 78%, 36% 73%, 35% 100%, 100% 100%, 100% 0); }
}
Dryer Animation
type: custom:mushroom-template-card
icon: mdi:tumble-dryer
icon_color: teal
primary: Dryer
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: shake 400ms ease-in-out infinite, drum 1s infinite;
transform-origin: 50% 65%;
}
@keyframes shake {
0%, 100% { transform: rotate(4deg); }
50% { transform: rotate(-4deg); }
}
@keyframes drum {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 36% 74%, 31% 43%, 61% 40%, 71% 69%, 62% 78%, 36% 73%, 35% 100%, 100% 100%, 100% 0); }
}
Ding Animation
type: custom:mushroom-template-card
primary: Ding
icon: mdi:bell-ring
icon_color: indigo
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: ring 4s linear infinite;
transform-origin: 50% 15%;
}
@keyframes ring {
0% { transform: rotate(0); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
2% { transform: rotate(30deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
6% { transform: rotate(-28deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
10% { transform: rotate(34deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
14% { transform: rotate(-32deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
18% { transform: rotate(30deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
22% { transform: rotate(-28deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
26% { transform: rotate(26deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
30% { transform: rotate(-24deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
34% { transform: rotate(22deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
38% { transform: rotate(-20deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
42% { transform: rotate(18deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
46% { transform: rotate(-16deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
50% { transform: rotate(14deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
54% { transform: rotate(-12deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
58% { transform: rotate(10deg); clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }
62% { transform: rotate(-8deg); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
66% { transform: rotate(6deg); }
70% { transform: rotate(-4deg); }
74% { transform: rotate(2deg); }
78% { transform: rotate(-1deg); }
82% { transform: rotate(1deg); }
86% { transform: rotate(0); }
100% { transform: rotate(0); clip-path: polygon(0 50%, 0 100%, 100% 100%, 100% 50%, 85% 50%, 80% 30%, 60% 5%, 40% 5%, 20% 30%, 15% 50%); }
}
Alarm Animation
type: custom:mushroom-template-card
icon: mdi:alarm
icon_color: red
primary: Alarm
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: alarm 0.8s ease infinite;
}
@keyframes alarm {
0%, 80%, 100% { transform: translateY(0); }
10% { transform: translateY(-2px) rotate(-27deg); }
20% { transform: translateY(-2px) rotate(21deg); }
30% { transform: translateY(-2px) rotate(-15deg); }
40% { transform: translateY(-2px) rotate(9deg); }
50% { transform: translateY(0); }
60% { transform: translateY(-1.2px) }
}
Rocket Man Animation
type: custom:mushroom-template-card
icon: mdi:rocket-launch
icon_color: deep-orange
primary: Rocket Man
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: thrust 100ms infinite, motion 3s ease-in-out infinite;
}
@keyframes thrust {
0% { clip-path: polygon(0 0, 0 47%, 22% 57%, 28% 63%, 0 91%, 11% 100%, 37% 73%, 45% 77%, 55% 100%, 100% 100%, 100% 0%); }
33% { clip-path: polygon(0 0, 0 47%, 24% 59%, 42% 76%, 54% 100%, 100% 100%, 100% 0); }
66% { clip-path: polygon(0 0, 0 92%, 28% 64%, 36% 72%, 9% 100%, 100% 100%, 100% 0%); }
}
@keyframes motion {
0%, 100% { transform: translateY(-2px) translateX(-3px); }
50% { transform: translateY(3px) translateX(2px); }
}
Fountain Animation
type: custom:mushroom-template-card
primary: Fountain
icon: mdi:fountain
icon_color: light-blue
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: fountain 1.5s ease infinite;
}
@keyframes fountain {
0%, 100 { clip-path: polygon(0 100%, 0 0, 100% 0, 100% 100%); }
50% { clip-path: polygon(0 100%, 0 47%, 100% 47%, 100% 100%); }
60% { clip-path: polygon(0 100%, 100% 100%, 100% 37%, 79% 36%, 71% 21%, 56% 25%, 44% 25%, 31% 20%, 20% 36%, 0 36%); }
70% { clip-path: polygon(0 100%, 100% 100%, 100% 36%, 79% 36%, 71% 22%, 81% 1%, 24% 0, 31% 21%, 20% 36%, 0 36%); }
80% { clip-path: polygon(0 100%, 100% 100%, 100% 36%, 79% 36%, 76% 28%, 100% 0, 0 0, 23% 28%, 20% 36%, 0 36%); }
}
Motion Animation
type: custom:mushroom-template-card
icon: mdi:motion-sensor
icon_color: blue
primary: Motion
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: clip 2s linear infinite;
}
@keyframes clip {
50% { clip-path: polygon(0 0, 55% 0, 100% 100%, 0 100%); }
}
.shape {
--shape-animation: motion 2s linear infinite;
}
@keyframes motion {
0%, 100% { --shape-color: rgba(var(--rgb-blue), 0.3); }
50% { --shape-color: rgba(var(--rgb-blue), 0.2); }
}
Cog Animation
type: custom:mushroom-template-card
primary: Cog
icon: mdi:cog
icon_color: grey
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: spin 1.5s steps(5) infinite;
}
Signal Animation
type: custom:mushroom-template-card
icon: mdi:wifi
icon_color: green
primary: Signal
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: clip 2s steps(1) infinite;
}
@keyframes clip {
0% { clip-path: circle(0% at 50% 85%); }
20% { clip-path: circle(30% at 50% 85%); }
40% { clip-path: circle(55% at 50% 85%); }
60% { clip-path: circle(80% at 50% 85%); }
}
.shape {
--shape-animation: ping 2s infinite;
}
@keyframes ping {
60% { box-shadow: 0 0 0 0 rgba(var(--rgb-green), 0.7); }
100% { box-shadow: 0 0 5px 15px transparent; }
}
Alert Animation
type: custom:mushroom-template-card
icon: mdi:alarm-light
icon_color: red
primary: Alert
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: alert 0.8s infinite;
}
@keyframes alert {
0%, 100% { color: rgb(var(--rgb-orange)); }
50% { clip-path: polygon(0% 55%, 25% 55%, 25% 35%, 35% 25%, 50% 18%, 65% 20%, 75% 35%, 75% 55%, 100% 55%, 100% 100%, 0 100%); color: rgb(var(--rgb-red)); }
}
.shape {
--shape-animation: alert-shape 0.8s infinite;
}
@keyframes alert-shape {
0%, 100% { --shape-color: rgba(var(--rgb-orange), 0.2); }
60% { --shape-color: rgba(var(--rgb-red), 0.2); }
}
Console Animation
type: custom:mushroom-template-card
icon: mdi:console-line
icon_color: grey
primary: Console
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: console 1s infinite;
}
@keyframes console {
50% { clip-path: polygon(0 0, 100% 0, 24% 100%, 0 100%); }
}
Keypad Animation
type: custom:mushroom-template-card
icon: mdi:dialpad
icon_color: blue
primary: Keypad
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: pin 4s infinite;
transform-origin: 50% 75%;
}
@keyframes pin {
0%, 15%, 25%, 35%, 45%, 55% { clip-path: inset(0 0 0 0); }
10% { clip-path: polygon(0% 100%, 1% 23%, 36% 23%, 36% 0%, 100% 0, 100% 100%); }
20% { clip-path: polygon(0% 100%, 0 0, 62% 0, 61% 25%, 100% 24%, 100% 100%); }
30% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 0 25%, 36% 25%, 37% 50%, 63% 49%, 62% 26%, 0 25%); }
40% { clip-path: polygon(0 51%, 0 0, 100% 0, 100% 100%, 36% 100%, 37% 51%); }
50% { clip-path: polygon(0 100%, 0 0, 100% 0, 100% 50%, 64% 50%, 64% 100%); }
}
.shape {
--shape-animation: ping 4s infinite;
}
@keyframes ping {
55% { box-shadow: 0 0 1px 0px rgba(var(--rgb-blue), 0.3) inset; }
100% { box-shadow: 0 0 5px 15px transparent inset; }
}
Eye Animation
type: custom:mushroom-template-card
icon: mdi:eye
icon_color: blue
primary: Eye
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: wink 4s ease-in-out infinite;
}
@keyframes wink {
0%, 100% { transform: scale(1, 1); }
19% { transform: scale(1.05, 0.6); }
20% { clip-path: polygon(0 100%, 100% 100%, 100% 49%, 86% 51%, 79% 59%, 70% 66%, 57% 71%, 43% 71%, 29% 65%, 21% 57%, 13% 49%, 0 49%); }
25% { transform: scale(1, 1); }
28% { transform: scale(0.95, 1.05); }
30% { clip-path: inset(0 0 0 0); }
}
Camera #1 Animation
type: custom:mushroom-template-card
icon: mdi:cctv
icon_color: deep-purple
primary: 'Camera #1'
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: flip 8s ease-in-out infinite alternate;
}
@keyframes flip {
50% { transform: rotateY(180deg); }
}
Camera #2 Animation
type: custom:mushroom-template-card
primary: 'Camera #2'
icon: mdi:cctv
icon_color: deep-purple
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: scan 5s ease-in-out infinite;
transform-origin: 90% 80%
}
@keyframes scan {
0%, 100% { transform: rotate(20deg); }
50% { transform: rotate(-15deg); }
}
Battery #1 Animation
type: custom:mushroom-template-card
icon: mdi:battery
icon_color: green
primary: 'Battery #1'
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: charge 3s linear infinite;
}
@keyframes charge {
0%, 80% { clip-path: inset(0 0 0 0); }
10% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 84%, 34% 84%, 34% 100%, 100% 100%, 100% 0%); }
20% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 74%, 34% 74%, 34% 100%, 100% 100%, 100% 0%); }
30% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 64%, 34% 64%, 34% 100%, 100% 100%, 100% 0%); }
40% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 54%, 34% 54%, 34% 100%, 100% 100%, 100% 0%); }
50% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 44%, 34% 44%, 34% 100%, 100% 100%, 100% 0%); }
60% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 34%, 34% 34%, 34% 100%, 100% 100%, 100% 0%); }
70% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 24%, 34% 24%, 34% 100%, 100% 100%, 100% 0%); }
}
Battery #2 Animation
type: custom:mushroom-template-card
icon: mdi:battery-high
icon_color: green
primary: 'Battery #2'
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: charge 3s steps(1) infinite;
}
@keyframes charge {
0% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 84%, 34% 84%, 34% 100%, 100% 100%, 100% 0%); }
20% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 64%, 34% 64%, 34% 100%, 100% 100%, 100% 0%); }
40% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 44%, 34% 44%, 34% 100%, 100% 100%, 100% 0%); }
60% { clip-path: polygon(0% 0%, 0% 100%, 34% 100%, 34% 24%, 67% 24%, 67% 24%, 34% 24%, 34% 100%, 100% 100%, 100% 0%); }
}
Wrench Animation
type: custom:mushroom-template-card
primary: Wrench
icon: mdi:wrench
icon_color: grey
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
--icon-animation: tighten 1.5s ease-in-out infinite;
transform-origin: 31% 31%
}
@keyframes tighten {
0%, 100% { transform: rotate(-20deg); }
80% { transform: rotate(15deg); }
}
thank you this is great
I’ve changed the pagelayout to “Grid (layout-card)” and used this as a custom grid:
grid-template-columns: auto 380px 380px auto
grid-template-rows: auto
place-items: center stretch
grid-template-areas: |
". chips chips ."
". title1 title1 ."
". links1 rechts1 ."
". title2 title2 ."
". links2 rechts2 ."
mediaquery:
"(max-width: 600px)":
grid-template-columns: 100%
grid-template-areas: |
"chips"
"title1"
"links1"
"rechts1"
"title2"
"links2"
"rechts2"
"(max-width: 990px)":
grid-template-columns: 100%
grid-template-areas: |
"chips"
"title1"
"links1"
"rechts1"
"title2"
"links2"
"rechts2"
For each card you pick the position in the grid, like this:
view_layout:
grid-area: chips
This is a background color problem. I use
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
It works but most of the time I get estrange behavior.
I design a thermostat for multiples room that can be control all together or each one individually.
The problem is that most of the time the conditional card did not change the background.
To expand the thermostat I hold any Icon and it show like:
but it shows like:
the entire code is:
type: vertical-stack
cards:
- type: custom:stack-in-card
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Arriba
secondary: '{{ states(''sensor.temp_zona_arriba_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_zona_arriba
icon_color: |-
{% if is_state('climate.radiador_zona_arriba', 'heat') %}
orange
{% else %}
grey
{% endif %}
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id:
- input_boolean.radiador_pieza
- input_boolean.radiador_bano_pieza
- input_boolean.radiador_jose
- input_boolean.radiador_ninas
- input_boolean.radiador_estar
- input_boolean.radiador_bano_arriba
- type: custom:mushroom-climate-card
entity: climate.radiador_zona_arriba
show_temperature_control: true
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
- type: horizontal-stack
cards:
- type: custom:stack-in-card
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Pieza
secondary: '{{ states(''sensor.temp_pieza_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_pieza
icon_color: |-
{% if is_state('climate.radiador_pieza', 'heat') %}
orange
{% else %}
grey
{% endif %}
fill_container: true
double_tap_action:
action: more-info
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id: input_boolean.radiador_pieza
- type: conditional
conditions:
- entity: input_boolean.radiador_pieza
state: 'on'
card:
type: custom:mushroom-climate-card
entity: climate.radiador_pieza
show_temperature_control: |-
{% if is_state('input_boolean.radiador_pieza','on' %}
true
{% else %}
false
{% endif %}
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
- type: custom:stack-in-card
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Baño
secondary: '{{ states(''sensor.temp_bano_pieza_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_bano_pieza
icon_color: |-
{% if is_state('climate.radiador_bano_pieza', 'heat') %}
orange
{% else %}
grey
{% endif %}
fill_container: true
double_tap_action:
action: more-info
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id: input_boolean.radiador_bano_pieza
- type: conditional
conditions:
- entity: input_boolean.radiador_bano_pieza
state: 'on'
card:
type: custom:mushroom-climate-card
entity: climate.radiador_bano_pieza
show_temperature_control: |-
{% if is_state('input_boolean.radiador_bano_pieza','on' %}
true
{% else %}
false
{% endif %}
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
- type: horizontal-stack
cards:
- type: custom:stack-in-card
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Jose
secondary: '{{ states(''sensor.temp_jose_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_jose
icon_color: |-
{% if is_state('climate.radiador_jose', 'heat') %}
orange
{% else %}
grey
{% endif %}
fill_container: true
double_tap_action:
action: more-info
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id: input_boolean.radiador_jose
- type: conditional
conditions:
- entity: input_boolean.radiador_jose
state: 'on'
card:
type: custom:mushroom-climate-card
entity: climate.radiador_jose
show_temperature_control: |-
{% if is_state('input_boolean.radiador_jose','on' %}
true
{% else %}
false
{% endif %}
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
- type: custom:stack-in-card
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Niñas
secondary: '{{ states(''sensor.temp_ninas_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_ninas
icon_color: |-
{% if is_state('climate.radiador_ninas', 'heat') %}
orange
{% else %}
grey
{% endif %}
fill_container: true
double_tap_action:
action: more-info
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id: input_boolean.radiador_ninas
- type: conditional
conditions:
- entity: input_boolean.radiador_ninas
state: 'on'
card:
type: custom:mushroom-climate-card
entity: climate.radiador_ninas
show_temperature_control: |-
{% if is_state('input_boolean.radiador_ninas','on' %}
true
{% else %}
false
{% endif %}
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
- type: horizontal-stack
cards:
- type: custom:stack-in-card
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Estar
secondary: '{{ states(''sensor.temp_estar_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_estar
icon_color: |-
{% if is_state('climate.radiador_estar', 'heat') %}
orange
{% else %}
grey
{% endif %}
fill_container: true
double_tap_action:
action: more-info
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id: input_boolean.radiador_estar
- type: conditional
conditions:
- entity: input_boolean.radiador_estar
state: 'on'
card:
type: custom:mushroom-climate-card
entity: climate.radiador_estar
show_temperature_control: |-
{% if is_state('input_boolean.radiador_estar','on' %}
true
{% else %}
false
{% endif %}
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
- type: custom:stack-in-card
keep:
margin: false
box_shadow: false
background: false
cards:
- type: custom:mushroom-template-card
primary: Baño
secondary: '{{ states(''sensor.temp_bano_arriba_temperature'') | round(1)}}°C'
icon: mdi:radiator
entity: climate.radiador_bano_arriba
icon_color: |-
{% if is_state('climate.radiador_bano_arriba', 'heat') %}
orange
{% else %}
grey
{% endif %}
fill_container: true
double_tap_action:
action: more-info
hold_action:
action: call-service
service: input_boolean.toggle
data: {}
target:
entity_id: input_boolean.radiador_bano_arriba
- type: conditional
conditions:
- entity: input_boolean.radiador_bano_arriba
state: 'on'
card:
type: custom:mushroom-climate-card
entity: climate.radiador_bano_arriba
show_temperature_control: |-
{% if is_state('input_boolean.radiador_bano_arriba','on' %}
true
{% else %}
false
{% endif %}
fill_container: false
secondary_info: none
primary_info: none
icon_type: none
collapsible_controls: false
card_mod:
style: |
ha-card
{
background: rgba(255, 152, 0, 0.1);
}
Great… thanks alot for sharing…
animations for washing machine and dishwasher are really useful, but can the card mod only be applied when the power for that device is above a certain level? i.e. washing machine icon shakes while the washing machine is running and not idle.
Love your work, above and beyond in helping me take my first steps in customising HA
thanks for sharing this great stuff
Made this collapsible Furnace Filter card if anyone wants it. It can be easily changed to be for a Water Filter, Softener, etc. I borrowed some code from Rhys’s Mushroom Bar Card and the rest of the info to make it can be found here:
Mushroom Card code:
type: custom:stack-in-card
cards:
- type: custom:layout-card
layout_type: custom:grid-layout
layout:
grid-template-columns: 42px auto 12px
margin: '-4px -4px -8px -4px;'
cards:
- type: custom:mushroom-template-card
entity: sensor.furnace_filter_days_remaining
icon: mdi:air-filter
icon_color: |
{% set filter_days = states(entity) | int %}
{% if filter_days < 31 %}
red
{% elif filter_days < 91 %}
orange
{% else %}
green
{% endif %}
card_mod:
style: |
ha-card {
background: none;
--ha-card-box-shadow: 0px;
}
- type: custom:bar-card
entity: sensor.furnace_filter_days_remaining
height: 42px
min: '0'
max: '182'
entity_row: true
severity:
- color: rgb(var(--mush-rgb-green))
from: 91
to: 182
- color: rgb(var(--mush-rgb-orange))
from: 21
to: 90
- color: rgb(var(--mush-rgb-red))
from: 0
to: 30
positions:
icon: 'off'
indicator: 'off'
card_mod:
style: |
ha-card {
padding: 12px;
margin-left: 12px;
--bar-card-border-radius: 12px;
}
bar-card-value {
margin: 12px;
font-size: 12px;
font-weight: bolder;
}
bar-card-name {
margin: 12px;
font-size: 12px;
font-weight: bolder;
}
bar-card-backgroundbar {
opacity: 0.2;
filter: brightness(1);
}
- type: custom:mushroom-template-card
entity: input_boolean.furnace_filter_dropdown
icon: mdi:chevron-down
icon_color: disabled
hold_action:
action: none
card_mod:
style:
mushroom-shape-icon:
$: |
.shape ha-icon {
transition: transform 0.14s !important;
{{ 'transform: rotate(-180deg);' if is_state(config.entity, 'on') }}
}
.: |
ha-card {
align-items: flex-end;
box-shadow: none;
}
mushroom-shape-icon {
--shape-color: none !important;
}
- type: custom:stack-in-card
mode: horizontal
cards:
- type: custom:mushroom-entity-card
entity: input_datetime.furnace_filter_last_replaced
icon: mdi:calendar
name: Last Replaced
layout: vertical
primary_info: state
secondary_info: name
card_mod:
style: |
ha-card {
width: 130px;
margin-left: auto;
margin-right: auto;
}
- type: custom:mushroom-entity-card
entity: sensor.furnace_filter_days_since_replacement
name: Since Replaced
layout: vertical
primary_info: state
secondary_info: name
card_mod:
style: |
ha-card {
width: 130px;
margin-left: auto;
margin-right: auto;
}
- type: custom:mushroom-entity-card
entity: input_number.furnace_filter_threshold
icon: mdi:calendar-edit
name: Replacement Interval
layout: vertical
primary_info: state
secondary_info: name
card_mod:
style: |
ha-card {
width: 130px;
margin-left: auto;
margin-right: auto;
}
- type: custom:mushroom-template-card
primary: Reset
secondary: ''
icon: mdi:refresh
layout: vertical
tap_action:
action: call-service
service: script.reset_furnace_filter_date_to_today
data: {}
target: {}
hold_action:
action: none
double_tap_action:
action: none
card_mod:
style: |
ha-card {
margin-top: -14px;
}
card_mod:
style: |
ha-card {
{{ 'height: 66px;' if is_state('input_boolean.furnace_filter_dropdown', 'off') }}
}
a little bit of change in the code and I was able to accomplish it like this.
type: custom:mushroom-template-card
icon: mdi:washing-machine
entity: sensor.washer
tap_action:
action: more-info
icon_color: blue
primary: Washing Machine
secondary: '{{ states(entity) | title }}'
card_mod:
style:
mushroom-shape-icon$: |
{% if is_state('sensor.washer','on') %}
ha-icon {
--icon-animation: shake 400ms ease-in-out infinite, drum 2s ease infinite;
transform-origin: 50% 110%;
}
@keyframes shake {
0%, 100% { transform: translate(0, 0) rotate(0); }
20% { transform: translate(0.4px, -0.4px) rotate(-4deg); }
40% { transform: translate(-0.4px, 0.4px) rotate(4deg); }
60% { transform: translate(0.4px, 0.4px) rotate(-4deg); }
80% { transform: translate(-0.4px, -0.4px) rotate(4deg); }
}
@keyframes drum {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 34% 68%, 60% 41%, 71% 56%, 65% 74%, 47% 79%, 32% 69%, 35% 100%, 100% 100%, 100% 0); }
}
{% else %}
{% endif %}
}
You can do it within the Mushroom template card, but I prefer to create a sensor template that turns on when the power is over a certain value.
configuration.yaml
sensor:
- platform: template
sensors:
washing_machine:
friendly_name: "Washing Machine"
value_template: >-
{% if states('sensor.washing_machine_power') | float > 4 %}
on
{% else %}
off
{% endif %}
icon_template: mdi:washing-machine
Mushroom template card:
type: custom:mushroom-template-card
primary: Washing Machine
entity: sensor.washing_machine
secondary: |-
{% if states(entity) == 'on' %}
{{ states(entity+'_power') | round(0) }} W
{% else %}
Off
{% endif %}
icon: mdi:washing-machine
icon_color: '{{ ''blue'' if is_state(entity, ''on'') else ''disabled'' }}'
tap_action:
action: none
card_mod:
style:
mushroom-shape-icon$: |
ha-icon {
{% if is_state(config.entity, 'on') %}
--icon-animation: shake 400ms ease-in-out infinite, drum 2s ease infinite;
{% endif %}
transform-origin: 50% 110%;
}
@keyframes shake {
0%, 100% { transform: translate(0, 0) rotate(0); }
20% { transform: translate(0.4px, -0.4px) rotate(-4deg); }
40% { transform: translate(-0.4px, 0.4px) rotate(4deg); }
60% { transform: translate(0.4px, 0.4px) rotate(-4deg); }
80% { transform: translate(-0.4px, -0.4px) rotate(4deg); }
}
@keyframes drum {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 34% 68%, 60% 41%, 71% 56%, 65% 74%, 47% 79%, 32% 69%, 35% 100%, 100% 100%, 100% 0); }
}
The same idea can be applied to other appliances, such as dryer, dishwasher, oven etc
Amazing, thank you
OK, this takes me down a new rabbit hole of knowledge, thanks again for sharing the know-how.
Love this contribution. I’m going around my current dashboard and trying to animate where I can using some of your examples. For the most part I’ve gotten everything figured out except this last little piece when trying to add in the chip styling code to remove the shadow and outline around the individual chips. Any tips on how to achieve this? Anything I’ve tried with card mod just disables the animation.
Providing my code and gif
type: custom:stack-in-card
cards:
- type: custom:mushroom-template-card
primary: Garage
secondary: '{{ states(''sensor.livingroom'') }}'
icon: mdi:garage
entity: input_boolean.garage_light
tap_action:
action: navigate
navigation_path: garage
hold_action:
action: toggle
icon_color: '{{ ''orange'' if is_state(entity, ''on'') else ''disabled'' }}'
fill_container: true
layout: horizontal
multiline_secondary: false
card_mod:
style: |
:host([dark-mode]) {
background: rgba(var(--rgb-primary-background-color), 0.2);
}
:host {
background: rgba(var(--rgb-primary-text-color), 0.025);
--mush-icon-size: 56px;
height: 66px;
margin-left: -22px !important;
}
- type: custom:mushroom-chips-card
chips:
- type: template
icon: mdi:washing-machine
icon_color: |2-
{% if is_state(entity, 'off') %}
grey
{% else %}
blue
{% endif %}
entity: sensor.washer
tap_action:
action: more-info
- type: template
icon: mdi:tumble-dryer
icon_color: |2-
{% if is_state(entity, 'off') %}
grey
{% else %}
red
{% endif %}
entity: sensor.dryer
tap_action:
action: more-info
card_mod:
style:
mushroom-template-chip:nth-child(1)$: |
{% if is_state('sensor.washer','on') %}
ha-icon {
animation: shake 800ms ease-in-out infinite, drum 2s ease infinite;
}
@keyframes shake {
0%, 100% { transform: translate(0, 0) rotate(0); }
20% { transform: translate(0.4px, -0.4px) rotate(-4deg); }
40% { transform: translate(-0.4px, 0.4px) rotate(4deg); }
60% { transform: translate(0.4px, 0.4px) rotate(-4deg); }
80% { transform: translate(-0.4px, -0.4px) rotate(4deg); }
}
@keyframes drum {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 34% 68%, 60% 41%, 71% 56%, 65% 74%, 47% 79%, 32% 69%, 35% 100%, 100% 100%, 100% 0); }
}
{% else %}
{% endif %}
}
mushroom-template-chip:nth-child(2)$: |
{% if is_state('sensor.dryer','on') %}
ha-icon {
animation: shake 800ms ease-in-out infinite, drum 1s infinite;
transform-origin: 100% 100%;
}
@keyframes shake {
0%, 100% { transform: rotate(4deg); }
50% { transform: rotate(-4deg); }
}
@keyframes drum {
50% { clip-path: polygon(0 0, 0 100%, 35% 100%, 36% 74%, 31% 43%, 61% 40%, 71% 69%, 62% 78%, 36% 73%, 35% 100%, 100% 100%, 100% 0); }
}
{% else %}
{% endif %}
}
alignment: end
card_mod:
style: |
ha-card {
height: 102px;
{% if is_state('input_boolean.garage_light', 'on') %}
background: rgba(255, 152, 0, 0.1);
{% endif %}
}