Templates
All styles may contain jinja2 templates that will be processed by the Home Assistant backend.
UI eXtension also makes the following variables available for templates:
config- The entire configuration of the card, entity or badge - (config.entitymay be of special interest)user- The name of the currently logged in userbrowser- Thebrowser_idof your browser, if you have browser_mod installedhash- Whatever comes after#in the current URL. UIX watches for location changes throughlocation-changedandpopstateevents so templates will be rebound with the updatedhashpanel- various information about the panel in view, be it a lovelace dashboard or another panel view.panelis a dictionary containing the following panel attributes with example values shown.panel.fullUrlPath: "uix/another-test-view"panel.panelComponentName: "lovelace"panel.panelIcon: "mdi:card-bulleted-outline"panel.panelNarrow: truepanel.panelRequireAdmin: falsepanel.panelTitle: "UIX"panel.panelUrlPath: uix"panel.panelTitle: "UIX - Test View"panel.viewNarrow: truepanel.viewTitle: "Test View"panel.viewUrlPath: "another-test-view"
You can debug UIX jinja2 templates by placing the comment {# uix.debug #} anywhere in your template. You will see debug messages on template binding, value updated, reuse, unbinding and final unsubscribing. Any template is kept subscribed in cache for a 20s cooldown period to assist with template application, which can bring a slight speed improvements when switching back and forth to views, or using the same template on cards on different views.
Macros
UI eXtension supports reusable Jinja2 macros that can be defined at card level or via a theme, and are prepended to every template in the card.
Defining macros on a card
Macros are defined under uix.macros in the card configuration. A macro without returns renders its template inline as a string — use this when you want to substitute a text value (such as a CSS color or icon name) directly into the template:
type: tile
entity: light.living_room
uix:
macros:
state_color:
params:
- entity_id
- name: color_on
default: "'yellow'"
- name: color_off
default: "'gray'"
template: "{{ color_on if is_state(entity_id, 'on') else color_off }}"
style: |
ha-card {
background: {{ state_color(config.entity) }};
}
Each macro entry supports the following keys:
| Key | Required | Description |
|---|---|---|
template |
Yes | The Jinja2 template body of the macro. |
params |
No | A list of parameters the macro accepts. Each entry is either a plain string (parameter name) or a mapping with name and default keys (see below). |
returns |
No | Set to true to make the macro callable as a function using Home Assistant's as_function filter. When true, use {%- do returns(<value>) -%} inside the template to return a typed value (boolean, number, etc.). |
Each item in params can be either:
- A plain string — just the parameter name:
- entity_id - A mapping with
nameanddefault— the parameter name and its Jinja2 default expression:
params:
- entity_id
- name: color_on
default: "'yellow'"
- name: color_off
default: "'gray'"
This generates the following Jinja2 macro signature:
{% macro state_color(entity_id, color_on = 'yellow', color_off = 'gray') %}
{{ color_on if is_state(entity_id, 'on') else color_off }}
{% endmacro %}
The default value is injected verbatim as a Jinja2 expression. Quote string values with single quotes inside the YAML string (e.g. "'yellow'").
Macros with returns
When a macro renders inline (no returns), its output is always a string — even {{ is_state(entity_id, "on") }} produces the string "True" or "False", and any non-empty string is truthy in Jinja2. To return an actual boolean or numeric value that behaves correctly in conditionals and comparisons, use returns: true.
When returns: true, the macro follows Home Assistant's as_function convention: the macro is internally named macro_<name> with returns added as its last parameter, then exposed as <name> via the as_function filter. The returns callable is injected automatically when the macro is invoked as a function:
type: tile
entity: light.living_room
uix:
macros:
is_on:
params:
- entity_id
returns: true
template: "{%- do returns(is_state(entity_id, 'on')) -%}"
style: |
ha-card {
--tile-color: {{ 'yellow' if is_on(config.entity) else 'gray' }};
}
This generates the following Jinja2 block that is prepended to every template:
{% macro macro_is_on(entity_id, returns) %}
{%- do returns(is_state(entity_id, 'on')) -%}
{% endmacro %}
{% set is_on = macro_is_on | as_function %}
Importing macros from custom template files
In addition to defining macros inline, you can import macros from Home Assistant reusable templates stored in /config/custom_templates/*.jinja. To do this, set the macro entry's value to the filename (a plain string) instead of a macro definition object:
type: tile
entity: light.living_room
uix:
macros:
state_color: "my_macros.jinja"
style: |
ha-card {
background: {{ state_color(config.entity) }};
}
This generates the following import statement that is prepended to every template:
{% from 'my_macros.jinja' import state_color %}
The macro state_color must be defined in /config/custom_templates/my_macros.jinja. Each entry in macros imports its own named macro, so you can import multiple macros from the same or different files:
uix:
macros:
state_color: "my_macros.jinja"
is_on: "my_macros.jinja"
format_date: "utils.jinja"
Using template file macros
All template files must have the .jinja extension and be less than 5MiB. Templates in the /config/custom_template folder will be loaded at Home Assistant startup. To reload the templates without restarting Home Assistant, invoke the homeassistant.reload_custom_templates action.
Inline and file-import macros can be freely mixed within the same card.
Theme macros
Macros can also be defined in a theme so they are available to all cards that use it. See Themes - Macros for details.
Card-level macros take precedence over theme macros of the same name, allowing individual cards to override theme-defined macros.