Here’s a little Panel (Single Card) display that I made for a home theater display for Plex. It has a old school marquee vibe to it and can handle multiple players at once. For best results use a dark theme for the view (makes sure that the text is white).
Requirements:
- Card Mod from HACS
- Mushroom Cards from HACS
- Auto Entities from HACS
Create a new view and select Panel layout
Add a card on the panel layout and select manual and then paste in the following code:
type: custom:auto-entities
card_mod:
style:
hui-grid-card$: >
{% set active_players = states.media_player | selectattr('state', 'in',
['playing', 'paused']) | list | length %}
#root {
height: calc(100vh - 65px) !important;
display: flex !important;
flex-direction: column !important;
gap: 0px !important;
/* THE MARGIN NUKES */
--grid-card-gap: 0px !important;
--stack-card-margin: 0px !important;
--masonry-view-card-margin: 0px !important;
}
#root > * {
flex: 1 1 0 !important;
min-height: 150px !important;
margin: 0px !important;
padding: 0px !important; /* <--- NEW */
}
{% if active_players > 0 %}
/* The Cinematic Title Banner */
#root::before {
content: "NOW PLAYING";
flex: 0 0 auto !important; /* Stops the banner from stretching */
display: flex;
align-items: center;
justify-content: center;
min-height: 50px;
margin-bottom: 15px;
border-radius: 12px;
background-color: rgba(0, 0, 0, 0.5);
/* The Skewed Light Beam + Sparkles */
background-image:
linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.4) 45%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,0.4) 55%, transparent 100%),
radial-gradient(circle at 15px 15px, white 1px, transparent 1.5px),
radial-gradient(circle at 50px 35px, white 2px, transparent 2.5px),
radial-gradient(circle at 25px 45px, rgba(255,255,255,0.7) 1px, transparent 1.5px),
radial-gradient(circle at 80px 10px, white 1.5px, transparent 2px);
background-size: 200% 100%, 40px 40px, 70px 70px, 50px 50px, 90px 90px;
background-repeat: no-repeat, repeat, repeat, repeat, repeat;
/* Text Styling */
font-size: 24px;
font-weight: 900;
letter-spacing: 6px;
animation: root-sweep 4s infinite, root-pulse 4s infinite;
}
@keyframes root-sweep {
0% { background-position: -100% 0, 0 0, 0 0, 0 0, 0 0; }
50% { background-position: 200% 0, 0 0, 0 0, 0 0, 0 0; }
100% { background-position: 200% 0, 0 0, 0 0, 0 0, 0 0; }
}
@keyframes root-pulse {
0%, 15% { color: white; text-shadow: 2px 2px 4px rgba(0,0,0,0.8); }
48%, 52% { color: #ffeb3b; text-shadow: 0 0 20px rgba(255, 235, 59, 1), 0 0 10px rgba(255, 255, 255, 0.8); }
90%, 100% { color: white; text-shadow: 2px 2px 4px rgba(0,0,0,0.8); }
}
{% endif %}
hui-vertical-stack-card$: >
{% set active_players = states.media_player | selectattr('state', 'in',
['playing', 'paused']) | list | length %}
#root {
height: calc(100vh - 65px) !important;
display: flex !important;
flex-direction: column !important;
gap: 0px !important; /* <--- THIS CONTROLS THE SPACE BETWEEN CARDS */
}
#root > * {
flex: 1 1 0 !important;
min-height: 150px !important;
margin: 0 !important; /* <--- THIS DELETES HOME ASSISTANT'S DEFAULT EXTRA PADDING */
}
{% if active_players > 0 %}
/* The Cinematic Title Banner */
#root::before {
content: "NOW PLAYING";
flex: 0 0 auto !important; /* Stops the banner from stretching */
display: flex;
align-items: center;
justify-content: center;
min-height: 50px;
margin-bottom: 15px;
border-radius: 12px;
background-color: rgba(0, 0, 0, 0.5);
/* The Skewed Light Beam + Sparkles */
background-image:
linear-gradient(115deg, transparent 0%, rgba(255,255,255,0.4) 45%, rgba(255,255,255,0.7) 50%, rgba(255,255,255,0.4) 55%, transparent 100%),
radial-gradient(circle at 15px 15px, white 1px, transparent 1.5px),
radial-gradient(circle at 50px 35px, white 2px, transparent 2.5px),
radial-gradient(circle at 25px 45px, rgba(255,255,255,0.7) 1px, transparent 1.5px),
radial-gradient(circle at 80px 10px, white 1.5px, transparent 2px);
background-size: 200% 100%, 40px 40px, 70px 70px, 50px 50px, 90px 90px;
background-repeat: no-repeat, repeat, repeat, repeat, repeat;
/* Text Styling */
font-size: 24px;
font-weight: 900;
letter-spacing: 6px;
animation: root-sweep 4s infinite, root-pulse 4s infinite;
}
@keyframes root-sweep {
0% { background-position: -100% 0, 0 0, 0 0, 0 0, 0 0; }
50% { background-position: 200% 0, 0 0, 0 0, 0 0, 0 0; }
100% { background-position: 200% 0, 0 0, 0 0, 0 0, 0 0; }
}
@keyframes root-pulse {
0%, 40% { color: white; text-shadow: 2px 2px 4px rgba(0,0,0,0.8); }
48%, 52% { color: #ffeb3b; text-shadow: 0 0 20px rgba(255, 235, 59, 1), 0 0 10px rgba(255, 255, 255, 0.8); }
60%, 100% { color: white; text-shadow: 2px 2px 4px rgba(0,0,0,0.8); }
}
{% endif %}
card:
type: grid
columns: 1
square: false
card_param: cards
filter:
include:
- domain: media_player
state: /playing|paused/
entity_id: "*plex*"
options:
type: custom:mushroom-media-player-card
icon_type: none
layout: vertical
primary_info: name
fill_container: true
use_media_info: true
card_mod:
style: |
/* 1. Force the hidden wrapper to stretch and drop margins */
:host {
height: 100% !important;
width: 100% !important;
margin: 0px !important; /* <--- NEW */
padding: 0px !important; /* <--- NEW */
}
/* 2. Force the card to fill the wrapper and drop its margins */
ha-card {
height: 100% !important;
width: 100% !important;
margin: 0 !important; /* Kills the invisible gap outside the border */
box-sizing: border-box !important; /* Ensures the thick 12px border doesn't cause overflow */
background: url('{{ state_attr(config.entity, "entity_picture") }}');
background-size: cover;
background-position: center;
background-blend-mode: saturation;
position: relative;
display: block !important;
--primary-text-color: white !important;
--secondary-text-color: rgba(255, 255, 255, 0.8) !important;
/* THE HOLLYWOOD MARQUEE BORDER */
border: 12px solid #111 !important;
outline: 6px dotted #ffcc00 !important;
outline-offset: -16px !important;
animation: marquee-glow 2s infinite alternate;
}
/* Player Name (Top Left) - Matching the white-on-black look */
ha-card::before {
content: "{{ state_attr(config.entity, 'friendly_name') }}";
position: absolute;
top: 12px;
left: 12px;
font-size: 14px;
font-weight: bold;
color: white;
background: rgba(0,0,0,0.6);
padding: 4px 10px;
border-radius: 4px;
z-index: 2;
}
/* Media Info Box (Top Right) */
mushroom-state-item {
position: absolute !important;
top: 12px !important;
right: 12px !important;
bottom: auto !important; /* Stops it from stretching downward */
height: max-content !important; /* Forces the box to shrink-wrap the text */
background: rgba(0, 0, 0, 0.6) !important;
padding: 4px 10px !important;
border-radius: 4px !important;
max-width: 60% !important;
display: flex !important;
}
mushroom-state-info {
text-align: right !important;
display: flex !important;
flex-direction: column !important; /* Stacks title and episode */
justify-content: flex-start !important; /* Pushes text to the top */
align-items: flex-end !important; /* Aligns text to the right edge */
margin: 0 !important;
}
/* The Glowing Light Animation */
@keyframes marquee-glow {
0% {
/* Dark room corner shadow + Dim orange halo */
box-shadow: inset 0 0 50px rgba(0,0,0,0.9), inset 0 0 10px 4px rgba(255, 150, 0, 0.1);
outline-color: #cc8800; /* Dimmed orange bulb */
}
100% {
/* Dark room corner shadow + BRIGHT yellow halo */
box-shadow: inset 0 0 50px rgba(0,0,0,0.9), inset 0 0 30px 12px rgba(255, 230, 0, 0.8);
outline-color: #ffee00; /* Blazing yellow bulb */
}
}
card_mod: null
style: |
/* This targets the grid container itself */
.card-content {
display: grid !important;
/* This says: fill the space with cards at least 400px wide.
If only 1 card exists, it will take the full width! */
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)) !important;
gap: 16px !important;
}
grid_options:
columns: 12
rows: 1
** I tried a bunch of stuff to get rid of the margins around each mushroom media player card but couldn’t figure it out. If anyone has any better ideas let me know!
