Skip to content

Instantly share code, notes, and snippets.

@Mariusthvdb
Last active December 10, 2025 16:45
Show Gist options
  • Select an option

  • Save Mariusthvdb/6e43803973505483a4d418d4e20c0a8b to your computer and use it in GitHub Desktop.

Select an option

Save Mariusthvdb/6e43803973505483a4d418d4e20c0a8b to your computer and use it in GitHub Desktop.
card-mod-themes
##########################################################################################
# https://community.home-assistant.io/t/card-mod-super-charge-your-themes/212176/419
# My 'Custom header' card-mod theme:
# - Enables individual color customization for view icons.
# - Provides an optional replacement for the default three-dots options menu.
# - Supports configuration of left-side menu icons, including animations, color schemes,
# and notification badges.
# - Allows definition of custom background images or colors to override the default
# theme background.
#
# https://community.home-assistant.io/t/card-mod-super-charge-your-themes/212176/1236
# most interface elements are now set using the new Kiosk-mode
# https://github.com/NemesisRE/kiosk-mode
# using Custom sidebar https://github.com/elchininet/custom-sidebar/discussions/163
#
# @mariusthvdb last_update 20251210
# versions:
# HA 2025.12.2
# Kiosk-mode 9.0.2
# Custom-sidebar 10.7.3
# Card_mod 4.2.0-beta1
# Fold-entity-row 2.3.2-dcapslock.3
# Auto-entities 1.16.1-dcapslock.8
#
# credits to all mentioned repo code-owners and maintainers without whom none of this
# would be possible, special thanks to @dcapslock for card-mod fixes and development of
# auto-entities and fold-entity-row
#
##########################################################################################
theme-mods:
##########################################################################################
# make the Yaml list scroll to a better height, add warning color
# https://github.com/thomasloven/lovelace-card-mod/issues/486
##########################################################################################
# requires 4.0.0
# set a color to the Reload YAML card and make it scrollable
card-mod-developer-tools-yaml: |
developer-yaml-config $ ha-card:nth-of-type(2) $: |
:host slot {
display: block;
padding-top: 5px;
height: 600px;
overflow: scroll;
color: var(--warning-color);
font-weight: 600;
}
# requires 4.0.0, test settings, not yet in use, but functional
# card-mod-config-yaml: |
# .: |
# :host {
# --app-header-background-color: orange;
# --card-background-color: orange;
# --primary-background-color: orange;
# --mdc-text-field-fill-color: lightblue;
# --mdc-select-fill-color: lightblue;
# /*--sidebar-background-color: orange;*/
# --data-table-background-color: orange;
# --primary-color: purple;
# }
# ha-config-integrations {
# --app-header-background-color: green;
# --card-background-color: green;
# --primary-background-color: green;
# --mdc-text-field-fill-color: lightorange;
# --mdc-select-fill-color: lightorange;
# --sidebar-background-color: green;
# --data-table-background-color: green;
# --primary-color: purple;
# }
# requires 4.0.0
# card-mod-top-app-bar-fixed: |
# :host {
# --app-header-background-color: orange;
# background-color: orange;
# }
# requires 4.0.0
# card-mod-developer-tools: |
# :host {
# --app-header-background-color: orange;
# --card-background-color: orange;
# --primary-background-color: orange;
# --mdc-text-field-fill-color: lightblue;
# --mdc-select-fill-color: lightblue;
# /*--sidebar-background-color: orange;*/
# --data-table-background-color: orange;
# --primary-color: purple;
# --code-editor-gutter-color: lightblue;
# }
# developer-tools-router {
# background-color: orange;
# }
# requires 4.0.0
card-mod-panel-custom-yaml: |
browser-mod-panel: |
:host {
/* --card-background-color: green;*/
/*--primary-background-color: green;*/
--mdc-text-field-fill-color: lightorange;
--mdc-select-fill-color: lightorange;
/*--sidebar-background-color: green;*/
--data-table-background-color: lightgray;
--primary-text-color: purple;
--secondary-text-color: green;
--ha-config-card-border-radius: var(--ha-card-border-radius);
}
browser-mod-panel $ ha-top-app-bar-fixed $: |
:host {
/* --app-header-background-color: green !important; */
background: var(--lovelace-background);
}
.mdc-top-app-bar__title {
color: purple;
}
#actions {
color: green !important;
}
.mdc-top-app-bar {
/*color: purple;*/
background: var(--header-background);
}
# set a left margin on all type section labels (also in folds) and align with
# fold-entity-row label margin (set in theme)
# reduce margin-top above divider to not make section above show taller than fold-entity-row height
# apply styling to the fold-entity-row icon, which now supports ripple (custom edition @dcapslock)
card-mod-row-yaml: |
.: |
:host(.type-section) .divider {
margin-top: 0px;
background-color: var(--primary-color)
}
/* stock type: section */
:host(.type-section) .label {
margin-left: var(--section-label-margin-left);
color: var(--success-color);
font-style: italic;
}
/* stock type: section inside fold-entity-row */
:host(.type-fold-entity-row-section:not([role="switch"])) .label {
text-align: center;
color: var(--info-color);
font-style: italic;
}
:host(.type-fold-entity-row-section:not([role="switch"])) .divider {
background: var(--warning-color);
}
ha-icon-button $: |
mwc-icon-button {
--mdc-ripple-color: var(--primary-color); {# defaults to color of icon, with opacity as per vars below #}
--mdc-ripple-hover-opacity: 0.2; {# defaults 0.04 #}
--mdc-ripple-focus-opacity: 0.6; {# defaults 0.12 #}
}
card-mod-glance: |
:host {
transition: none !important;
}
##########################################################################################
# make badges mask image less obtrusive
# decrease gap in header, between markdowns and badges
##########################################################################################
card-mod-view-yaml: |
:first-child $:
hui-view-header:
$: |
{# reduce gap between badges and section below #}
.layout {
gap: 8px !important;
}
{# make the overlay at the border of the scroller less obtrusive #}
.badges.scroll {
mask-image: linear-gradient(
90deg,
transparent 0%,
black 1.5%,
black 98.5%,
transparent 100%
) !important;
}
{# move badges to the left, remove bigger padding from default
in card-mod-root-yaml with ha-tab-padding-x #}
.badges-scroll hui-view-badges {
--badge-padding: 4px !important;
}
.: |
/* {# card_mod.debug #} */
{% set feest = is_state('binary_sensor.feest_alerts','on') %}
{% set seizoen = states('sensor.season_astronomical') %}
{% set donker = is_state('binary_sensor.donker_thema','on') %}
{% set extension = '_donker' if donker else '' %}
{% set path = panel.viewUrlPath %}
hui-view {
{% if path == 'welkom' %}
{% if is_state('input_boolean.home_mode_party','on') %}
background: repeat url('/local/modes/party.png');
{% endif %}
{% elif path in ['weer','buienradar','weer_cams'] %}
{% if is_state('input_boolean.weer_view_background','on') %}
background:
repeat url({{state_attr('camera.buienradar','entity_picture')}}) fixed;
{% endif %}
{% elif path in ['feest','familie_overzicht','kalender'] %}
{% if feest %} background: repeat url('/local/images/balloons.png') fixed;
{% endif %}
{% elif path == 'tijd' %}
background: repeat url('/local/season/{{seizoen}}_2.png') fixed;
{% elif path in ['onderweg','proximity'] %}
background:
center/cover no-repeat url('/local/wallpapers/map{{extension}}.png') fixed;
{% elif path == 'xbox' %}
/*background:
center/cover no-repeat url('/local/xbox/xbox-animated-background.gif') fixed;*/
{% endif %}
}
hui-view-background {
{% if path == 'plafond_spots' %}
background: center / cover no-repeat url('/local/images/areas/plafond.jpg') fixed;
filter: {{'grayscale()' if is_state('light.plafond','off') else 'none' }}
{% endif %}
}
:host {
{% set panelUrlPath = panel.panelUrlPath if 'panelUrlPath' in panel else '' %}
{% if panelUrlPath == 'ui-utiliteiten' %}
--ha-view-sections-column-max-width: 100%;
{% endif %}
}
##########################################################################################
# instead of using the theme option on a view, and set dedicated card-mod theme to the
# view, see xxx-background themes at the bottom of this file, we can now,
# (from version 4.0.0), set a generic template on the hui-view in card-mod-view-yaml
# This will be more efficient, as the modifications are less intrusive than reloading
# the full themes.
##########################################################################################
##########################################################################################
# to align notification badges on their right side (with the core notification use
# left: calc(var(--app-drawer-width,248px) - 22px);
# transform: translateX(-100%);
# -32px aligns with the middle of the core notification badge, and around that the
# translateX(-50%) centers.
# no more use of complex calculations based on string length in notification.
##########################################################################################
##########################################################################################
# most of the sidebar settings are now in custom plugin custom-sidebar
# https://github.com/elchininet/custom-sidebar
# config https://gist.github.com/Mariusthvdb/e41957dc6f66d9764e0480030c9bd386
##########################################################################################
card-mod-sidebar-yaml: |
.: |
{%- set alerts = states('sensor.marquee_alerts')|int(0) %}
{% set style_badge_not_expanded %}
position: absolute;
box-sizing: border-box;
min-width: 20px;
border-radius: 24px;
font-weight: 400;
line-height: 20px;
text-align: center;
left: 26px;
font-size: 10px;
bottom: 20px;
padding: 0px 2px;
transform: translateX(-25%);
{% endset %}
{# notification badge on collapsed menu icon #}
:host(:not([expanded])) .menu ha-icon-button:after {
content: "{{- alerts if alerts > 0 }}";
{{style_badge_not_expanded}}
color: ivory;
background: var(--alert-color);
}
ha-md-list-item$: |
{% set afval = states('sensor.afvalwijzer_vandaag')|default('Geen')|capitalize %}
{% set beweging_buiten = is_state('binary_sensor.camera_beweging_buiten','on') %}
{% set core = is_state('update.home_assistant_core_update','on') %}
{% set noti = states('sensor.config_notifications')|int(0) > 0 %}
{% set feest = is_state('binary_sensor.feest_alerts','on') %}
{% set gereed = is_state('binary_sensor.huis_ramen_deuren_puien_veilig','on') %}
{% set gevaar = is_state('binary_sensor.rook_co_lekkage','on') %}
{% set lek = is_state('binary_sensor.watermeter_leak_detected','on') %}
{% set vent = is_state('input_boolean.ventilate','on') %}
@keyframes blink { 50% { opacity: 0.2; } }
@keyframes spin { from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0% { opacity: 0.8; transform: scale(0.2); }
80% { opacity: 0; transform: scale(1.2); }
100% { opacity: 0; transform: scale(2.2); }
}
a[href='/ui-data'] {
animation: {{'blink 2.5s ease infinite' if lek else 'none'}};
}
a[href='/ui-data'] ::slotted(:is(ha-svg-icon, ha-icon)) {
animation: {{'spin 3s infinite linear' if lek else 'none'}};
}
a[href='/ui-familie'] ::slotted(:is(ha-svg-icon, ha-icon)) {
animation: {{'blink 2s ease infinite,spin 3s infinite linear' if feest
else 'none'}};
}
{# different animation when not expanded because of spinning badge #}
:host(:not([expanded])) a[href=='/ui-familie'] ::slotted(:is(ha-svg-icon, ha-icon)) {
animation: {{'blink 2.5s ease infinite' if feest else 'none'}};
}
a[href='/ui-instellingen'] ::slotted(:is(ha-svg-icon, ha-icon)) {
animation: {{'blink 2s ease infinite' if vent else 'none'}};
}
a[href='/ui-develop'] ::slotted(:is(ha-svg-icon, ha-icon)) {
animation: {{'blink 2s ease infinite' if core or noti else 'none'}};
}
a[href='/ui-cctv'] {
animation: {{'blink 2.5s ease infinite' if beweging_buiten else 'none'}};
}
##########################################################################################
# set classes for card-headers, with and without margin (used for starting entities
# cards with fold-entity-rows)
# https://community.home-assistant.io/t/card-mod-add-css-styles-to-any-lovelace-card/120744/2458
##########################################################################################
# style chips in header/footer buttons, and other places in the UI (/config settings etc)
# commenting the section below, because now too powerful for now #}
# also modifies other chips, so back to modifying individual chips in cards #}
card-mod-assist-chip: |
:host {
/*border: 1px solid var(--primary-color);
box-shadow: var(--box-shadow-chip);
--secondary-text-color: var(--primary-color);
--primary-text-color: var(--primary-color);
border-radius: var(--ha-card-border-radius) !important;
--_label-text-weight: bold !important;*/
}
.leading.icon {
/*justify-content: space-between;*/
/*margin-left: 0px;*/
}
# create 'header' like efect on the energy-distribution.
# combine with headers on all other energy cards below
card-mod-grid-section-yaml: |
.type-energy-distribution $ ha-card $: |
.card-header {
background: var(--header-background);
color: var(--text-color-off) !important;
font-size: 20px !important;
padding: 4px 12px !important;
margin: 0 0 16px 0 !important;
}
<<: &card-mod-card-yaml
card-mod-card-yaml: |
hui-buttons-header-footer:
$: |
.divider {
margin: 8px 0 0 0 !important;
}
hui-buttons-header-footer $ hui-buttons-base:
$: |
.ha-scrollbar {
justify-content: space-evenly;
height: 50px;
align-content: center;
/*margin: -16px 0px 0px 0px;*/
padding: 0 !important;
}
{# commenting the section below, because now in card-mod-assist-chip: #}
{# which is way more generic, so beware this also modifies other chips #}
ha-assist-chip {
/*border: 1px solid var(--primary-color);
border-radius: var(--ha-card-border-radius);
--secondary-text-color: var(--primary-color);
--primary-text-color: var(--primary-color);
--_label-text-weight: bold;
box-shadow: var(--box-shadow-chip);*/
}
ha-assist-chip state-badge {
/*justify-content: space-between;
margin-left: 4px;*/
}
.: |
{# create headers like on all other cards in config,
combine with grid-yaml above.
still requires text-color adjustment on the total-energy chip in header #}
:host(:is(.class-header-margin,
.type-energy-devices-graph,
.type-energy-devices-detail-graph,
.type-energy-solar-graph,
.type-energy-water-graph,
.type-energy-sources-table,
.type-power-sources-graph,
.type-energy-usage-graph,
.type-energy-gas-graph)) .card-header,
.class-header-margin .card-header {
background: var(--header-background);
color: var(--text-color-off);
font-weight: 400;
font-size: 20px;
padding: 4px 12px;
margin: 0 0 16px 0px;
}
{# also create header on date-picker,
a bit too tall because ha-card still remains #}
:host(:is(.type-energy-date-selection)) .card-content {
background: var(--header-background);
color: var(--text-color-off);
font-weight: 400;
font-size: 20px;
height: 48px !important;
padding: 0px 12px;
}
:host(:is(.type-energy-date-selection)) ha-card {
background: var(--header-background) !important;
}
{% set kerst = is_state('input_select.theme','Kerst') %}
{# https://community.home-assistant.io/t/card-mod-super-charge-your-themes/212176/2133?u=mariusthvdb #}
:host(.class-heading) .container {
background: var(--header-background);
--ha-heading-card-title-color: var(--text-color-off);
--ha-heading-card-title-font-size: 20px;
--ha-heading-card-title-font-weight: 400;
height: 48px;
padding: 0 12px;
box-shadow: var(--ha-card-box-shadow);
}
:host(.class-heading-alert) .container {
background: var(--alert-background);
--ha-heading-card-title-color: var(--alert-text-color);
--ha-heading-card-title-font-size: 20px;
--ha-heading-card-title-font-weight: 400;
height: 48px;
padding: 0 12px;
}
:host(.class-heading-no-color) .container {
--ha-heading-card-title-font-size: 20px;
--ha-heading-card-title-font-weight: 400;
height: 48px;
padding: 0 12px;
box-shadow: var(--ha-card-box-shadow);
}
:host(.class-header-icon) .card-header .icon {
padding-left: 0;
padding-right: 4px;
/* color: pink; */
}
:host(.class-header-margin) .card-header,
.class-header-margin .card-header {
background: var(--header-background);
color: var(--text-color-off);
font-weight: 400;
font-size: 20px;
padding: 4px 12px;
margin: 0 0 16px 0px;
}
/*:host(.class-header-margin) ha-card,
ha-card.class-header-margin {
box-shadow: var(--box-shadow);
}
:host(.class-header-margin) ha-card .card-content,
ha-card.class-header-margin .card-content {
max-height: {{states('input_number.max_scroll_hoogte')|int(0)}}px;
overflow-y: scroll;
overflow-x: none;
}*/
:host(.class-header-margin-no-color) .card-header {
font-weight: 400;
font-size: 20px;
padding: 4px 12px;
margin: 0 0 16px 0px;
}
:host(.class-header-no-margin) .card-header {
background: var(--header-background);
color: var(--text-color-off);
font-weight: 400;
font-size: 20px;
padding: 4px 12px;
margin: 0 0 8px 0px; {# for dcapslock fold-entity-row #}
}
:host(.class-header-no-margin-no-color) .card-header {
font-weight: 400;
font-size: 20px;
padding: 4px 12px;
margin: 0 0 8px 0px; {# for dcapslock fold-entity-row #}
}
:host(.class-clock) ha-card {
background-color: red !important;
border-radius: 20px !important;
}
:host(.type-clock) ha-card {
background-color: red !important;
border-radius: 20px !important;
}
ha-card {
transition: none !important;
overflow: {{'hidden' if is_state('input_boolean.hide_card_overflow','on')}};
background: {{'repeat url("/local/season/kerst_smurfen.png")' if kerst}};
}
{{ "ha-card::before
{
content: '';
background: top / contain no-repeat url('/local/season/snow.png');
height: 16%;
position: absolute;
left: -1%;
width: 102%;
top: -30px;
}"
if kerst}}
/* {{ "ha-card::after
{
content: '';
backdrop-filter: blur(20px);
background: top / contain no-repeat url('/local/season/lightchain.png');
height: 24%;
position: absolute;
width: 100%;
bottom: 48px;
}"
if kerst }} */
##########################################################################################
# Set the animation of the currently selected tab icon, color and icon itself are/
# set below the .: section to prevent background animation
# https://community.home-assistant.io/t/card-mod-super-charge-your-themes/212176/1094
# https://community.home-assistant.io/t/card-mod-add-css-styles-to-any-lovelace-card/120744/5174
# https://github.com/thomasloven/lovelace-card-mod/issues/268
# https://community.home-assistant.io/t/2025-5-two-million-strong-and-getting-better/886760/217?u=mariusthvdb
# https://community.home-assistant.io/t/2025-7-thats-the-question/907169/45?u=mariusthvdb
##########################################################################################
card-mod-root-yaml: |
.header: |
{# remove action buttons, except the download button in Energy panels, where
Kiosk-mode doesnt apply. Also new Home panel #}
{% set panelUrlPath = panel.panelUrlPath if 'panelUrlPath' in panel else '' %}
{% if panelUrlPath in ['energy','home'] %}
.action-items #button-0 {
display: {{'none' if is_state('input_boolean.hide_add_to_home_assistant','on')}};
}
.action-items #button-1 {
display: {{'none' if is_state('input_boolean.hide_search','on')}};
}
.action-items #button-2 {
display: {{'none' if is_state('input_boolean.hide_assistant','on')}};
}
.action-items #button-3 {
display: {{'none' if is_state('input_boolean.hide_energy_download_button','on')}};
}
{% endif %}
ha-tab-group-tab {
/*text-transform: uppercase !important;*/
}
.toolbar {
padding-left: 1px !important;
}
.header ha-tab-group$: |
wa-button[name='chevron-left'], wa-icon[name='chevron-right'] {
display: {{'none' if is_state('input_boolean.toon_chevrons','off')}};
}
{# Optionally set tab padding per device width. Only mobile. #}
@media (orientation: portrait) and (max-width: 569px) {
:host {
--ha-tab-padding-start: 0.8rem !important;
--ha-tab-padding-end: 0.8rem !important;
}
@media (min-width: 570px) {
:host {
--ha-tab-padding-start: 1.2rem !important;
--ha-tab-padding-end: 1.2rem !important;
}
ha-tab-group-tab[aria-label='Ventilatoren'] ha-icon$: |
ha-svg-icon {
transition: opacity 0.5s;
{% set vent = is_state('input_boolean.ventilate','on') %}
animation: {{'spin 1s infinite linear' if vent else 'none'}}
}
@keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(360deg);}
}
ha-tab-group-tab[aria-label='Vijver'] ha-icon$: |
ha-svg-icon {
{% set pomp = is_state('switch.vijverpompen','on') %}
animation: {{'spin 3s infinite linear' if pomp else 'none'}};
}
@keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(360deg);}
}
ha-tab-group-tab[aria-label='Weer'] ha-icon$: |
ha-svg-icon {
{% set alarm = is_state('binary_sensor.meteoalarm_brabant','on') %}
animation: {{'blink 2s ease infinite' if alarm else 'none'}};
}
@keyframes blink {
50% {opacity: 0.2;}
}
ha-tab-group-tab[aria-label='Kalender'] ha-icon$: |
ha-svg-icon {
{% set feest = is_state('binary_sensor.feest_alerts','on') %}
animation: {{'spin 3s infinite linear' if feest else 'none'}};
}
@keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(360deg);}
}
ha-tab-group-tab[aria-label='Feest'] ha-icon$: |
ha-svg-icon {
{% set feest = is_state('binary_sensor.feest_alerts','on') %}
animation: {{'spin 3s infinite linear' if feest else 'none'}};
}
@keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(360deg);}
}
ha-tab-group-tab[aria-label='Water'] ha-icon$: |
{% set lek = is_state('binary_sensor.watermeter_leak_detected','on') %}
ha-svg-icon {
animation: {{'spin 3s infinite linear' if lek else 'none'}};
}
@keyframes spin {
from {transform:rotate(0deg);}
to {transform:rotate(360deg);}
}
ha-tab-group-tab[aria-label='Samenvatting'] ha-icon$: |
ha-svg-icon {
{% set kritiek = states('sensor.hubs_samenvatting')|int(-1) > 0 or
states('sensor.kritieke_schakelaars_samenvatting')|int(-1) > 0 %}
animation: {{'pulse 2s ease 0s infinite normal' if kritiek else 'none'}};
}
@keyframes pulse {
0% {opacity: 0.8;transform: scale(0.2);}
80% {opacity: 0;transform: scale(1.2);}
100% {opacity: 0;transform: scale(2.2);}
}
.: |
{# center the view tabs when in potrait mode to make 1 column visually #}
@media (orientation: portrait) or (max-width: 850px) {
.toolbar ha-tab-group::part(tabs) {
justify-content: center;
}
}
{% set kerst = is_state('input_select.theme','Kerst') %}
{% set feest = is_state('binary_sensor.feest_alerts','on') %}
{% set lek = is_state('binary_sensor.watermeter_leak_detected','on') %}
{% set vent = is_state('input_boolean.ventilate','on') %}
{% set pomp = is_state('switch.vijverpompen','on') %}
{% set netto = states('sensor.netto_verbruik')|int(0) %}
{% set meteo = is_state('binary_sensor.meteoalarm_brabant','on') %}
{% set alerts = states('sensor.alerts_notifying')|int(0) > 0 %}
{% set motion = is_state('binary_sensor.motion_sensors_all','on') %}
{% set symbol = states('sensor.buienradar_symbol') %}
{% set temp = states('sensor.ws_5500_outdoor_temperature')|default(-100) %}
{% set template = is_state('input_boolean.menu_options_template','on') %}
{% set wekker = is_state('binary_sensor.wekker_voor_morgen','on') %}
{% set donker_thema = is_state('binary_sensor.donker_thema','on') %}
{% set verwarming = is_state('binary_sensor.opentherm_heating','on') or
is_state('binary_sensor.mill_heater_aan','on') %}
{# Hide the first button +, now in Kiosk-mode #}
/* ha-button-menu:nth-of-type(1) {
display: none;
} */
{# Set the three-dots transparency, to allow replacement template text #}
ha-button-menu:nth-of-type(2) ha-icon-button {
color: {{'transparent' if template}};
pointer-events: {{'none' if template}};
display: inline-flex; {# required in Safari to center the text, Chrome ok without #}
cursor: context-menu; {# set here, because doesnt work in the ::after pseudo-element below #}
/* background: yellow; */ {# test to see the element #}
}
{# Optionally set a replacement template text #}
ha-button-menu:nth-of-type(2) ha-icon-button::after {
content: "{%- set sym = symbol|truncate(21,False,'') -%}
{%- if template -%} {{- sym}} | {{temp}} °C
{%- endif -%}";
color: {{'var(--app-header-text-color)' if donker else 'var(--primary-color)'}};
/* visibility: visible; */ {# no longer required? #}
/* position: absolute; */ {# no longer required? #}
pointer-events: auto;
/* cursor: context-menu; */ {# doesnt work here, so set it in actual element above... #}
/* right: 0;*/ {# no longer required? #}
align-self: center;
/* white-space: nowrap; */ {# no longer required? #}
/* background: orange; */ {# test to see the element #}
}
{# Set the toolbar background and generic icon color #}
.header, .toolbar {
background: {%- if kerst -%} url('/local/wallpapers/snow.mp4')
{%- elif donker_thema -%} var(--lovelace-background)
{%- else -%} var(--header-background);
{%- endif -%};
color: var(--app-header-text-color);
}
ha-tab-group-tab:hover {
--icon-primary-color: var(--primary-color);
background: var(--lovelace-background);
}
{# Set the color of the currently selected tab
Set size of the currently selected tab icon #}
ha-tab-group-tab[aria-selected=true] {
--ha-tab-active-text-color: oklch(from var(--primary-color) calc(l + .5) c h);
border: 1px solid var(--primary-color);
/*background: var(--lovelace-background);*/
--mdc-icon-size: {{states('input_number.active_icon_size')|int(24)}}px;
height: calc(var(--header-height) - 2px);
display: flex;
}
{# This hides the help button when in edit mode #}
a.menu-link[target='_blank'] {
{% if is_state('input_boolean.hide_edit_mode_help','on') %}
visibility: hidden;
margin-right: -30px;
{% endif %}
}
{# Dynamically set the color and icons of individual tabs #}
ha-tab-group-tab[aria-label='Wekker instellingen'] {
color: {{'var(--alert-color)' if wekker else 'var(--success-color)'}};
}
ha-tab-group-tab[aria-label='Welkom'] {
--card-mod-icon: {{'mdi:home-alert' if alerts }};
/* background: url('/local/devices/hue_home.png'); */
color: {{'var(--alert-color)' if alerts else 'var(--success-color)'}};
}
ha-tab-group-tab[aria-label='Samenvatting'] {
{%- if states('sensor.hubs_samenvatting')|int(-1) > 0 or
states('sensor.kritieke_schakelaars_samenvatting')|int(-1) > 0 %}
--card-mod-icon: mdi:alert;
color: var(--alert-color);
{%- endif %}
}
ha-tab-group-tab[aria-label='Beweging'] {
--card-mod-icon: {{'mdi:motion-sensor' if motion}};
color: {{'var(--alert-color)' if motion}};
}
ha-tab-group-tab[aria-label='Alarm'] {
--card-mod-icon: {{states('sensor.alarm_panel_icon')|default('mdi:help')}};
color: {{states('sensor.alarm_panel_icon_color')|default('pink')}};
}
ha-tab-group-tab[aria-label='Verwarming'] {
--card-mod-icon: mdi:{{'radiator' if verwarming else 'radiator-off'}};
color: {{'var(--alert-color)' if verwarming}};
}
ha-tab-group-tab[aria-label='Frontend'] {
/*--card-mod-icon-color: url('/local/gradients/gradients.svg#linearBackgroundLight');
background: var(--rainbow-radial);
/* Clip the background to the text shape */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;*/
}
ha-tab-group-tab[aria-label='Updates'] {
{%- set update = integration_entities('hacs')
|select('search','update.')
|select('is_state','on')|list|count > 0 or
is_state('update.home_assistant_core_update','on') %}
--card-mod-icon: mdi:package{{'-up' if update}};
color: {{'var(--alert-color)' if update }};
}
ha-tab-group-tab[aria-label='Kalender'] {
--card-mod-icon: {{'mdi:party-popper' if feest}};
color: {{'var(--warning-color)' if feest else
states('sensor.afval_kleur') if states('sensor.afval_kleur') != 'gray'
else 'var(--alert-color)' if wekker}};
}
ha-tab-group-tab[aria-label='Familie overzicht'] {
color: {{states('sensor.presence_color')|default('pink')}};
}
ha-tab-group-tab[aria-label='Feest'] {
color: {{'var(--warning-color)' if feest}};
}
ha-tab-group-tab[aria-label='Klimaat'] {
color: {{states('sensor.inside_temperature_color_name')|default('pink')}};
}
ha-tab-group-tab[aria-label='Rolluiken'] {
--card-mod-icon: mdi:window-shutter{{'-alert' if
not has_value('cover.slaapkamers')
else '-open' if is_state('cover.slaapkamers','open')}};
}
ha-tab-group-tab[aria-label='Verlichting'] {
{% set lampen = states('sensor.lampen_samenvatting')|int(-1) %}
--card-mod-icon: mdi:lightbulb-group{{'-off' if lampen == 0 }};
color: {{'var(--active-color)' if lampen > 0 }};
/* background: {{'var(--hover-color)' if lampen > 0 }}; */
}
ha-tab-group-tab[aria-label='Weer'] {
--card-mod-icon: {{states('sensor.meteoalarm_icon')
if meteo else states('sensor.weather_icon')}};
color: {{'var(--alert-color)' if meteo else
states('sensor.temperature_color_name')}};
}
ha-tab-group-tab[aria-label='Energie'] {
color: {{'brown' if netto >= 0 else 'var(--power-color)'}};
}
ha-tab-group-tab[aria-label='Zonne-energie'] {
color: {{'var(--power-color)' if netto < 0}};
}
ha-tab-group-tab[aria-label='Water'] {
--card-mod-icon: {{'mdi:pipe-leak' if lek}};
color: {%- if lek %} var(--alert-color)
{%- elif is_state('binary_sensor.watermeter_update_available','on') %}
blue
{%- endif %};
}
ha-tab-group-tab[aria-label='Ventilatoren'] {
color: {{'var(--alert-color)' if vent }};
}
ha-tab-group-tab[aria-label='Vijver'] {
color: {{'lightseagreen' if pomp}};
}
ha-tab-group-tab[aria-label='Tijd'] {
--card-mod-icon: {{state_attr('sensor.hour_icon','icon')}};
color: {{'var(--state-sun-below_horizon-color)'
if is_state('binary_sensor.donker_buiten','on') else
'deepskyblue'}};
}
ha-tab-group-tab[aria-label='Home Assistant'] {
color: var(--ha-color);
}
##########################################################################################
# modify the more-info dialog, breadcrumbs and set a blur
##########################################################################################
card-mod-more-info-yaml: |
ha-dialog-header: |
{# adding this, because Kiosk-mode does not apply to /config dashboards #}
.breadcrumb {
{% if is_state('input_boolean.hide_dialog_header_breadcrumb_navigation','on') %}
display: none !important
{% endif %};
}
ha-more-info-info $ more-info-content $:
more-info-input_boolean,more-info-switch,more-info-siren $:
ha-state-control-toggle $: |
ha-control-switch {
--control-switch-border-radius: var(--border-radius-square) !important;
--control-switch-thickness: var(--more-info-control-thickness) !important;
}
more-info-fan $:
ha-control-select-menu $: |
.select-anchor {
border-radius: var(--border-radius-square) !important;
}
ha-state-control-fan-speed $: |
ha-control-slider {
--control-slider-border-radius: var(--border-radius-square) !important;
--control-slider-thickness: var(--more-info-control-thickness) !important;
}
ha-state-control-fan-speed $ ha-control-slider $: |
.slider .slider-track-bar::after {
border-radius: var(--border-radius-square) !important; /* --slider-track-bar-border-radius*/
}
.tooltip {
border-radius: var(--border-radius-square) !important;
background: var(--card-background-color) !important;
/*color: var(--primary-text-color) !important;*/
}
more-info-alarm_control_panel $:
ha-state-control-alarm_control_panel-modes $: |
ha-control-select {
--control-select-border-radius: var(--border-radius-square) !important;
--control-select-thickness: var(--more-info-control-thickness) !important;
}
more-info-cover $:
ha-state-control-cover-position $: |
ha-control-slider {
--control-slider-border-radius: var(--border-radius-square) !important;
--control-slider-thickness: var(--more-info-control-thickness) !important;
}
ha-state-control-cover-position $ ha-control-slider $: |
.slider .slider-track-bar::after {
border-radius: var(--border-radius-square) !important; /* --slider-track-bar-border-radius*/
}
.tooltip {
border-radius: var(--border-radius-square) !important;
background: var(--card-background-color) !important;
/*color: var(--primary-text-color) !important;*/
}
more-info-light $:
ha-state-control-light-brightness $: |
ha-control-slider {
--control-slider-border-radius: var(--border-radius-square) !important;
--control-slider-thickness: var(--more-info-control-thickness) !important;
}
ha-state-control-light-brightness $ ha-control-slider $: |
.slider .slider-track-bar::after {
border-radius: var(--border-radius-square) !important;
}
.tooltip {
border-radius: var(--border-radius-square) !important;
background: var(--card-background-color) !important;
/*color: var(--primary-text-color) !important;*/
}
light-color-rgb-picker $: |
.native-color-picker {
color: var(--primary-color) !important;
}
light-color-temp-picker $: |
ha-control-slider {
--control-slider-border-radius: var(--border-radius-square) !important;
--control-slider-thickness: var(--more-info-control-thickness) !important;
/*--control-slider-background: red !important;
--control-slider-color: red !important;*/
}
light-color-temp-picker $ ha-control-slider $: |
.slider {
--handle-size: 4px;
}
.slider .slider-track-cursor {
--cursor-size: 14px !important;
/*background: yellow !important;*/
}
.slider .slider-track-cursor::after {
border-radius: var(--border-radius-square) !important;
}
.tooltip {
border-radius: var(--border-radius-square) !important;
background: var(--card-background-color) !important;
/*color: var(--primary-text-color) !important;*/
}
ha-control-select-menu $: |
.select-anchor {
border-radius: var(--border-radius-square) !important;
}
$: |
.mdc-dialog {
backdrop-filter: blur(17px) !important;
-webkit-backdrop-filter: blur(17px) !important;
}
.mdc-dialog .mdc-dialog__content {
/*padding: var(--dialog-content-padding, 24px);*/
}
##########################################################################################
# modify ha-dialog, ha-md-dialog, ha-wa-dialog (will be some in 2025.11) or ha-drawer
# card-mod theme variable is card-mod-dialog and class applied to dialog element is the
# parent element with any ha- stripped off, then prefix with type (similar to cards).
# e.g. hui-dialog-create-card will have class type-dialog-create-card.
##########################################################################################
card-mod-dialog-yaml: |
$: |
:host(.type-dialog-box) wa-dialog::part(dialog)::backdrop {
backdrop-filter: blur(17px); /* blurs whole screen background */
}
{% set donker = is_state('binary_sensor.donker_thema','on') %}
{% set titel = params.title if 'title' in params else '' %}
{% set ha = titel == 'Home Assistant herstarten?' %}
{% set sy = titel =='Systeem herstarten?' %}
{% set bkgrnd = 'var(--background-color-off)' if donker else
'var(--card-background-color)' %}
:host(.type-dialog-box) wa-dialog::part(dialog) {
background:
{% if ha %} linear-gradient(90deg, var(--warning-color) 0%, var(--primary-color) 100%);
{% elif sy %} linear-gradient(90deg, var(--error-color) 0%, var(--primary-color) 100%);
{% else %} var(--lovelace-background-linear);
{% endif %};
/*{% if ha %} var(--warning-color)
{% elif sy %} var(--error-color)
{% else %} {{bkgrnd}}
{% endif %};*/
--primary-text-color:
{% if ha %} white
{% elif sy %} black
{% else %}
{{'var(--text-color-off)' if donker else 'var(--primary-text-color)'}}
{% endif %};
box-shadow: var(--box-shadow);
}
:host(.type-dialog-restart) {
--card-background-color: none;
--input-fill-color: none;
}
:host(.type-dialog-restart) wa-dialog::part(dialog) {
background: var(--lovelace-background-linear);
}
.: |
.type-quick-bar {
--mdc-theme-surface: var(--header-background);
max-height: {{states('input_number.max_scroll_hoogte')|int(300)}}px;
}
# no longer use below, as al moved to the main dialog modification
# {% set donker = is_state('binary_sensor.donker_thema','on') %}
# {# card_mod.debug #}
# ha-wa-dialog {
# /*--card-background-color: linear-gradient(90deg,rgba(42, 123, 155, 1) 0%, rgba(87, 199, 133, 1) 50%, rgba(237, 221, 83, 1) 100%);*/
# }
# {% set titel = params.title if 'title' in params else '' %}
# /*{% if titel == 'Home Assistant herstarten?' %}
# ha-wa-dialog.type-dialog-box {
# --card-background-color: var(--warning-color);
# {% elif titel == 'Systeem herstarten?' %}
# ha-wa-dialog.type-dialog-box {
# --card-background-color: var(--alert-color);
# }
# {% endif %}*/
#
# {% set titel = params.title if 'title' in params else '' %}
# {% set ha = titel == 'Home Assistant herstarten?' %}
# {% set sy = titel =='Systeem herstarten?' %}
# {% set bkgrnd = 'var(--background-color-off)' if donker else
# 'var(--card-background-color)' %}
# ha-wa-dialog.type-dialog-box {
# --card-background-color:
# {% if ha %} var(--warning-color)
# {% elif sy %} var(--error-color)
# {% else %} {{bkgrnd}}
# {% endif %};
# --primary-text-color:
# {% if ha %} black
# {% elif sy %} white
# {% else %}
# {{'var(--text-color-off)' if donker else 'var(--primary-text-color)'}}
# {% endif %};
# }
# below background themes no longer used, because with card-mod 4.0.0 we can set
# modifications to the Panel variable like panel.viewUrlPath directly
# see: https://github.com/thomasloven/lovelace-card-mod/tree/v4.0?tab=readme-ov-file#templates
# without anything further, these themed backgrounds break primary-text-color and
# secondary-text-color in themes, because they need to have anything from the base themes
# in the theme itself.
# It does not cascade (or inherit), it gets replaced. Remember this is a view and
# not the document.
# So explicitly declaring them again in the mod themes fixes that
# thanks @dcapslock for helping me out here
# weather-background:
# card-mod-theme: weather-background
# <<: *card-mod-card-yaml
# card-mod-view: |
# {# card_mod.debug #}
# hui-view {
# {% if is_state('input_boolean.weer_view_background','on') %}
# background: repeat url({{state_attr('camera.buienradar','entity_picture')}}) fixed;
# {% endif %}
# }
# <<: &prim_sec
# primary-text-color: var(--primary-text-color)
# secondary-text-color: var(--secondary-text-color)
#
# feest-background:
# card-mod-theme: feest-background
# <<: *card-mod-card-yaml
# card-mod-view: |
# {% set feest = is_state('binary_sensor.feest_alerts','on') %}
# hui-view {
# {% if feest %} background: repeat url('/local/images/balloons.png') fixed;
# {% endif %}
# }
# <<: *prim_sec
#
# seizoen-background:
# card-mod-theme: seizoen-background
# <<: *card-mod-card-yaml
# card-mod-view: |
# hui-view {
# {% set seizoen = states('sensor.season_astronomical') %}
# background: repeat url('/local/season/{{seizoen}}_2.png') fixed;
# }
# <<: *prim_sec
#
# map-background:
# card-mod-theme: map-background
# <<: *card-mod-card-yaml
# card-mod-view: |
# hui-view {
# background:
# {% set donker = is_state('binary_sensor.donker_thema','on') %}
# {% set extension = '_donker' if donker else '' %}
# center/cover no-repeat url('/local/wallpapers/map{{extension}}.png') fixed;
# }
# <<: *prim_sec
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment