omachala
ha-treemap-card
TypeScript

Treemap card for Home Assistant - like a stock market heatmap, but for your home. Instantly see which sensors need attention.

Last updated Jun 30, 2026
70
Stars
1
Forks
0
Issues
+2
Stars/day
Attention Score
67
Language breakdown
No language data available.
Files click to expand
README

Treemap Card Icon

Treemap Card for Home Assistant

HACS Default Downloads Version Coverage Quality Gate

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.

Treemap Card

Why Treemap Card?

Installation

HACS (Recommended)

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

Or manually:

  • Go to HACS → Frontend
  • Search for "Treemap Card"
  • Install and restart Home Assistant

Manual

Download treemap-card.js from releases and follow the official guide.

Data Modes

The card supports two ways to get data:

Entities Mode

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.*_battery

JSON Attribute Mode

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


Stock portfolio treemap

type: custom:treemap-card
entity: sensor.my_data
data_attribute: items
label:
  attribute: name
value:
  attribute: amount

Entity Types

The card is optimized for three entity types, each with special handling.

Sensors

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

Lights

Light 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: 300

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

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

Example: 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: 400

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


Climate sparklines showing temperature and HVAC activity

Binary Sensors & Switches

switch., inputboolean., and binarysensor.* entities display On / Off and use your configured color.high and color.low colors.

| State | Color behavior | | ----- | ---------------------------------- | | On | Uses color.high (default: green) | | Off | Uses color.low (default: red) |

type: custom:treemap-card
header:
  title: Switches & Devices
entities:
  - switch.*
  - input_boolean.*
size:
  equal: true
color:
  high: '#16a34a' # Green for On
  low: '#6c757d' # Gray for Off

Configuration Reference

Data Source

| Option | Default | Description | | ---------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | entities | | List of entity IDs or patterns. Supports wildcards (sensor.*) and object format ({ entity, name, icon, color, tapaction, holdaction }). | | 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). |

Label

