Skip to content

Variables

tempus2016 edited this page Aug 18, 2026 · 7 revisions

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: Kitchen

Writing placeholders

A 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 list

Inside 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.

Passing values

variables: on the instance is a list, one key per entry:

variables:
  - light: light.kitchen
  - room: Kitchen

Default values

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:thermometer

Used 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

Three cards from one template showing defaults, partial override and full override

default: uses the same list-of-mappings shape as variables:.

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.

Defaults that reference other 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: Sensor

Loops

A 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.


Value types

How a value is substituted depends on where the placeholder sits.

The placeholder is the entire value

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: 1
variables:
  - cols: 12                     # inserted as the number 12, not "12"

One template rendered at six, four and three column widths

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-brightness

and to booleans and null:

variables:
  - show_name: true
  - icon: null

The placeholder is part of a longer string

The 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.

Awkward characters are handled

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.


Unresolved placeholders

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.


Reference

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]]
Precedence Winner
variables on the instance vs default on the template variables
Same key twice in one list the first one

Next

Cards · Badges · Rows · ElementsRecipes for finished examples

Clone this wiki locally