Free open source community project.
If you find it useful, please support it by giving a ⭐️ on GitHub
A custom Lovelace card that dynamically visualizes entities as a treemap. Rectangle sizes represent relative values while colors indicate status - perfect for comparing sensors, lights, thermostats, portfolios or any numeric data at a glance.
- Optimized for thousands of entities without breaking a sweat
- Works beautifully with sensors, lights, thermostats, and custom data
- Smart defaults, fully customizable - including per-tile CSS when you need pixel-perfect control
- Works with auto-entities for advanced filtering (area, device, label)
- 18 KB gzipped, 90%+ test coverage
Or manually:
- Go to HACS → Frontend
- Search for "Treemap Card"
- Install and restart Home Assistant
Download treemap-card.js from releases and follow the official guide.
The card supports two ways to get data:
Display Home Assistant entities directly. Supports wildcards and per-entity customization.
type: custom:treemap-card
entities:
- sensor.temperature_* # Wildcard pattern
- sensor.humidity_*
- entity: sensor.power_total # Object format with overrides
name: 'Total Power'
icon: mdi:lightning-bolt
exclude:
- sensor.*_batteryFor data where all values come from a single entity as JSON. Since Home Assistant doesn't allow JSON as sensor state values, structured data must be stored in attributes - a common pattern when feeding HA from external sources like Node-RED or custom integrations. This is ideal when you don't want (or can't) create individual sensors for each data item, especially for dynamic lists like stock portfolios, server metrics, or any array of objects.
type: custom:treemap-card
entity: sensor.my_data
data_attribute: items
label:
attribute: name
value:
attribute: amountThe card is optimized for three entity types, each with special handling.
Standard numeric sensors like temperature, humidity, battery levels, energy usage.
type: custom:treemap-card
header:
title: Humidity Levels
entities:
- sensor.*_humidity
exclude:
- sensor.*target*
size:
equal: true
value:
suffix: '%'
color:
low: '#4dabf7'
mid: '#69db7c'
high: '#ff6b35'
scale:
neutral: 50
min: 30
max: 70
label:
replace: ' Humidity$//'
height: 300Light entities automatically use brightness for sizing and display their actual color.
- RGB/HS color lights: Rectangle shows the light's actual color
- Dimmable-only lights: Yellow gradient based on brightness
- Off lights: Uses
color.low(default: dark gray#333333)
type: custom:treemap-card
header:
title: Lights
entities:
- light.*
color:
low: '#1a1a1a'
high: '#fbbf24'
height: 300Light-specific behavior:
| Feature | Behavior |
|---|---|
| Size | Based on brightness (brighter = bigger) |
| Color | Actual light color (RGB/HS) if available |
| Off state | Uses color.low value |
| Value | Shows brightness percentage |
Climate entities (thermostats, HVAC) support special computed values that make it easy to visualize which rooms need attention.
Standard attributes you can use:
| Attribute | What it shows |
|---|---|
current_temperature |
Current room temperature |
temperature |
Target/setpoint temperature |
hvac_action |
Current action: heating, cooling, idle, off |
Computed attributes - calculated automatically for you:
| Attribute | What it shows | Best for |
|---|---|---|
temp_difference |
How far from target (always positive). A room 3°C too cold or 3°C too hot both show 3. |
Sizing - rooms furthest from target get biggest rectangles |
temp_offset |
Direction from target. Too cold = negative, too hot = positive. | Coloring - blue for cold, red for hot |
Smart offset behavior: The card understands your heating/cooling goals:
- Heating mode: If the room is already warm enough, offset shows
0(not a positive number) - Cooling mode: If the room is already cool enough, offset shows
0(not a negative number)
Example: Room at 24°C, target 21°C, mode is heating → shows 0.0°C because it's warm enough. No action needed.
Example: Temperature offset view
Show how far each room is from target. Blue = too cold, green = on target, orange = too hot:
type: custom:treemap-card
header:
title: Temperature Offset
entities:
- climate.*
size:
attribute: temp_difference
inverse: true
value:
attribute: temp_offset
suffix: '°C'
color:
attribute: temp_offset
low: '#4dabf7'
mid: '#69db7c'
high: '#ff6b35'
scale:
neutral: 0
min: -3
max: 3
label:
replace: ^Wiser //
height: 350Example: Current temperature with HVAC status
Show current temperature, colored by value but override when actively heating/cooling:
type: custom:treemap-card
header:
title: Room Temperatures
entities:
- climate.*
size:
equal: true
value:
attribute: current_temperature
suffix: '°C'
color:
low: '#4dabf7'
mid: '#69db7c'
high: '#ff6b35'
scale:
neutral: 21
min: 18
max: 24
hvac:
heating: '#ff6b35'
cooling: '#4dabf7'
label:
replace: ^Wiser //
height: 400HVAC color behavior:
When color.hvac is configured:
| State | Color behavior |
|---|---|
heating |
Uses hvac.heating color (overrides gradient) |
cooling |
Uses hvac.cooling color (overrides gradient) |
idle |
Uses gradient based on value (so you see temp offset) |
off / unavailable |
Always uses hvac.off color (default: gray #868e96) |
This lets you see temperature-based colors normally, but immediately spot which rooms are actively heating or cooling.
Climate sparklines:
Climate entities show temperature history with HVAC activity highlighted. The filled sections indicate when heating (or cooling) was active, making it easy to see how often each room needed climate control.
| Option | Default | Description |
|---|---|---|
entities |
List of entity IDs or patterns. Supports wildcards (sensor.*) and object format ({ entity, name, icon }). |
|
exclude |
List of entity patterns to exclude. Supports * wildcards. |
|
entity |
Single entity ID with array data in attributes (JSON mode). | |
data_attribute |
items |
Which attribute contains the array (JSON mode). |
| Option | Default | Description |
|---|---|---|
label.show |
true |
Show/hide labels. |
label.attribute |
friendly_name |
Field/attribute for label. Default: friendly_name (entities) or label (JSON). |
label.replace |
Regex to clean labels. Format: pattern/replacement/flags. Example: ^Wiser // removes "Wiser " prefix. |
|
label.prefix |
Text before label. | |
label.suffix |
Text after label. | |
label.style |
CSS for labels. |
| Option | Default | Description |
|---|---|---|
value.show |
true |
Show/hide values. |
value.attribute |
state |
Field/attribute for value. Default: state (entities) or value (JSON). Climate: current_temperature, temperature, temp_offset, etc. |
value.precision |
1 |
Number of decimal places. Default uses entity's display_precision from HA registry, or 1 if not set. |
value.abbreviate |
false |
Abbreviate large numbers with suffixes: k (thousands), M (millions), B (billions), T (trillions). |
value.prefix |
Text before value. | |
value.suffix |
Text after value. Example: °C, %. |
|
value.style |
CSS for values. |
Control how numbers are displayed using precision (decimal places) and abbreviate (large number suffixes).
| precision | abbreviate | Input | Output | Description |
|---|---|---|---|---|
0 |
false |
1234.5 | 1235 |
Whole number (rounded) |
1 |
false |
1234.56 | 1234.6 |
1 decimal place |
2 |
false |
1234.5 | 1234.50 |
2 decimal places |
0 |
true |
1234 | 1k |
Abbreviated whole |
1 |
true |
2345 | 2.3k |
Abbreviated, 1 decimal |
2 |
true |
1234567 | 1.23M |
Abbreviated, 2 decimals |
Precision priority: value.precision config > entity's display_precision from HA registry > default 1
Examples:
# Show whole numbers (no decimals)
value:
precision: 0
# Show 2 decimal places
value:
precision: 2
# Large values abbreviated (2.3k, 1.5M)
value:
precision: 1
abbreviate: true| Option | Default | Description |
|---|---|---|
size.attribute |
same as value.attribute |
Field/attribute for sizing. For climate: temp_difference works well with inverse: true. |
size.equal |
false |
All rectangles same size. |
size.inverse |
false |
Low values get bigger rectangles. |
size.min |
auto | Minimum size floor in entity units (e.g., 5 for 5W or 5°C). Ensures zero-value items visible. 0 hides them. |
size.max |
Maximum size cap in entity units (e.g., 500 for 500W). Prevents outliers from dominating the layout. |
| Option | Default | Description |
|---|---|---|
color.target |
background |
Where to apply color: background (default) or foreground (text/icon). |
color.low |
#b91c1c (red) |
Color for lowest values. Also used for off lights. |
color.mid |
Optional middle color. Creates three-color gradient: low → mid → high. | |
color.high |
#16a34a (green) |
Color for highest values. |
color.unavailable |
#868e96 (gray) |
Color for unavailable/unknown entities. See filter.unavailable. |
color.opacity |
1 |
Color opacity (0-1). |
color.attribute |
same as value.attribute |
Field/attribute for coloring. For climate: temp_offset, hvac_action. |
color.scale.neutral |
Value where mid color appears. Example: 0 for profit/loss, 21 for temperature. |
|
color.scale.min |
auto | Values at or below get full low color. |
color.scale.max |
auto | Values at or above get full high color. |
color.hvac.heating |
#ff6b35 |
Color when actively heating (climate only). |
color.hvac.cooling |
#4dabf7 |
Color when actively cooling (climate only). |
color.hvac.idle |
Not used - idle falls back to gradient. | |
color.hvac.off |
#868e96 |
Color for off/unavailable climate entities. |
Foreground coloring:
Use color.target: foreground to apply the gradient color to text and icons instead of the background. The background becomes a subtle dark overlay, making the colored text stand out.
type: custom:treemap-card
entities:
- sensor.temperature_*
color:
target: foreground
low: '#4dabf7'
high: '#ff6b35'Note: Custom styles (
label.style,value.style,icon.style) always take priority overcolor.target.
| Option | Default | Description |
|---|---|---|
icon.show |
true |
Show/hide icons. |
icon.icon |
Static icon for all items. Example: mdi:thermometer. |
|
icon.attribute |
icon |
Field/attribute containing icon. |
icon.style |
CSS for icons. |
| Option | Default | Description |
|---|---|---|
order |
desc |
Sort order: desc (largest first) or asc (smallest first). |
limit |
Maximum items to show. | |
filter.above |
Only show items with value greater than this. | |
filter.below |
Only show items with value less than this. | |
filter.unavailable |
false |
Include entities that stopped reporting or are unreachable (unavailable, unknown, none states). Useful for battery monitoring where dead sensors matter as much as low batteries. Displays state text and gray background (customize via color.unavailable). |
Note: These filters work on entity values after entities are resolved. For entity-level filtering (by area, device, label, attributes), see the Auto-Entities guide.
| Option | Default | Description |
|---|---|---|
height |
auto | Card height in pixels. Auto-calculates based on row count (~100px per row). |
gap |
6 |
Space between rectangles in pixels. |
Two ways to add a title - use one or the other, not both:
title - Uses Home Assistant's built-in card header. Consistent with other HA cards, but no customization options.
title: Humidityheader - Custom compact header with full styling control. Takes less vertical space than HA's default.
header:
title: Humidity
style: |
font-size: 14px;
padding: 4px 16px;If both are set, header.title takes precedence and title is ignored.
Customize the appearance with inline CSS. All style options accept multiline YAML strings.
header:
title: My Treemap
style: |
font-size: 20px;
color: red;
label:
style: |
text-shadow: 0 0 10px rgba(0,0,0,0.5);
value:
style: |
font-size: 18px;
font-weight: bold;
icon:
style: |
opacity: 0.8;
card_style: |
background: transparent;| Option | Description |
|---|---|
header.show | Show or hide custom header. Default: true if header.title is set. |
header.title | Custom header text. More compact than HA's default title. |
header.style | CSS for the custom header. Example: font-size: 14px; padding: 4px 16px; |
label.style | CSS for labels. Example: text-shadow: 0 0 10px rgba(0,0,0,0.3); |
value.style | CSS for values. Example: font-size: 18px; |
icon.style | CSS for icons. Example: color: white; opacity: 0.8; |
card_style | CSS for the entire card. Example: background: transparent; |
Each rectangle can display a mini chart showing historical data.
|
|
Entities mode: Uses Home Assistant's long-term statistics (most numeric sensors).
type: custom:treemap-card
entities:
- sensor.temperature_*
sparkline:
period: 24hJSON mode: Uses data array from each item's attribute.
type: custom:treemap-card
entity: sensor.portfolio
data_attribute: holdings
sparkline:
attribute: history| Option | Default | Description |
|---|---|---|
sparkline.show |
true |
Show/hide sparklines. |
sparkline.attribute |
Field containing sparkline data array (JSON mode). | |
sparkline.period |
24h |
Time period for entity history: 12h, 24h, 7d, or 30d. |
sparkline.mode |
dark |
Color mode: dark (dark line/fill) or light (light line/fill). |
sparkline.line.show |
true |
Show/hide the line. |
sparkline.line.style |
Custom CSS for line (SVG properties). | |
sparkline.fill.show |
true |
Show/hide the filled area under the line. |
sparkline.fill.style |
Custom CSS for fill (SVG properties). |
| Period | Time Range | Data Points | Best For |
|---|---|---|---|
12h |
12 hours | ~144 | Detailed recent view |
24h |
24 hours | ~24 | Daily overview |
7d |
7 days | ~168 | Weekly trends |
30d |
30 days | ~30 | Monthly trends |
Red line, no fill:
sparkline:
fill:
show: false
line:
style: |
stroke: rgba(255, 0, 0, 0.5);
stroke-width: 2;Thick white line with light fill:
sparkline:
mode: light
line:
style: |
stroke: rgba(255, 255, 255, 0.8);
stroke-width: 3;
fill:
style: |
fill: rgba(255, 255, 255, 0.2);Fill only, no line:
sparkline:
line:
show: false
fill:
style: |
fill: rgba(0, 0, 0, 0.3);Note: Sparklines use Home Assistant's long-term statistics. Most numeric sensors and climate entities (temperature) have statistics enabled by default.
Tip: You may often prefer
size.equal: truefor a clean, uniform grid layout.
Below are common sizing and ordering configurations to achieve different visual effects:
| What you want | Configuration |
|---|---|
| Biggest values = biggest rectangles, shown first | order: desc (default) |
| Biggest values = biggest rectangles, shown last | order: asc |
| Smallest values = biggest rectangles, shown first | order: desc + size.inverse: true |
| Smallest values = biggest rectangles, shown last | order: asc + size.inverse: true |
| All rectangles same size | size.equal: true |
| Hide zero-value items | size.min: 0 |
| Tame outliers (e.g., cap 1000W at 100W) | size.max: 100 |
| Boost small items (e.g., 0-5 become 10) | size.min: 10 |
Note:
size.minandsize.maxuse the same units as your entity values, not percentages of the layout.Example with valve sensors (0-100%):
- Valve A: 75%, Valve B: 50%, Valve C: 0%, Valve D: 0%
- Default behavior: Zero-value valves automatically get a small minimum size so they're visible
size.min: 10- All valves below 10% are treated as 10% for sizingsize.min: 0- Zero-value valves are hidden (no rectangle area)Example with power sensors (0-3000W):
- One device at 2500W dominates the layout, others at 50-200W are tiny
size.max: 500- Caps the 2500W device to 500W for sizing, giving other devices more visible space
For advanced entity filtering by area, device, label, or attributes, use auto-entities. This is YAML-only (no visual editor when using auto-entities as a wrapper).
| Use Case | Solution |
|---|---|
| Simple pattern matching | Built-in: sensor.power_* |
| Filter by area, device, label | Auto-entities |
| Filter by attributes or state | Auto-entities |
Filter by area and device class:
type: custom:auto-entities
card:
type: custom:treemap-card
header:
title: Kitchen Power
filter:
include:
- domain: sensor
area: Kitchen
attributes:
device_class: power
exclude:
- state: unavailableWith treemap filtering:
type: custom:auto-entities
card:
type: custom:treemap-card
filter:
above: 10 # Only show values > 10W
order: desc
limit: 20
filter:
include:
- domain: sensor
attributes:
device_class: powerPer-entity customization (works with or without auto-entities):
type: custom:treemap-card
entities:
- sensor.power_*
- entity: sensor.solar_production
name: 'Solar Panels'
icon: mdi:solar-power
2 New HACS Energy Cards You NEED in Home Assistant
by BeardedTinker
Created and maintained by Ondrej Machala (LinkedIn).
MIT License. Contributions and feedback are welcome - feel free to open an issue or submit a PR.
