Thanks RomRider - very annoying, but does explain why nothing I tried worked (I should have asked yesterday and saved myself many hours!)
i tried it with
aspect_ratio: 1/0.3
color: 'rgb(47, 186, 229)'
icon: 'fas:couch'
label: >
[[[ return states['sensor.heizung_wohnzimmer_temperature'].state + 'Ā°C / ' +
states['sensor.heizung_wohnzimmer_humidity'].state + '%' ]]]
name: Wohnzimmer
show_label: true
size: 100%
styles:
img_cell:
- justify-content: start
- align-items: start
card:
- color: '#101012'
icon:
- justify-self: start
label:
- color: '#adadb7'
- font-size: 13px
- padding-top: 5px
name:
- justify-self: center
- margin-bottom: 5%
- font-size: 18px
- font-weight: bold
- font-family: 'Roboto,sans-serif'
tap_action:
action: navigate
navigation_path: /lovelace/wohnzimmer
type: 'custom:button-card'
But the icon is still centered:
Hi dave, Share your entire configuration for the button. Iāve come up with work arounds for this issue and it should work for you. I just need to see your entire button config.
as far as I understand GitHub - thomasloven/lovelace-layout-card: š¹ Get more control over the placement of lovelace cards. this works for full views, and not for a āCardā within which one needs to show aligned items in a grid? Of course, I say this without having used the layout card myself yet.
what I imagined was the button-cards-in-card to allow for a grid config, and use columns:
to determine the horizontal grid (maybe also have an āautoā settingā¦) and then show buttons in those grid positions. (which would in fact be a copy of the former tiles card)
allow for a column_span:
to have it use more than 1 position, and also use row:
and row_span:
to do the same for the vertical positioning of the buttons.
this config could then be used on a view, instead of ābeingā a view?
You can use layout-card āas a cardā also and it works great, not only āas a viewā
Hi petro - please see below. Still a bit of a work in progress. Basically I am trying to align the icon in the button-card
section, with the min details in mini-graph-card
. I know I can do it all in mini-graph-card
, but sometimes I want to show different info, or have different layouts over all, so find this the best solution given button-card
's flexibilty.
- type: custom:button-card
entity: sensor.landing_sensor_temperature
icon: mdi:thermometer
show_state: false
show_label: false
show_last_changed: false
name: Temperature
tap_action:
action: more-info
styles:
card:
- padding: 16px 1px 0px 0px
- border-right: 1px solid var(--primary-background-color)
grid:
- grid-template-areas: '"i n" "graph graph"'
- grid-template-columns: min-content 1fr
- grid-template-rows: 2em auto
img_cell:
- padding-left: 8px
# - align-self: start
# - text-align: start
- justify-content: start # horizontal
- align-items: start # vertical
- width: 40px
- height: 40px
- border: 1px dashed red
icon:
# - justify-content: start # horizontal
# - align-items: start # vertical
- height: 24px
- width: 24px
- border: 1px dashed green
name:
- padding-right: 16px
- justify-self: end
- font-size: var(--paper-font-body1_-_font-size)
- font-weight: var(--paper-font-body1_-_font-weight)
custom_fields:
graph:
card:
type: custom:mini-graph-card
entities:
- entity: sensor.landing_sensor_temperature
show:
name: false
icon: false
extrema: true
average: true
line_color: rgb(100, 149, 237)
align_state: center
line_width: 2
font_size: 75
decimals: 1
hour24: true
You can see the green border is aligned with the Min text below from mini-graph-card, but because the icon is centered its out of alignment and my OCD goes mad I can remove the padding, which will align this icon, but then when I have a full width icon, its too far left, and as my ultimate goal is to template these, I canāt be faffing with padding depending on the icon used each time.
Thanks for any help!
Ah, so what you should do is take the mini-graph-card out of the button card. Use a picture elements card and place the mini-graph-card behind the button card. Itās a complciated setup but youāll end up with a grid thatās separated from the mini-graph card. Hereās a full card that I built that uses that.
# lovelace_gen
{% set color = color|default('var(--paper-item-icon-active-color)') %}
{% set ratio = ratio|default('1/1') %}
{% set imgratio = 'transparent_' ~ 'to'.join(ratio.split('/')) ~ '.png' %}
type: picture-elements
image: /local/images/{{ imgratio }}
style: |
ha-card {
border-radius: 15px;
}
elements:
- type: custom:mini-graph-card
style:
top: 40%
left: 50%
width: 100%
height: 80%
translate: translate(-50%, -50%)
'--paper-card-background-color': 'rgba(0, 0, 0, 0.0)'
'--ha-card-background': "rgba(0, 0, 0, 0.0)"
'--ha-card-box-shadow': 'none'
z-index: 3
pointer-events: none
entities:
- {{ entity }}
group: true
points_per_hour: 1
hour24: true
line_color: {{ color }}
line_width: 10
hours_to_show: 24
update_interval: 600
show:
name: false
icon: false
state: false
points: false
legend: false
average: false
extrema: false
labels: false
fill: false
labels_secondary: false
name_adaptive_color: false
icon_adaptive_color: false
- type: custom:button-card
style:
top: 50%
left: 50%
width: 100%
translate: translate(-50%, -50%)
aspect_ratio: {{ ratio }}
entity: {{ entity }}
icon: {{ icon }}
color: var(--paper-item-icon-color)
show_name: true
show_label: true
show_icon: true
show_last_changed: true
size: 70%
tap_action:
action: more-info
haptic: light
styles:
icon:
- opacity: 0.3
- width: 100%
img_cell:
- top: 0%
- left: 30%
- position: absolute
- z-index: 2
grid:
- grid-template-areas: '"info info" "n n" "l l"'
- grid-template-columns: 40% 1fr
- grid-template-rows: 1fr min-content min-content
- position: relative
card:
- padding: 10px
- z-index: 1
name:
- justify-self: start
- align-self: end
- font-weight: bold
- font-family: Helvetica
- font-size: 12px
- text-align: start
- background-image: linear-gradient(to right, white 0%, white 80%, rgba(0,0,0,0))
- -webkit-background-clip: text
- -webkit-text-fill-color: transparent
- position: relative
- display: inline-block
- width: 100%
- align-content: start
- text-align: start
- text-overflow: unset
- z-index: 5
label:
- justify-self: start
- align-self: end
- font-weight: bold
- font-family: Helvetica
- font-size: 12px
- text-align: start
- background-image: linear-gradient(to right, var(--paper-item-icon-color) 0%, var(--paper-item-icon-color) 80%, rgba(0,0,0,0))
- -webkit-background-clip: text
- -webkit-text-fill-color: transparent
- position: relative
- display: inline-block
- width: 100%
- align-content: start
- text-align: start
- text-overflow: unset
- z-index: 5
custom_fields:
info:
- align-self: start
- width: 40%
- z-index: 5
custom_fields:
info: >
[[[
var entity_id = (entity === undefined) ? 'Invalid Entity' : entity.entity_id;
var statestr = (entity === undefined || entity.state === undefined) ? null : entity.state;
var units = (statestr && entity.attributes.unit_of_measurement) ? entity.attributes.unit_of_measurement : null;
var date = (statestr && entity.attributes.device_class === 'timestamp') ? new Date(statestr) : null;
var value;
if (statestr && date === null) {
if (statestr.split('.').length - 1 <= 1){
var test = parseFloat(parseFloat(statestr).toFixed(2));
value = (isNaN(test)) ? null : test;
// test if units are in the state because some sensors are stupid. Looking
// at you synology.
const expr = /[^-.0-9]+/;
var has_units = expr.test(statestr.trim());
// console.log(`${entity_id}: "${statestr}" ${matches}`);
if (value && has_units)
units = statestr.replace(/[.0-9]+/, '');
}
}
// console.log(`${entity_id}: ${statestr}, ${units}, ${date}, ${value}`);
const length = 50;
const width = 3;
var radius = length / 2;
if (date){
let now = new Date();
var tdelta = Math.floor((now - date)/1000);
// console.log(`${entity_id}: ${tdelta}`);
function plural(descriptor, divisor){
var ret = Math.floor(tdelta/divisor);
return (ret == 1) ? [ret, descriptor] : [ret, `${descriptor}s`];
}
var values;
if (tdelta < 60)
values = plural('second', 1);
else if (tdelta < 60 * 60)
values = plural('minute', 60);
else if (tdelta < 60 * 60 * 24)
values = plural('hour', 60 * 60);
else if (tdelta < 7 * 60 * 60 * 24)
values = plural('day', 60 * 60 * 24);
else
values = plural('week', 7 * 60 * 60 * 24);
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="${radius}" fill="{{ color }}" />
<text x="50%" y="43%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${values[0]}<tspan x="50%" dy="1.2em" font-size="10" font-weight="normal" >${values[1]}</tspan>
</text>
</svg>
`;
}
else if (value && units && units === '%') {
radius = (length - 3) / 2;
const circumference = radius * 2 * Math.PI;
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="${radius}" fill="none" stroke="var(--paper-item-icon-color)" opacity="0.5" stroke-width="${width}" />
<circle style="
transform: rotate(-90deg);
transform-origin: 50% 50%;
stroke-dasharray: ${circumference};
stroke-dashoffset: ${circumference - value / 100 * circumference};
"
id="c_brightness" cx="25" cy="25" r="${radius}" stroke="var(--paper-item-icon-active-color)" stroke-width="${width}" fill="none" stroke-linecap="round" />
<text x="50%" y="54%" fill="var(--primary-text-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan font-size="10" font-weight="normal" >%</tspan>
</text>
</svg>
`;
}
else if (value && units && units.includes('Ā°')) {
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="${radius}" fill="{{ color }}" />
<text x="50%" y="54%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan font-size="10" font-weight="normal" >${units}</tspan>
</text>
</svg>
`;
}
else if (value && units && units.length > 1) {
var y = (String(value).length > units.length) ? "50%" : "43%";
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="${radius}" fill="{{ color }}" />
<text x="50%" y="${y}" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan x="50%" dy="1.2em" font-size="10" font-weight="normal" >${units}</tspan>
</text>
</svg>
`;
}
else if (value) {
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="${radius}" fill="{{ color }}" />
<text x="50%" y="54%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan font-size="10" font-weight="normal" >${units}</tspan>
</text>
</svg>
`;
}
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="${radius}" fill="{{ color }}" />
<text x="50%" y="54%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${statestr}
</text>
</svg>
`;
]]]
Just use it as a refernce to help out your style. Thereās a few key elements that are required to make this work properly though.
-
pointer-events: none
on the mini-graph-card is required if you intend to click on the button. Otherwise youāll have ādead spotsā when clicking that do nothing. -
The man card background is the picture elements. That means that both the backgrounds for mini-graph-card and button-card must be transparent with no shadow. Thatās provided with the following styles:
'--paper-card-background-color': 'rgba(0, 0, 0, 0.0)'
'--ha-card-background': "rgba(0, 0, 0, 0.0)"
'--ha-card-box-shadow': 'none'
- Youāll need to mess with the z order. Meaning, the order in which items appear. You can put the icon BEHIND the minigraph card if you like by adjusting the z order even though they are in different cards. Z order is controlled with the property
z-index
. Keep it simple, 1 will be the lowest where N will be the highest.
Wowser! Thanks petro, I will have a proper read through that and digest, but think I get the general idea. Appreciate the help
Yes, Iāve āborrowedā these buttons and am using them. I think they are great. And once you get your head around how they work can be adjusted for almost anythingā¦
@petro, when you gave me the code you said you were tidying them all up. Did that ever get done? Iād like to see if I missed anything I can improve on.
Thatās the current version. Thereās a few issues but it should work if you use correct entity_idās.
Just in the interest of completeness - on one of my old HA installs (0.93.2) I used FontAwesome icons. I could have sworn on that install I had left aligned the icon using button-card
at some point - so I just checked, and indeed it does:
With everything that is going on with Home Assistant, I had decided to try and keep my re-install as stock as possible (that lasted all of 5 minutes!), so wanted to use mdi and not FontAwesome . Given I am already down the custom card route, I might as well give FontAwesome a try on 0.110x before I delve into petroās alternative.
I tried it several times with all your tips but the icon does not take its way to the left ;-(
Could you help me once again?
What did you wind up doing? I was just thinking about doing the same thing! Would love to see your example.
This is the code for the three buttons inside the button card
custom_fields:
down:
card:
type: 'custom:button-card'
entity: >
[[[ return entity.entity_id; ]]]
icon: 'mdi:arrow-down'
tap_action:
action: call-service
service: cover.close_cover
service_data:
entity_id: >
[[[ return entity.entity_id; ]]]
styles:
icon:
- opacity: >
[[[
if (entity.attributes.current_position > 0) return '1';
else return '0.3';
]]]
up:
card:
type: 'custom:button-card'
entity: >
[[[ return entity.entity_id; ]]]
icon: 'mdi:arrow-up'
tap_action:
action: call-service
service: cover.open_cover
service_data:
entity_id: >
[[[ return entity.entity_id; ]]]
styles:
icon:
- opacity: >
[[[
if (entity.attributes.current_position < 100) return '1';
else return '0.3';
]]]
stop:
card:
type: 'custom:button-card'
entity: >
[[[ return entity.entity_id; ]]]
icon: 'mdi:stop'
tap_action:
action: call-service
service: cover.stop_cover
service_data:
entity_id: >
[[[ return entity.entity_id; ]]]
styles:
icon:
- opacity: 1
styles:
grid:
- grid-template-areas: '"s s s s s" ". up stop down ." "n n n n n"'
- grid-template-rows: min-content 1fr min-content
- grid-template-columns: 5% 1fr 1fr 1fr 5%
Iāve just created something like that:
How I can remove unnecessary spaces between cards?
When I edit lovelace UI I can see this:
As You can see there is a lerge blank space
I donāt know hot to get rid of it.
You gotta share your config for one of those to help
If you define the width and the height of the card, thatās what you get. Better use aspect_ratio
instead.
This is an example:
type: vertical-stack
cards:
- type: 'custom:button-card'
color_type: auto
name: Rodzice
entity: sensor.temperature_158d00022c7127
show_state: true
styles:
card:
- background-color: '#000044'
- width: 165px
- height: 80px
- border-radius: 10%
- padding: 3%
- font-size: 15px
- text-shadow: 0px 0px 5px black
name:
- position: absolute
- left: 15px
- top: 15px
- font-size: 20px
icon:
- height: 25px
- position: absolute
- left: 80px
- top: 15px
- color: |
[[[
if (entity.state < 21) return 'rgb(102, 153, 255)';
if (entity.state >= 25) return 'red';
else return 'white';
]]]
state:
- position: absolute
- left: 100px
- top: 50px
- color: |
[[[
if (entity.state < 21) return 'rgb(102, 153, 255)';
if (entity.state >= 25) return 'red';
else return 'white';
]]]
custom_fields:
wilgotnosc:
- position: absolute
- left: 10px
- top: 45px
- '--text-color-sensor': >-
[[[ if (states["sensor.humidity_158d00022c7127"].state <40) return
"red"; if (states["sensor.humidity_158d00022c7127"].state >60)
return "rgb(102, 153, 255)"; else return "white" ;]]]
custom_fields:
wilgotnosc: >
[[[ return `<ha-icon icon="mdi:water-percent" style="width: 20px;
height: 20px;"></ha-icon><span style="color:
var(--text-color-sensor);">${states['sensor.humidity_158d00022c7127'].state}%</span>`
]]]
- type: horizontal-stack
cards:
- type: 'custom:button-card'
entity: light.rodzice
color_type: auto
icon: 'mdi:lamp'
name: Lampka
state:
- value: 'on'
color: red
- value: 'off'
color: white
show_last_changed: true
styles:
name:
- font-size: 80%
label:
- font-size: 60%
card:
- width: 80px
- height: 80px
- border-radius: 10%
- padding: 3%
- font-size: 15px
- text-shadow: 0px 0px 5px black
- type: 'custom:button-card'
entity: light.gateway_light_7811dc6c98d7
color_type: auto
icon: 'mdi:circle-slice-8'
name: Bramka
state:
- value: 'on'
color: red
- value: 'off'
color: white
show_last_changed: true
styles:
name:
- font-size: 80%
label:
- font-size: 60%
card:
- width: 80px
- height: 80px
- border-radius: 10%
- padding: 3%
- font-size: 15px
- text-shadow: 0px 0px 5px black
- type: horizontal-stack
cards:
- type: 'custom:button-card'
entity: binary_sensor.natgas_sensor_158d00024f11d2
color_type: auto
name: Gaz
show_state: true
show_last_changed: true
styles:
name:
- font-size: 80%
state:
- font-size: 70%
- position: relative
- left: 0%
- top: '-00%'
label:
- font-size: 60%
icon:
- color: |
[[[
if (states['binary_sensor.natgas_sensor_158d00024f11d2'].state == 'on')
return "red";
return "white";
]]]
card:
- width: 80px
- height: 80px
- border-radius: 10%
- padding: 3%
- font-size: 15px
- text-shadow: 0px 0px 5px black
- type: 'custom:button-card'
entity: binary_sensor.door_window_sensor_158d0001b706f5
color_type: auto
state:
- value: 'on'
color: red
- value: 'off'
color: white
show_last_changed: true
styles:
name:
- font-size: 80%
label:
- font-size: 60%
card:
- width: 80px
- height: 80px
- border-radius: 10%
- padding: 3%
- font-size: 15px
- text-shadow: 0px 0px 5px black
yep, as @RomRider said, youāre defining the height/width. Remove that and use the aspect ratio field.
Can You be more specific? Can You show me how to use aspect_ratio to achieve similar effect as Iāve done with width and height parameters ?