A replacement for vertical-stack-in-card and horizontal-stack-in-card
with some more features.
It allows to group multiple cards into one card without the borders. By default, it will stack everything vertically.
Options
If a card inside the stack has the --keep-background
CSS style defined, it will not replace the background. This is usefull for button-card for example. You can also define this CSS variable by using card-mod .
Name
Type
Requirement
Description
Default
type
string
Required
custom:stack-in-card
title
string
Optional
Header of the card
mode
string
Optional
vertical
or horizontal
stack
vertical
cards
object
Required
The cards you want to embed
none
Example
Simple Example
- type: custom:stack-in-card
title: My Stack In Card
mode: vertical
cards:
- type: horizontal-stack
cards:
- type: button
entity: sun.sun
- type: button
entity: sun.sun
- type: vertical-stack
cards:
- type: entities
entities:
- sun.sun
Example with button-card to keep the background
This will keep the background of the button even if stacked:
- type: custom:stack-in-card
title: My Stack In Card
mode: vertical
cards:
- type: custom:button-card
entity: sun.sun
color_type: card
styles:
card:
- --keep-background: 'true'
Installation
Use HACS or follow this guide
resources:
url: /local/stack-in-card.js
type: module
18 Likes
SeLLeRoNe
(Andrea Iannucci)
March 21, 2020, 12:12pm
2
Updating the HACS Repos to find it
Knapoc
March 21, 2020, 12:13pm
3
does styling work the same as with vertical-stack-in-card?
This following code produces this:
- type: custom:mod-card # robovac
style: |
ha-card {
height: 115px;
background-color: var(--primary-background-color);
border-radius: 15px;
box-shadow:
{% if is_state('sun.sun', 'above_horizon') %}
-4px -4px 4px 0 rgba(255,255,255,.5),4px 4px 4px 0 rgba(0,0,0,.03);
{% else %}
-4px -4px 4px 0 rgba(50, 50, 50,.5),4px 4px 4px 0 rgba(0,0,0,.15);
{% endif %}
}
card:
type: custom:stack-in-card
mode: vertical
cards:
- type: entities
entities:
- entity: vacuum.robovac
type: custom:multiple-entity-row
name: Robovac
show_state: false
entities:
- attribute: status
name: Status
- attribute: battery_level
name: Battery
unit: '%'
- entity: counter.vacuum_counter
name: Count
style: |
ha-card {
height: 70px;
}
- type: horizontal-stack
cards:
- type: custom:button-card
color: auto
entity: vacuum.robovac
size: 25%
icon: mdi:play
show_name: false
tap_action:
action: call-service
service: vacuum.turn_on
service_data:
entity_id: vacuum.robovac
- type: custom:button-card
color: auto
entity: vacuum.robovac
size: 25%
icon: mdi:pause
show_name: false
tap_action:
action: call-service
service: vacuum.pause
service_data:
entity_id: vacuum.robovac
- type: custom:button-card
color: auto
entity: vacuum.robovac
size: 25%
icon: mdi:broom
show_name: false
tap_action:
action: call-service
service: vacuum.clean_spot
service_data:
entity_id: vacuum.robovac
- type: custom:button-card
color: auto
entity: vacuum.robovac
size: 25%
icon: mdi:map-marker
show_name: false
tap_action:
action: call-service
service: vacuum.locate
service_data:
entity_id: vacuum.robovac
- type: custom:button-card
color: auto
entity: vacuum.robovac
size: 25%
icon: mdi:home-map-marker
show_name: false
tap_action:
action: call-service
service: vacuum.return_to_base
service_data:
entity_id: vacuum.robovac
Edit: Oh got it⌠mod-card is no longer needed
Edit 2: got it to work on this example but this config fails:
- type: custom:stack-in-card
style: |
ha-card {
background-color: var(--primary-background-color);
border-radius: 15px;
box-shadow:
{% if is_state('sun.sun', 'above_horizon') %}
-4px -4px 4px 0 rgba(255,255,255,.5),4px 4px 4px 0 rgba(0,0,0,.03);
{% else %}
-4px -4px 4px 0 rgba(50, 50, 50,.5),4px 4px 4px 0 rgba(0,0,0,.15);
{% endif %}
}
mode: vertical
cards:
- type: glance
title: Home Assistant
columns: 7
show_name: false
entities:
- entity: sensor.count_automations
name: Automations
icon: mdi:play-circle
- entity: sensor.count_binary_sensors
name: Binary Sensors
icon: mdi:transition-masked
- entity: sensor.count_lights
name: Lights
icon: mdi:lightbulb
- entity: sensor.count_scripts
name: Scripts
icon: mdi:script-text
- entity: sensor.count_sensors
name: Sensors
icon: mdi:counter
- entity: sensor.count_switches
name: Switches
icon: mdi:toggle-switch
- entity: sensor.count_zones
name: Zones
- type: entities
show_header_toggle: false
entities:
- entity: sensor.potential_breaking_changes
name: Breaking changes
icon: mdi:alert-circle
- entity: input_select.log_level
AhmadK
(akasma74)
March 21, 2020, 12:16pm
4
Thanks for the new card!
If not using HACS, where can we find that stack-in-card.js
?
AhmadK
(akasma74)
March 21, 2020, 12:20pm
6
I looked at that page but forgot to check releases
button/section. Got it now.
McGiverGim
(MĂguel Ăngel Mulero MartĂnez)
March 21, 2020, 12:24pm
7
Great! Replaced the old vertical-in-card and working perfectly. Thanks!
SeLLeRoNe
(Andrea Iannucci)
March 21, 2020, 1:10pm
8
@RomRider I got a question, is it possible to have the âdividerâ working inside the stack-in-card?
My code:
people:
card:
type: custom:stack-in-card
mode: vertical
cards:
- type: custom:decluttering-card
template: title
variables:
- title: People
- type: custom:decluttering-card
template: andrea
- type: divider
The error:
Also, I am seeing in the console a huge amount of errors like this one:
hui-stack-card.ts:109 Uncaught TypeError: Cannot read property 'replaceChild' of null
at HTMLElement.value (hui-stack-card.ts:109)
at HTMLElement.t.addEventListener.once (hui-stack-card.ts:97)
at r (fire_event.ts:76)
at create-element-base.ts:94
value @ hui-stack-card.ts:109
t.addEventListener.once @ hui-stack-card.ts:97
r @ fire_event.ts:76
(anonymous) @ create-element-base.ts:94
Promise.then (async)
a @ create-element-base.ts:92
l @ create-element-base.ts:154
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
_createCard @ decluttering-card.js:743
async function (async)
_createCard @ decluttering-card.js:743
setConfig @ decluttering-card.js:739
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
_createCard @ decluttering-card.js:743
async function (async)
_createCard @ decluttering-card.js:743
setConfig @ decluttering-card.js:739
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
(anonymous) @ layout-card.js:1
u @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_card @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_cards @ layout-card.js:1
updated @ layout-card.js:1
performUpdate @ updating-element.ts:720
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
initialize @ lit-element.ts:146
A @ updating-element.ts:438
V @ lit-element.ts:61
p @ layout-card.js:1
s @ create-element-base.ts:56
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-panel-view.ts:55
value @ hui-panel-view.ts:34
performUpdate @ updating-element.ts:704
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
A @ updating-element.ts:438
i @ hui-panel-view.ts:16
value @ hui-root.ts:709
(anonymous) @ hui-root.ts:79
(anonymous) @ debounce.ts:22
setTimeout (async)
(anonymous) @ debounce.ts:27
handleEvent @ parts.ts:505
__boundHandleEvent @ parts.ts:463
r @ card-mod.js:1
(anonymous) @ card-mod.js:1
Promise.then (async)
(anonymous) @ card-mod.js:1
n @ card-mod.js:1
(anonymous) @ card-mod.js:1
(anonymous) @ card-mod.js:1
3hui-stack-card.ts:109 Uncaught TypeError: Cannot read property 'replaceChild' of null
at HTMLElement.value (hui-stack-card.ts:109)
at HTMLElement.t.addEventListener.once (hui-stack-card.ts:97)
at r (fire_event.ts:76)
at create-element-base.ts:94
value @ hui-stack-card.ts:109
t.addEventListener.once @ hui-stack-card.ts:97
r @ fire_event.ts:76
(anonymous) @ create-element-base.ts:94
Promise.then (async)
a @ create-element-base.ts:92
l @ create-element-base.ts:154
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
_createCard @ decluttering-card.js:743
async function (async)
_createCard @ decluttering-card.js:743
setConfig @ decluttering-card.js:739
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
(anonymous) @ layout-card.js:1
build_card @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_cards @ layout-card.js:1
updated @ layout-card.js:1
performUpdate @ updating-element.ts:720
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
initialize @ lit-element.ts:146
A @ updating-element.ts:438
V @ lit-element.ts:61
p @ layout-card.js:1
s @ create-element-base.ts:56
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-panel-view.ts:55
value @ hui-panel-view.ts:34
performUpdate @ updating-element.ts:704
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
A @ updating-element.ts:438
i @ hui-panel-view.ts:16
value @ hui-root.ts:709
(anonymous) @ hui-root.ts:79
(anonymous) @ debounce.ts:22
setTimeout (async)
(anonymous) @ debounce.ts:27
handleEvent @ parts.ts:505
__boundHandleEvent @ parts.ts:463
a @ layout-card.js:1
(anonymous) @ layout-card.js:1
Promise.then (async)
(anonymous) @ layout-card.js:1
u @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_card @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_cards @ layout-card.js:1
updated @ layout-card.js:1
performUpdate @ updating-element.ts:720
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
requestUpdate @ updating-element.ts:623
updateSize @ layout-card.js:1
firstUpdated @ layout-card.js:1
performUpdate @ updating-element.ts:718
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
initialize @ lit-element.ts:146
A @ updating-element.ts:438
V @ lit-element.ts:61
p @ layout-card.js:1
s @ create-element-base.ts:56
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-panel-view.ts:55
value @ hui-panel-view.ts:34
performUpdate @ updating-element.ts:704
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
A @ updating-element.ts:438
i @ hui-panel-view.ts:16
value @ hui-root.ts:709
(anonymous) @ hui-root.ts:79
(anonymous) @ debounce.ts:22
setTimeout (async)
(anonymous) @ debounce.ts:27
handleEvent @ parts.ts:505
__boundHandleEvent @ parts.ts:463
r @ card-mod.js:1
(anonymous) @ card-mod.js:1
Promise.then (async)
(anonymous) @ card-mod.js:1
n @ card-mod.js:1
(anonymous) @ card-mod.js:1
(anonymous) @ card-mod.js:1
3hui-stack-card.ts:109 Uncaught TypeError: Cannot read property 'replaceChild' of null
at HTMLElement.value (hui-stack-card.ts:109)
at HTMLElement.t.addEventListener.once (hui-stack-card.ts:97)
at r (fire_event.ts:76)
at create-element-base.ts:94
value @ hui-stack-card.ts:109
t.addEventListener.once @ hui-stack-card.ts:97
r @ fire_event.ts:76
(anonymous) @ create-element-base.ts:94
Promise.then (async)
a @ create-element-base.ts:92
l @ create-element-base.ts:154
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
_createCard @ decluttering-card.js:743
async function (async)
_createCard @ decluttering-card.js:743
setConfig @ decluttering-card.js:739
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-stack-card.ts:89
(anonymous) @ hui-stack-card.ts:54
value @ hui-stack-card.ts:53
s @ create-element-base.ts:61
l @ create-element-base.ts:158
Tt @ create-card-element.ts:53
_createCard @ stack-in-card.js:784
async function (async)
_createCard @ stack-in-card.js:784
setConfig @ stack-in-card.js:758
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
_createCard @ decluttering-card.js:743
async function (async)
_createCard @ decluttering-card.js:743
setConfig @ decluttering-card.js:739
s @ create-element-base.ts:61
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
(anonymous) @ layout-card.js:1
build_card @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_cards @ layout-card.js:1
updated @ layout-card.js:1
performUpdate @ updating-element.ts:720
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
initialize @ lit-element.ts:146
A @ updating-element.ts:438
V @ lit-element.ts:61
p @ layout-card.js:1
s @ create-element-base.ts:56
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-panel-view.ts:55
value @ hui-panel-view.ts:34
performUpdate @ updating-element.ts:704
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
A @ updating-element.ts:438
i @ hui-panel-view.ts:16
value @ hui-root.ts:709
(anonymous) @ hui-root.ts:79
(anonymous) @ debounce.ts:22
setTimeout (async)
(anonymous) @ debounce.ts:27
handleEvent @ parts.ts:505
__boundHandleEvent @ parts.ts:463
a @ layout-card.js:1
(anonymous) @ layout-card.js:1
Promise.then (async)
(anonymous) @ layout-card.js:1
u @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_card @ layout-card.js:1
(anonymous) @ layout-card.js:1
build_cards @ layout-card.js:1
updated @ layout-card.js:1
performUpdate @ updating-element.ts:720
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
requestUpdate @ updating-element.ts:623
updateSize @ layout-card.js:1
firstUpdated @ layout-card.js:1
performUpdate @ updating-element.ts:718
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
initialize @ lit-element.ts:146
A @ updating-element.ts:438
V @ lit-element.ts:61
p @ layout-card.js:1
s @ create-element-base.ts:56
a @ create-element-base.ts:80
l @ create-element-base.ts:131
Tt @ create-card-element.ts:53
value @ hui-panel-view.ts:55
value @ hui-panel-view.ts:34
performUpdate @ updating-element.ts:704
_enqueueUpdate @ updating-element.ts:653
async function (async)
_enqueueUpdate @ updating-element.ts:640
_requestUpdate @ updating-element.ts:605
initialize @ updating-element.ts:449
A @ updating-element.ts:438
i @ hui-panel-view.ts:16
value @ hui-root.ts:709
(anonymous) @ hui-root.ts:79
(anonymous) @ debounce.ts:22
setTimeout (async)
(anonymous) @ debounce.ts:27
handleEvent @ parts.ts:505
__boundHandleEvent @ parts.ts:463
r @ card-mod.js:1
(anonymous) @ card-mod.js:1
Promise.then (async)
(anonymous) @ card-mod.js:1
n @ card-mod.js:1
(anonymous) @ card-mod.js:1
(anonymous) @ card-mod.js:1
hui-stack-card.ts:109 Uncaught TypeError: Cannot read property 'replaceChild' of null
at HTMLElement.value (hui-stack-card.ts:109)
at HTMLElement.t.addEventListener.once (hui-stack-card.ts:97)
at r (fire_event.ts:76)
at create-element-base.ts:94
Thanks for your work
hui-stack-card
is not me, itâs a core element (vertical-stack or horizontal-stack). Not much I can do about it.
Iâll add the divider support though, thanks for letting me know
Edit: type: divider
is not valid in a standard vertical-stack
(and this is what I use to wrap all your cards).
SeLLeRoNe
(Andrea Iannucci)
March 21, 2020, 1:43pm
10
Thanks
Thatâs odd, that error started now that Iâve added your stack-in-card, I thought it was related
Not sure to understand what fails. Could detail the problem please?
Youâll have to replace your divider with:
- type: entities
entities:
- type: divider
But there another problem by doing that which Iâm trying to fix right now
SeLLeRoNe
(Andrea Iannucci)
March 21, 2020, 1:54pm
13
Oh I see, thanks for the time youâre taking to help me with this
Knapoc
March 21, 2020, 2:03pm
14
Sorry for being vague⌠the styling is only applied on the first part (glance-card) of the card. The entities part should be in the same background-colour as the glance card
Right, Iâve seen the same thing on my side. entities
card do not keep the style. Iâm looking into this
1 Like
how come type: divider isnât valid? Or, maybe the better question would be: how come the the vertical-stack-in-card didnât throw an error on this? much friendlier to use the shorthand notationâŚ
maybe you are willing to think of that finding a solution to the problem your trying to fix now
btw, your current solution doesnât throw an error in the inspector at all, and is working just perfectly as far as we can see here.
trying to keep the background of the markdown card in the stack wont work, am I misunderstanding the --keep-background styles setting?
- type: custom:stack-in-card
cards:
- type: markdown
styles:
card:
- --keep-background: 'true'
style: |
ha-card {
background: url('/local/images/alarm_bell.png');
background-size: cover;
}
content: >
# <font color={{'green' if states('sensor.next_alarm') == 'Not set' else 'crimson'}}>Next alarm</font>
<font color={{'green' if states('sensor.next_alarm') == 'Not set' else 'crimson'}}>{{states('sensor.next_alarm_text')}}</font>
- type: entities
# title: Next alarm
show_header_toggle: false
entities:
- sensor.next_alarm_text
- sensor.time_until_next_alarm
- sensor.number_of_days_next_alarm
- sensor.next_alarm_day
- sensor.next_alarm
- entity: script.say_next_alarm
action_name: Say
- entity: script.say_next_alarm_greet
action_name: Greet
I wonât find a solution, as instead of redefining a complete new element I leverage HAâs core elements (vertical-stack and horizontal-stack) and they natively donât support divider
as a child element.
style: |
ha-card {
background: url('/local/images/alarm_bell.png');
background-size: cover;
--keep-background: 'true';
}
Of course I tried that before asking, sorry, should have mentioned. It doesnât work howeverâŚIt show what I posted above, and no error in the inspector
for reference, this is what vertical-stack-in-card makes of it:
funny enough, it doesnt complain about the --keep-background which I forgot to take out
paddy0174
(Patrick)
March 21, 2020, 3:43pm
20
@RomRider Great that you took over the card. Iâve read your comments over at GitHub. Thanks!
When youâre done with all the âmovingâ, could you please make an example for an update from vertical-stack-in-card
to stack-in-card
. Oh, and it would be great, if you could rename and clean the forked repository.
Thanks for taking action!