-
-
Notifications
You must be signed in to change notification settings - Fork 0
Variables
Variables are the holes in a template. You write [[name]] in the template, and pass a
value for name when you use it.
decluttering_templates:
room_light:
card:
type: tile
entity: '[[light]]'
name: '[[room]]'type: custom:decluttering-card-plus
template: room_light
variables:
- light: light.kitchen
- room: KitchenA placeholder is a name in double square brackets: [[light]], [[room]], [[accent]].
When a placeholder is the whole value, quote it.
entity: '[[light]]' # ✅
entity: [[light]] # ❌ not valid YAML - "[" starts a listInside a longer string, quotes are optional but harmless.
name: [[room]] light'
title: Lights in [[room]]Placeholders work anywhere in the content — keys' values, nested mappings, list items,
even inside CSS in a style block. They are substituted throughout the whole
template body.
variables: on the card can be written either way. A list, one name per entry:
variables:
- light: light.kitchen
- room: Kitchenor a single mapping:
variables:
light: light.kitchen
room: KitchenBoth are read the same way, here and in a template's default:. The list form is what the
visual editor writes, so a card edited there comes out as a list whichever
way you typed it.
default: on the template supplies fallbacks, so callers only pass what differs.
decluttering_templates:
area_sensor:
card:
type: tile
entity: '[[entity]]'
name: '[[label]]'
icon: '[[icon]]'
default:
- label: [[area]] temperature'
- area: Living Room
- entity: sensor.living_room_temperature
- icon: mdi:thermometerUsed with no variables at all, it renders entirely from the defaults. Override one, and only that one changes:
# 1. nothing passed - pure defaults
- type: custom:decluttering-card-plus
template: area_sensor
# 2. override the area, and the label follows
- type: custom:decluttering-card-plus
template: area_sensor
variables:
- area: Bedroom
- entity: sensor.bedroom_temperature
# 3. override the label outright
- type: custom:decluttering-card-plus
template: area_sensor
variables:
- label: Solar output right now
- entity: sensor.solar_power
- icon: mdi:solar-power
default: uses the same shape as variables: — a list, or a single mapping.
The default values are also what the visual editor uses to draw its
preview, so giving every variable a sensible default makes templates much nicer to work on.
A template can go further and describe each variable — a label, a helper line and a Home Assistant selector — so that cards using it get a real entity picker or dropdown instead of a YAML box, and so the editors can warn about variables that are missing or unused. See Describing Variables.
A default can contain placeholders of its own. Above, label defaults to
[[area]] temperature', so changing area changes the label without the caller ever
mentioning label.
Substitution repeats until nothing is left to replace, so the order you declare them in does not matter, and a value you pass always beats a default — including when the placeholder only appears because of an earlier substitution.
This also gives you "fall back to another variable":
default:
- title: '[[name]]' # if no title is given, use the name
- name: SensorA variable that refers to itself can never be resolved. Substitution gives up after 10 passes and logs a warning to the browser console rather than hanging:
decluttering-card-plus: gave up substituting variables after 10 passes.
Check whether a variable refers to itself.
Ten passes is far more than any sane template needs — chains that deep are fine, cycles are not.
A placeholder can ask for its value written differently, which lets one variable serve both a room's name and the entity id built from it:
decluttering_templates:
room_tile:
card:
type: tile
entity: 'light.[[room|slug]]'
name: '[[room|title]]'
default:
- room: Back Gardenlight.[[room|slug]] becomes light.back_garden, and [[room|title]] becomes
Back Garden. Pass room: John's Shed and you get light.john_s_shed without the caller
ever mentioning the entity id.
| Transform | Does |
John's Back Garden becomes |
|---|---|---|
slug |
Lower case; anything that is not a letter or digit becomes _
|
john_s_back_garden |
upper |
Upper case | JOHN'S BACK GARDEN |
lower |
Lower case | john's back garden |
title |
Capitalises each word | John's Back Garden |
The same variable can be used raw and transformed in the same template.
A transform is a way of writing a value out, not a way of choosing it, so a transformed placeholder is always text. That makes it a tool for scalars: a number transforms as its digits, but a mapping or a list under a transform is left unsubstituted — slugging or uppercasing its JSON would only garble it, so the placeholder stays visible instead.
Only those four are transforms. A word after the bar that is not one of them is not recognised, so nothing is substituted and you are left looking at
[[room|shout]]in the card. That is deliberate: a silent empty string would be far harder to spot.
How a value is substituted depends on where the placeholder sits.
The type is preserved. Numbers stay numbers, booleans stay booleans, and mappings and lists are inserted as structure.
decluttering_templates:
sized_tile:
card:
type: tile
entity: '[[entity]]'
name: '[[name]]'
grid_options:
columns: '[[cols]]' # whole value
rows: 1variables:
- cols: 12 # inserted as the number 12, not "12"
This matters: columns: "12" would be a string and Home Assistant would ignore it.
The same applies to structures:
card:
type: tile
entity: '[[entity]]'
features: '[[features]]'variables:
- features:
- type: toggle
- type: light-brightnessand to booleans and null:
variables:
- show_name: true
- icon: nullThe value is inserted as text.
name: [[room]] light'With room: Kitchen this becomes Kitchen light. A mapping or list used this way is
inserted as its JSON text, which is occasionally useful and usually not what you want.
Values containing quotes, backslashes, newlines or tabs are escaped correctly. So multi-line values and Jinja templates work:
variables:
- message: >-
Line one
Line two
- jinja: "{{ states('sensor.x') | float * 2 }}"Values containing $& or $1 are inserted literally rather than being interpreted as
replacement patterns, and variable names containing regex characters are matched
literally too.
If a placeholder has no matching variable and no default, it is left in place. You will
see the literal text [[light]] in the rendered card, or Home Assistant complaining about
an unknown entity called [[light]].
That is the number one symptom of a typo in a variable name. See Troubleshooting.
You will also see this in the visual editor while editing a template — the card editor there is looking at the raw template, so it reports
[[light]]as an unknown entity. That is expected and harmless.
| Where | Example | Result |
|---|---|---|
| Whole value, string |
entity: '[[e]]' with e: light.x
|
light.x |
| Whole value, number |
columns: '[[c]]' with c: 12
|
12 (number) |
| Whole value, boolean |
show: '[[s]]' with s: true
|
true (boolean) |
| Whole value, mapping/list | features: '[[f]]' |
inserted as structure |
Whole value, null
|
icon: '[[i]]' with i: null
|
null |
| Inside a string |
name: [[r]] light' with r: Hall
|
Hall light |
| No such variable | entity: '[[nope]]' |
left as [[nope]]
|
| Transform | Example | Result |
|---|---|---|
slug |
`'light.[[r | slug]]'withr: Back Garden` |
upper / lower
|
`'[[r | upper]]'withr: Hall` |
title |
`'[[r | title]]'withr: back garden` |
| Not a transform | `'[[r | shout]]'` |
| Shape | Read as |
|---|---|
- light: light.x per line |
one variable per entry |
light: light.x in a mapping |
one variable per key |
| An entry with several keys | one variable per key |
| Precedence | Winner |
|---|---|
variables on the instance vs any default |
variables |
default inside a declaration vs the default: list |
the declaration |
| Same key twice in one list | the first one |
→ Describing Variables to give them labels, pickers and warnings → Repeating a Template to render one template once per item → Cards · Badges · Rows · Elements → Recipes for finished examples
Getting started
Core concepts
Content types
Features
- Repeating a Template
- Sharing Between Dashboards
- Sharing a Template
- Visibility
- Styling
- Visual Editors
- Translations
Reference