not good, but closer
styles:
icon:
- color: >
[[[
let rgb = states['light.wz_hue_go'].state.attributes.rgb_color || [0, 0, 0]; // [0, 0, 0] will be the default color if the attribute doesn't exist.
return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
]]]
That’s not possible, you’ll have to do it based on the state of an entity.
for that:
Good luck
- Instantiate the card:
- type: custom:button-card
template: square_media_player
entity: media_player.sonos_office_stereo
variables:
name: Sonos Office
default_background: /local/sonos_one_big.png
sonos_master: media_player.sonos_office_stereo
- Button-card templates:
square_defaults:
aspect_ratio: 1/1
styles:
card:
- padding: 9.3px
- border-radius: var(--sq-border-radius)
- font-size: 14px
- font-weight: 400
- background-clip: padding-box
- --sq-background-color: var(--sq-background-off)
- --sq-text-color: var(--sq-text-off)
- background: var(--sq-background-color)
- --sq-info-color: var(--sq-text-color)
- --sq-icon-color: var(--sq-icon-off)
- --mdc-ripple-color: var(--sq-background-on)
lock:
- justify-content: flex-end
- align-items: flex-end
icon:
- color: var(--sq-icon-color)
square_media:
template:
- square_defaults
variables:
background: |
[[[
if (entity && entity.attributes && entity.attributes.entity_picture != null) {
return entity.attributes.entity_picture;
}
]]]
default_background: /local/hifi.jpg
name: "No Name Defined"
label: "No Label Defined"
show_icon: false
show_name: true
show_state: false
extra_styles: |
span.fade {
background-image: linear-gradient(to right, var(--sq-text-color) 0%, var(--sq-text-color) 60%, rgba(0,0,0,0));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
position:relative;
display:inline-block;
width: 100%;
}
name: |
[[[
let sonos_group = "";
if (entity && entity.attributes && entity.attributes.sonos_group && entity.attributes.sonos_group.length != 1) {
sonos_group = ` (+${entity.attributes.sonos_group.length - 1})`
}
if (entity && entity.entity_id === 'media_player.sonos_universal' && states['media_player.sonos_connect'].attributes.sonos_group.length != 1) {
sonos_group = ` (+${states['media_player.sonos_connect'].attributes.sonos_group.length - 1})`
}
return `
<div style="width: auto; padding: 9.3px; background: var(--name-background);">
<span class="fade" style="text-transform: lowercase;">${variables.name}${sonos_group}</span>
<br />
<span class="fade" style="font-weight: initial;">${variables.label}</span>
</div>
`;
]]]
custom_fields:
fade: ''
media_image: ''
styles:
custom_fields:
fade:
- width: 100%
- height: 100%
- position: absolute
- z-index: 2
- border-radius: var(--sq-border-radius)
media_image:
- border-radius: var(--sq-border-radius)
- background-clip: padding-box
- top: 0
- left: 0
- position: absolute
- height: 100%
- width: 100%
- transition: background-image 1s ease-in-out, filter 1s ease-in-out
- background-size: cover
- background-position: center center
- background-repeat: no-repeat
- background-image: '[[[ return `url(${variables.background ? variables.background : variables.default_background})` ]]]'
- -webkit-transform-origin-z: 0px
- -webkit-backface-visibility: hidden
icon_image:
- position: absolute
- top: 9.3px
- left: 9.3px
- z-index: 2
- width: 14%
card:
- padding: 0
- background-clip: padding-box
- transition: 1s ease
- --name-background: linear-gradient(to top, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.6) 80%, transparent)
- -webkit-backface-visibility: hidden
name:
- text-align: start
- align-self: end
- font-weight: bold
- z-index: 3
- transition: all 1s ease
- width: 100%
square_media_player:
template: square_media
triggers_update:
- sensor.date_time
variables:
default_background: /local/hifi.jpg
is_idle: |
[[[
if (!entity.attributes.media_position_updated_at || entity.state === "playing") return false;
const diff = (Date.now() - new Date(entity.attributes.media_position_updated_at).getTime()) / 1000;
return diff > 5 * 60;
]]]
is_playing_paused: |
[[[
if (entity.state === 'playing' || entity.state === 'paused')
return true;
return false;
]]]
display_big_icon: |
[[[
if (entity.attributes.is_volume_muted)
return true;
else if (entity.attributes.media_position_updated_at) {
if (entity.state === 'playing') return false;
const diff = (Date.now() - new Date(entity.attributes.media_position_updated_at).getTime()) / 1000;
const idle = diff > 5 * 60;
if (idle)
return false;
return entity.state === "paused";
} else {
return entity.state === "paused";
}
]]]
label: |
[[[
let state = entity.state.charAt(0).toUpperCase() + entity.state.substring(1);;
let idle = false;
if (entity.attributes.media_position_updated_at && entity.state !== "playing") {
const diff = (Date.now() - new Date(entity.attributes.media_position_updated_at).getTime()) / 1000;
idle = diff > 5 * 60;
}
if (!idle && (entity.state === 'playing' || entity.state === 'paused')) {
const attr = entity.attributes;
if (attr.media_artist && attr.media_title && attr.media_album_name)
state = `${attr.media_artist} - ${attr.media_title} [${attr.media_album_name}]`
else if (attr.media_artist && attr.media_title)
state = `${attr.media_artist} - ${attr.media_title}`
else if (attr.media_title) {
// plex
if (attr.media_series_title && attr.media_season && attr.media_episode)
state = `${attr.media_series_title} - S${attr.media_season}E${attr.media_episode} - ${attr.media_title}`
else
state = `${attr.media_title}`
}
}
return state;
]]]
big_icon: |
[[[
if (entity.attributes.is_volume_muted) return "mdi:volume-off";
return "mdi:pause";
]]]
custom_fields:
big_icon: '[[[ return `<ha-icon icon="${variables.big_icon}" style="height: 100%; width: 100%"/>` ]]]'
shade: ''
styles:
custom_fields:
shade:
- border-radius: var(--sq-border-radius)
- position: absolute
- top: 0
- left: 0
- width: 100%
- height: 100%
- z-index: 1
- transition: all 1s ease
- background: |
[[[
if (variables.display_big_icon)
return "rgba(0, 0, 0, 0.6)";
return "none";
]]]
big_icon:
- position: absolute
- transition: opacity 1s ease-in-out
- top: 50%
- left: 50%
- transform: translate(-50%, -50%)
- z-index: 50
- opacity: '[[[ return variables.display_big_icon ? 1 : 0 ]]]'
- color: var(--sq-background-on)
media_image:
- background-image: |
[[[
function image(variables) {
const image = !variables.is_idle && variables.is_playing_paused ? variables.background : variables.default_background;
return image;
}
if (!variables.is_idle && variables.is_playing_paused) {
async function myFetch(elt, url, variables, hass) {
try {
await fetch(url);
new Image().src = hass.hassUrl(url);
elt.shadowRoot.getElementById('media_image').style.backgroundImage = `url(${url})`
} catch(e) {
console.log("error");
window.setTimeout(myFetch(elt, url, variables, hass), 500);
}
}
// Sometimes the image wouldn't load without all this shit below...
let url = image(variables);
if (!url) return;
myFetch(this, url, variables, hass);
return;
} else {
return `url(${variables.default_background})`
}
]]]
- filter: '[[[ if (variables.display_big_icon) return "blur(4px)"; else return null ]]]'
tap_action:
action: call-service
service: media_player.media_play_pause
service_data:
entity_id: entity
double_tap_action:
action: call-service
service: media_player.media_next_track
service_data:
entity_id: entity
- CSS Stuff included in lovelace:
html {
--sq-text-on: rgba(0, 0, 0, 0.6);
--sq-text-off: var(--paper-item-icon-color);
--sq-background-on: rgba(255, 255, 255, 0.8);
--sq-background-off: var(--paper-card-background-color);
--sq-icon-off: var(--paper-item-icon-color);
--sq-icon-on: var(--paper-item-icon-active-color);
--sq-border-radius: 10px;
}
And you’d include it like this:
lovelace:
resources:
- url: /local/square_theme.css
type: css
That line entity: "[[entity]]"
needs to be changed to entity: "[[[ return entity.entity_id ]]]"
It is only possible if you use a custom_field and build that yourself.
That is hard to achieve, using the card part. A filter will apply to the whole card and make the content also brighter or darker.
An easier way it to declare a css var which is more bright and use that variable.
Usign the fill
attribute should work if your svg supports it:
I might look into this, but I’m not sure this is a good idea.
This is how I tackled it (which is a hack )
Include this as a variable in your button (it will expand the group and the button will update if a nested entity is updated). This variable also contains the number of total entities in the group (works with nested groups also).
max: |
[[[
if (!entity) return 0;
const loop = (elt, list, max) => {
list.forEach(entity => {
if (states[entity])
if (entity.split('.')[0] === "group")
max = loop(elt, states[entity].attributes.entity_id, max);
else {
max++
if (!elt._entities.includes(entity)) elt._entities.push(entity); // This is the hack ;)
}
});
return max;
}
return loop(this, entity.attributes.entity_id, 0);
Use the timer on the button instead of the light. And adapt the button to turn on or off the light.
Is all day… i try to get the card right…i give up
3 ways to place a graph…and none works…
- type: horizontal-stack
cards:
- entities:
- sensor.0x00158d000464c4a6_humidity_3
font_size: 10px
aspect_ratio: 1/1
show_label: true
show_state: true
# size: 100%
animate: true
icon: mdi:toilet
line_color: orange
line_width: 9
type: 'custom:mini-graph-card'
style: |
ha-card {
background: rgba(10,10,10,0.7);
border-radius: 20px;
font-weight: bold;
box-shadow: none;
overflow: hidden;
position: relative;
overflow: hidden;
}
[style*="--aspect-ratio"] > :first-child {
position: absolute;
top: 0;
left: 0;
height: 100%;
}
:host {
display: block !important;
}
:element {
--aspect-ratio: 1/1;
}
name: Toilet
hours_to_show: 24
points_per_hour: 0.5
fill: false
- entities:
- sensor.0x00158d00044b3373_humidity_1
font_size: 100
aspect_ratio: 1/1
show_label: true
show_state: true
# size: 100%
animate: true
icon: mdi:sofa
line_color: blue
line_width: 9
type: 'custom:mini-graph-card'
style: |
ha-card {
background: rgba(10,10,10,0.7);
--primary-text-color: rgba(255,255,255,1.0);
border-radius: 20px;
font-weight: bold;
box-shadow: none;
overflow: hidden;
position: relative;
overflow: hidden;
}
name: Living
hours_to_show: 48
points_per_hour: 1
fill: false
- entity: sensor.0x00158d00044b3373_humidity_1
template: 'graph_button_style'
type: "custom:button-card"
icon: mdi:sofa
name: Living
and the template for the last
graph_button_style:
styles:
card:
- border-radius: 20px
# Borrar estos dos si se quiere un look menos plano
- box-shadow: none
- background-color: "rgba(10, 10, 10, 0.7)"
label:
- color: black
- font-size: 11px
- font-family: Helvetica
- padding: 10px 10px
- justify-self: start
- color: var(--primary-text-color)
state:
- font-size: 11px
- font-family: Helvetica
- padding: 0px 10px
- justify-self: start
- text-transform: capitalize
- font-weight: bold
- padding-left: 20px
- padding-bottom: 20px
- color: var(--primary-text-color)
- max-width: 75%
grid:
- grid-template-areas: '"i" "n" "graph"'
# - grid-template-columns: 1fr
# - grid-template-rows: 1fr # min-content min-content min-content
img_cell:
- justify-content: start
- align-items: start
- padding-left: 20px
icon:
- height: auto
# - padding-top: 10px
name:
- justify-self: start
- padding-left: 20px
- font-weight: bold
- font-family: Helvetica
- font-size: 13px
- padding-bottom: 3px
- color: var(--primary-text-color)
- max-width: 75%
custom_fields:
graph:
card:
type: sensor
entity: "[[[ return entity.entity_id ]]]"
graph: line
style: |
ha-card {
background: rgba(0,0,0,0);
--primary-text-color: rgba(255,255,255,1.0);
box-shadow: none;
overflow: hidden;
position: relative;
overflow: hidden;
}
:host {
display: block !important;
}
:element {
--aspect-ratio: 1/1;
}
entity: "[[[ return entity.entity_id ]]]"
hold_action:
action: more-info
and another issue with the media card… i am trying to merge 2 cards … but without success…
i cannot understand the functioning of the grid i i i n n n l l l
Trying and trying but still struggling, so please guide me what i have missed…
I want the state value to show at the bottom of the card instead of where the icon are.
My guess is the grid-template section is wrong somehow, but i cannot find what it should be.
styles:
card:
- border-radius: 15px
- height: 105px
- width: 129px
- margin: 5px 5px 0px 0px
- padding: 0px 0px
grid:
- grid-template-rows: 42px 0px auto
- grid-template-columns: 42px auto
icon:
- align-self: end
- height: 30px
- width: 30px
label:
- justify-self: start
- align-self: end
- padding: 9px 10px
- font-size: 12px
- text-transform: capitalize
name:
- justify-self: start
- padding: 0px 10px
- font-size: 13px
state:
- font-size: 11px
- font-family: Helvetica
- text-transform: capitalize
- font-weight: bold
- align-self: end
- justify-self: start
- padding: 9px 10px
Think i got it to work
hello petro
how can i change the size of this card? Tried to set the height and width but without success. Want it to be as the size above.
Ah! Perhaps this is the way to go?
- type: custom:button-card
color_type: blank-card
Can anyone tell me if its possible to make a button card like one of these examples?
I just want an entity picture that looks like its popping out
Edit: I got something not sure if I like it though.
I am loving the flexibility of the custom button card. In case it helps anyone I created a decluttering card to show the status of my ESXI VMs. The end result looks like this…
The decluttering template that goes directly into the main lovelace-ui.yaml file looks like this…
decluttering_templates:
esxi_vm_stats:
card:
type: 'custom:button-card'
entity: '[[entity_esxi]]'
name: '[[name]]'
icon: 'mdi:[[icon]]'
aspect_ratio: 1/1
styles:
card:
- background-color: '#55555544'
- border-radius: 10%
- padding: 10%
- color: ivory
- font-size: 10px
- text-shadow: 0px 0px 5px black
- text-transform: capitalize
grid:
- grid-template-areas: '"i up" "n n" "cpu cpu" "ram ram" "ip ip"'
- grid-template-columns: 1fr 1fr
- grid-template-rows: 1fr min-content min-content min-content min-content
name:
- font-weight: bold
- font-size: 13px
- color: white
- align-self: middle
- justify-self: start
- padding-bottom: 4px
img_cell:
- justify-content: start
- align-items: start
- margin: none
icon:
- color: |
[[[
if (entity.state == "running") return 'lime';
else return 'red';
]]]
- width: 70%
- margin-top: '-10%'
custom_fields:
up:
- align-self: start
- justify-self: end
cpu:
- padding-bottom: 2px
- align-self: middle
- justify-self: start
- '--text-color-sensor': '[[[ if (entity.attributes.cpu_use_pct > 80) return "red"; ]]]'
ram:
- padding-bottom: 2px
- align-self: middle
- justify-self: start
- '--text-color-sensor': >-
[[[ if (Math.round( (entity.attributes.memory_used_mb /
entity.attributes.memory_allocated_mb) * 100) > 95) return
"red"; ]]]
ip:
- align-self: left
- justify-self: start
custom_fields:
up: |
[[[
return `<ha-icon
icon="mdi:av-timer"
style="width: 12px; height: 12px; color: deepskyblue;">
</ha-icon> <span>${Math.round(entity.attributes.uptime_hours)} hours</span>`
]]]
cpu: |
[[[
return `<ha-icon
icon="mdi:server"
style="width: 12px; height: 12px; color: deepskyblue;">
</ha-icon> <span>CPU: <span style="color:white;">${entity.attributes.cpu_use_pct}%</span></span>`
]]]
ram: |
[[[
return `<ha-icon
icon="mdi:memory"
style="width: 12px; height: 12px; color: deepskyblue;">
</ha-icon> <span>RAM: <span style="color: var(--text-color-sensor);">${ Math.round((entity.attributes.memory_used_mb / entity.attributes.memory_allocated_mb) * 100) } %</span></span>`
]]]
ip: |
[[[
return `<ha-icon
icon="mdi:ip"
style="width: 12px; height: 12px; color: deepskyblue;">
</ha-icon> <span>${entity.attributes.guest_ip}</span>`
]]]
And finally the entire code block to get the final design looks like this (note the decluttering card is not used to display the information about the ESXI host itself, so the first card may look like a lot of code, but if you scroll down to the six cards below you’ll see the code is greatly simplified with the decluttering card)
type: vertical-stack
cards:
- type: 'custom:button-card'
entity: sensor.esxi_vmhost_localhost_cloudgate
name: Viper ESXI 6.7
icon: 'mdi:server'
aspect_ratio: 3/2
styles:
card:
- background-color: '#55555544'
- border-radius: 3%
- padding: 5%
- color: ivory
- font-size: 14px
- text-shadow: 0px 0px 5px black
- text-transform: capitalize
grid:
- grid-template-areas: '"i up" "n n" "cpu cpu" "ram ram" "ip ip" "ds ds"'
- grid-template-columns: 1fr 1fr
- grid-template-rows: 1fr min-content min-content min-content min-content min-content
name:
- font-weight: bold
- font-size: 20px
- color: white
- align-self: middle
- justify-self: start
- padding-bottom: 14px
img_cell:
- justify-content: start
- align-items: start
- margin: none
icon:
- color: |
[[[
if (entity.attributes.state == "poweredOn") return 'lime';
else return 'red';
]]]
- width: 30%
- margin-top: '-10%'
custom_fields:
up:
- align-self: start
- justify-self: end
cpu:
- padding-bottom: 8px
- align-self: middle
- justify-self: start
- '--text-color-sensor': '[[[ if (entity.attributes.cpu_use_pct > 80) return "red"; ]]]'
ram:
- padding-bottom: 8px
- align-self: middle
- justify-self: start
- '--text-color-sensor': >-
[[[ if (Math.round( (entity.attributes.memory_used_mb /
entity.attributes.memory_allocated_mb) * 100) > 95) return "red";
]]]
ds:
- padding-bottom: 8px
- align-self: left
- justify-self: start
custom_fields:
up: |
[[[
return `<ha-icon
icon="mdi:av-timer"
style="width: 24px; height: 24px; color: deepskyblue;">
</ha-icon> <span>${Math.round(entity.attributes.uptime_hours)} hours</span>`
]]]
cpu: |
[[[
return `<ha-icon
icon="mdi:server"
style="width: 24px; height: 24px; color: deepskyblue;">
</ha-icon> <span>CPU: <span style="color:white;">${ Math.round((entity.attributes.cpuusage_ghz / entity.attributes.cputotal_ghz) * 100) }%</span></span>`
]]]
ram: |
[[[
return `<ha-icon
icon="mdi:memory"
style="width: 24px; height: 24px; color: deepskyblue;">
</ha-icon> <span>RAM: <span style="color: var(--text-color-sensor);">${ Math.round((entity.attributes.memusage_gb / entity.attributes.memtotal_gb) * 100) } %</span></span>`
]]]
ds: |
[[[
return `<ha-icon
icon="mdi:harddisk"
style="width: 24px; height: 24px; color: deepskyblue;">
</ha-icon> <span>FREE SPACE DS1: <span style="color: var(--text-color-sensor);">${ states['sensor.esxi_datastore_datastore1'].state }GB </span>
<span>DS2: <span style="color: var(--text-color-sensor);">${ states['sensor.esxi_datastore_datastore2'].state }GB  </span>
<span>DS3: <span style="color: var(--text-color-sensor);">${ states['sensor.esxi_datastore_datastore3'].state }GB</span>`
]]]
- type: horizontal-stack
cards:
- type: 'custom:decluttering-card'
template: esxi_vm_stats
variables:
- name: Home Assistant
- icon: home-assistant
- entity_esxi: sensor.esxi_vm_home_assistant
- type: 'custom:decluttering-card'
template: esxi_vm_stats
variables:
- name: Downloader
- icon: download
- entity_esxi: sensor.esxi_vm_downloader
- type: 'custom:decluttering-card'
template: esxi_vm_stats
variables:
- name: Plex
- icon: plex
- entity_esxi: sensor.esxi_vm_plex
- type: horizontal-stack
cards:
- type: 'custom:decluttering-card'
template: esxi_vm_stats
variables:
- name: Bit
- icon: windows
- entity_esxi: sensor.esxi_vm_bit
- type: 'custom:decluttering-card'
template: esxi_vm_stats
variables:
- name: UNMS
- icon: network
- entity_esxi: sensor.esxi_vm_unms
- type: 'custom:decluttering-card'
template: esxi_vm_stats
variables:
- name: Blackhole
- icon: dns
- entity_esxi: sensor.esxi_vm_blackhole
Tell me, who understands this issue, is it possible to make a card on which the text, and then the sensor values went horizontally in one line, if possible, then with an example.
Somewhere like this: “text” + “sensor1” + “sensor2” + …
The tap action doesn’t work after HA update to 0.113.0 but hold action is working. Can anyone confirm this issue?
As I see this problem is related to the browser mod.
I only have the problem with popup card, tap and hold action are working fine for me
I believe this is new since .113 but not positive. When my color lights are set to white The icon is no longer visible. It looks like this
I’ve set the color to white.
I’ve tried
color: auto-no-temperature
as well as
color: auto (which is what it was before)
If I change to any other color, it shows the icon. Also if I reduce the brightness to lower levels, it shows as grey. in HA without a button card it shows as yellow under the same conditions.
Can you use button templates on Lovelace dashboards?
I just started with the native dashboard functionality and the exact same yaml on lovelace.yaml does not seem to work on the dashboards. I know the dashboards are not really yaml.
I get “Button-card template ‘climate_template’ is missing!”
entity: climate.bedrooms
type: 'custom:button-card'
template: climate_template
Again works in yaml, but not on dashboards.
Thoughts?
Nice, share the code, it’s especially interesting to learn about timers and the design itself
PSA:
Don’t forget to change paper-card-background-color
after updating to 0.113 if you use this style in your button templates. I only changed my themes and couldn’t work out why my buttons were looking funky.
Change what?
I updated to 0.113 and my button and titles are dis-oriented. My button when on or lit, the label disappears. When off the label appears correctly.
I’ve noticed similair issues. Not exactly the same. But my color lights, when turned on and set to 100% and to white fail to display, but in HA using a light card, display as bright yellow as expected.
Please open issues on github, else it’s hard to track. I’m going to fix CSS related issues introduced with 0.113 next week, probably
Could you please send me the link to Github to open this ticket?
Read the breaking change applicable to themes. Then as well as fixing your theme fix your button templates.This line if you have it in your button templates:
styles:
card:
- '--paper-card-background-color': 'rgba(0, 0, 0, 0)'
to:
styles:
card:
- '--ha-card-background': 'rgba(0, 0, 0, 0)'
or
styles:
card:
- '--card-background-color': 'rgba(0, 0, 0, 0)'