| Option | Default | Description | | ----------------- | --------------- | --------------------------------------------------------------------------------------------------------- | | label.show | true | Show/hide labels. | | label.attribute | friendlyname | Field/attribute for label. Default: friendlyname (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. |

Value

| Option | Default | Description | | ------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | value.show | true | Show/hide values. | | value.attribute | state | Field/attribute for value. Default: state (entities) or value (JSON). Climate: currenttemperature, temperature, tempoffset, 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. |

Value Formatting

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

Size

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

Color

| 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: tempoffset, hvacaction. | | 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 over color.target.

Per-entity color overrides:

Individual entities can have a fixed color that bypasses the gradient entirely. Useful for category dashboards where you want consistent, meaningful colors regardless of value:

type: custom:treemap-card
entities:
  - entity: sensor.cost_lights
    color: '#F68C00'
    name: Lighting
  - entity: sensor.cost_heating
    color: '#B40404'
    name: Heating
  - entity: sensor.cost_appliances
    color: '#1B5E20'
    name: Appliances

The color field accepts any valid CSS color: hex (#F68C00), rgb(...), or named colors. It takes the highest priority — it overrides the gradient, light color, HVAC coloring, and everything else.

Icon

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

Order & Filter

| Option | Default | Description | | -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | order | desc | Sort direction: desc (high to low) or asc (low to high). Works with any sort_by option. | | sortby | value | What to sort by: value (optimal layout), entityid (alphabetically), label (by friendly name), or default (preserve config order). Perfect for battery grids or alphabetical lists where predictable positioning matters. | | 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.

Battery monitoring with fixed positions:

When monitoring battery cells or sensors where predictable positioning matters more than value-based layout, use sortby: entityid or sort_by: label:

type: custom:treemap-card
header:
  title: Battery Cells
entities:
  - sensor.batterycell1
  - sensor.batterycell2
  - sensor.batterycell3
  - sensor.batterycell4
  - sensor.batterycell5
  - sensor.batterycell6
  - sensor.batterycell7
  - sensor.batterycell8
sortby: entityid # Cells always appear in same position
size:
  equal: true # Equal-size grid
color:
  low: '#ff6b35' # Red for low battery
  high: '#16a34a' # Green for full

This creates a predictable grid where each cell stays in the same position regardless of charge level. Perfect for quickly spotting which specific cell needs attention.

For alphabetical sorting by friendly name, use sortby: label. For exact config order (top to bottom, left to right), use sortby: default.

Layout

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

Tap & Hold Actions

Clicking or long-pressing a tile triggers an action. By default, tapping opens the entity's more-info dialog. Hold actions are disabled by default.

| Option | Default | Description | | ------------- | ----------- | ---------------------------------------------- | | tap_action | more-info | Action when tapping a tile. | | hold_action | none | Action when long-pressing a tile (500ms hold). |

Action Types

| Action | Description | | -------------- | --------------------------------------------------------------------------------- | | more-info | Opens the entity's more-info dialog (default). | | navigate | Navigates to a dashboard or view. Requires navigation_path. | | url | Opens a URL in a new tab. Requires url_path. | | toggle | Toggles the entity (lights, switches, etc.). | | call-service | Calls a Home Assistant service. Requires service and optionally service_data. | | assist | Opens the voice assistant dialog. | | none | Disables the action entirely. |

Examples

More info (default — no config needed):

type: custom:treemap-card
entities:
  - sensor.temperature_*
tap_action:
  action: more-info

Navigate to a dashboard view on tap:

type: custom:treemap-card
entities:
  - light.*
tap_action:
  action: navigate
  navigation_path: /lovelace/lights

Open a URL on tap:

type: custom:treemap-card
entities:
  - sensor.power_*
tap_action:
  action: url
  url_path: https://my.home-assistant.io

Toggle lights on tap, open more-info on hold:

type: custom:treemap-card
entities:
  - light.*
tap_action:
  action: toggle
hold_action:
  action: more-info

Call a service on tap:

type: custom:treemap-card
entities:
  - light.*
tap_action:
  action: call-service
  service: light.turn_on
  service_data:
    brightness_pct: 80

Open voice assistant on tap:

type: custom:treemap-card
entities:
  - sensor.temperature_*
tap_action:
  action: assist

Disable tap, navigate on hold:

type: custom:treemap-card
entities:
  - sensor.*
tap_action:
  action: none
hold_action:
  action: navigate
  navigation_path: /lovelace/sensors

Per-Entity Action Overrides

Individual entities can have their own tap/hold actions, overriding the card-level defaults:

type: custom:treemap-card
entities:
  - light.*
  - entity: light.living_room
    tap_action:
      action: navigate
      navigation_path: /lovelace/living-room
  - entity: light.kitchen
    tap_action:
      action: toggle
    hold_action:
      action: more-info
tap_action:
  action: more-info # Default for all other lights

Title & Header guide

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

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

Styling guide

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;
OptionDescription
header.showShow or hide custom header. Default: true if header.title is set.
header.titleCustom header text. More compact than HA's default title.
header.styleCSS for the custom header. Example: font-size: 14px; padding: 4px 16px;
label.styleCSS for labels. Example: text-shadow: 0 0 10px rgba(0,0,0,0.3);
value.styleCSS for values. Example: font-size: 18px;
icon.styleCSS for icons. Example: color: white; opacity: 0.8;
card_styleCSS for the entire card. Example: background: transparent;

Sparkline

Each rectangle can display a mini chart showing historical data.

Humidity sensors Radiator sensors with sparklines

Entities mode: Uses Home Assistant's long-term statistics (most numeric sensors).

type: custom:treemap-card
entities:
  - sensor.temperature_*
sparkline:
  period: 24h

JSON mode: Uses data array from each item's attribute.

type: custom:treemap-card
entity: sensor.portfolio
data_attribute: holdings
sparkline:
  attribute: history

Sparkline Options

| 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.min | auto | Fixed Y-axis minimum. Useful for sensors with a known range (e.g., 0 for humidity) so small changes aren't exaggerated. | | sparkline.max | auto | Fixed Y-axis maximum. Pair with sparkline.min to pin both bounds. | | sparkline.hvac.show | true | Show HVAC activity bars for climate entities. | | 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 Details

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

Custom Styling Examples

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);

Fixed Y-axis bounds:

Prevents a nearly flat line from filling the full chart height when values change only slightly. Set both bounds to the sensor's meaningful range:

sparkline:
  min: 0
  max: 100
Note: Sparklines use Home Assistant's long-term statistics. Most numeric sensors and climate entities (temperature) have statistics enabled by default.

Size & Order guide

Tip: You may often prefer size.equal: true for 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 | | Battery grid sorted by cell number | size.equal: true + sortby: entityid | | Alphabetical list by friendly name | sort_by: label | | Keep exact config order | sort_by: default | | 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.min and size.max use 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 sizing
- size.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

Auto-Entities guide

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

With 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: power

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

Resources

Video

2 New HACS Energy Cards You NEED in Home Assistant
by BeardedTinker
YouTube



Video

I Found 5 Home Assistant Dashboard Cards You NEED to See in 2026
by Byte of Geek
YouTube



Visualizing Your Smart Home Health with the HA Treemap Card
by Dima Tokar
In-depth guide on using the treemap card for maintenance dashboards: battery monitoring, MQTT reconnect tracking, and WiFi signal strength visualization.
Blog Post


Author

Created and maintained by Ondrej Machala (LinkedIn).

MIT License. Contributions and feedback are welcome - feel free to open an issue or submit a PR.

🔗 More in this category

© 2026 GitRepoTrend · omachala/ha-treemap-card · Updated daily from GitHub