Skip to content
cataseven edited this page Jul 29, 2026 · 1 revision

Examples

Jump to

💡 Examples

Basic: Single Sensor

type: custom:statistics-graph-chart-card
card_header: Bedroom
hours_to_show: 12
entities:
  - entity: sensor.bedroom_temperature
    name: Temperature
    color: "#ff6b35"
    icon: mdi:thermometer

🌡️ Multi-Entity with Dual Axes

Combine temperature and humidity on the same card without the scales conflicting.

type: custom:statistics-graph-chart-card
card_header: Climate
card_icon: mdi:home-thermometer
hours_to_show: 24
lower_bound_secondary: "~0"
upper_bound_secondary: "~100"
entities:
  - entity: sensor.temperature
    name: Temperature
    color: "#ff6b35"
    y_axis: primary
    icon: mdi:thermometer

  - entity: sensor.humidity
    name: Humidity
    color: "#00bcd4"
    y_axis: secondary
    icon: mdi:water-percent

⚡ Bar Chart with Legend

type: custom:statistics-graph-chart-card
card_header: Energy Today
entities:
  - entity: sensor.daily_energy
    name: Consumption
    graph_type: bar
    color: "#2ecc71"
    show_in_legend: true
    aggregate_func: sum
    group_by: hour

show_in_legend: true prints the stats row; choose which numbers with legend_stats — any combination of min, avg, max, last, sum and, new in v3.32, live (the entity's state right now, whatever period the chart shows).


🎯 Period Highlight

On bar charts, hovering a bar shades the background of the entire period under the cursor — a soft band spanning the full bar slot — so it is immediately clear which period a tooltip or value belongs to. It is most useful with several entities drawn side by side, where the thin gaps between adjacent periods otherwise make the boundaries hard to read.

type: custom:statistics-graph-chart-card
period_highlight: true
period_highlight_color: rgba(128,128,128,0.3)   # optional; empty = subtle theme grey
graph_type: bar
group_by: date
entities:
  - sensor.garage_temp
  - sensor.kids_room_temp
  - sensor.living_room_temp
  • Off by default. Enable with period_highlight: true.
  • period_highlight_color accepts any CSS color (hex, rgba, name) or variable. You can also set the --sgc-period-highlight-color CSS variable from a theme or card_mod. Leave it empty for a subtle theme grey.
  • The band follows the hovered period, so it lines up exactly with the bar group beneath it.
  • Works whether or not show_tooltip is enabled — turn the tooltip off and you still get the period band on hover.
  • In the visual editor it lives in the Tooltip section.
  • Available in Timeline mode (bar and line charts).

🎨 Color Thresholds

Colorize the graph based on value ranges. Two independent settings control the behavior:

  • Direction — which axis the colors are painted along:

    • vertical (default) — Y-axis gradient. The entire chart is colored based on value height.
    • horizontal — per-segment coloring along the time axis. Each line segment gets the color matching its data value.
  • Transition — how colors change at threshold boundaries:

    • smooth (default) — gradual interpolation between adjacent threshold colors.
    • hard — instant color switch exactly at the threshold value.
type: custom:statistics-graph-chart-card
entities:
  - entity: sensor.outdoor_temperature
    name: Outdoor Temp
    color: threshold
    state_color: threshold
    color_thresholds:
      enabled: true
      direction: vertical   # or: horizontal
      transition: smooth     # or: hard
      values:
        - value: 0
          color: "#3498db"
        - value: 15
          color: "#2ecc71"
        - value: 25
          color: "#f39c12"
        - value: 35
          color: "#e74c3c"

All four direction × transition combinations are available from the editor under Colors → Color Thresholds.

Setting color: threshold propagates threshold colors to the state row dot as well. Setting state_color: threshold colors the displayed value text.

Gradient fill is threshold-aware. When gradient: true is enabled alongside color_thresholds, the fill area under the line is rendered as a vertical gradient whose colors match the line — the gradient stops sample threshold colors at chart top, zero line, and chart bottom. For a chart that crosses zero with two threshold bands (e.g. purple above zero, green below), the fill blends from purple at the top through transparent at the zero line down to green at the bottom, just like the line itself.

Dynamic thresholds from entities. Both the value and the color of each threshold entry can be an entity reference instead of a fixed literal. Use sensor.x for an entity's state or sensor.x.attribute for one of its attributes (nested attribute paths are supported). This lets thresholds track other sensors — a seasonal comfort target, a calculated limit, or a color served by a template sensor — and they update live as those entities change, without waiting for the next data refresh.

color_thresholds:
  enabled: true
  values:
    - value: sensor.heating_setpoint        # threshold follows a sensor's state
      color: "#3498db"
    - value: sensor.comfort.upper           # or one of its attributes
      color: sensor.theme_colors.warn       # the color can be entity-driven too

📈 Rise/Fall Colors

Color each graph segment green when rising and red when falling — without needing to define any value thresholds. trend_period_hours controls how sensitive the detection is.

type: custom:statistics-graph-chart-card
entities:
  - entity: sensor.stock_price
    name: Price
    rise_fall_colors:
      enabled: true
      increase: "#2ecc71"
      decrease: "#e74c3c"
      stable: "#95a5a6"
    trend_period_hours: 2

🎨 Color Templates

Use Jinja2 templates in any color field to manage colors centrally. Create a single template sensor with all your entity colors, and every card updates when you change it.

Setup: Create a central color sensor

# configuration.yaml → template section
template:
  - sensor:
      - name: "Entity Colors"
        unique_id: entity_colors_map
        state: "ok"
        attributes:
          entities: >-
            {{
              {
                "Temperature": "#FF6B6B",
                "Humidity": "#2ecc71",
                "Solar": "#f1c40f"
              }
            }}

Usage in card YAML:

entities:
  - entity: sensor.temperature
    color: "{{ state_attr('sensor.entity_colors','entities')['Temperature'] | default('#ff4757') }}"
    icon_color: "{{ states('input_select.theme_accent') }}"

Templates are evaluated server-side by HA via WebSocket subscriptions — colors update automatically when dependencies change, with no polling. In the editor, typing {{ in any color field dims the picker automatically.

Works with color, point_colors, icon_color, state_color, and all card-level color options (y_axis_color, x_axis_color, y_grid_color, x_grid_color, card_icon_color).


➖ Average Line

Draw a dashed reference line at the mean value over the visible time window. Useful for spotting trends at a glance.

type: custom:statistics-graph-chart-card
hours_to_show: 24
entities:
  - entity: sensor.outdoor_temperature
    name: Temperature
    color: "#ff6b35"
    show_average: true

  # Multiple entities each show their own average in their own color
  - entity: sensor.indoor_temperature
    name: Indoor
    color: "#00bcd4"
    show_average: true

🔗 Attribute Reading

Read a specific attribute instead of the main entity state. Supports dot notation for nested paths.

type: custom:statistics-graph-chart-card
entities:
  # Simple attribute
  - entity: weather.home
    name: Humidity
    attribute: humidity
    icon: mdi:water-percent

  # Nested attribute (e.g. first forecast entry)
  - entity: weather.home
    name: Forecast Temp
    attribute: forecast.0.temperature
    icon: mdi:thermometer

Since v3.32 you no longer have to hand-write a name: just to tell two attributes of the same entity apart. Set include_attribute_name: true at card level for Home · Humidity, or use_only_attribute_name: true for just Humidity — applied to the state row, legend, tooltip, stats and exports. Rows that plot the entity state itself, and rows with an explicit name:, are left alone.


🔀 State Map — Non-Numeric Entities

Use state_map to graph entities with string states like input_boolean, binary_sensor, or input_select. States are mapped to numbers in the order they are listed, starting at 0.

The Y-axis automatically shows the original state names instead of numeric indexes — so a washing machine graph displays idle, running, done on the axis, not 0, 1, 2. The chart tooltip shows the matching entry's label too (nearest entry when values are aggregated) — improved in v3.29: timeline tooltips previously showed the numeric index.

You can optionally provide friendly display labels with the label field — useful when the raw state is technical (armed_home) but you want a cleaner axis (Home):

type: custom:statistics-graph-chart-card
entities:
  # binary_sensor → 0 (off) / 1 (on), axis shows "off" / "on"
  - entity: binary_sensor.front_door
    name: Front Door
    color: "#9b59b6"
    graph_type: step
    state_map:
      - value: "off"
      - value: "on"

  # With friendly labels — axis shows "Idle" / "Running" / "Done"
  - entity: sensor.washing_machine
    name: Washing Machine
    graph_type: step
    state_map:
      - value: "idle"
        label: Idle
      - value: "running"
        label: Running
      - value: "done"
        label: Done

  # input_select → 0 / 1 / 2 / 3
  - entity: input_select.heating_mode
    name: Heating Mode
    state_map:
      - value: "off"
      - value: "eco"
      - value: "comfort"
      - value: "boost"

In the visual editor, the State Map textarea accepts a value, label, color syntax — one line per state, with the label and color both optional. Any CSS color works (name, hex, or var(--…)):

off, Idle, grey
on, Running, green

These colors are used as the segment color in state_timeline mode (and for the dot/marker elsewhere). Colors set in YAML — color: under a state_map entry — are preserved when you re-open the card in the editor.

Auto-detected for binary_sensor, input_boolean, and any input_select entity in step mode — you don't need to define a state_map for those, the card detects available states automatically and labels the axis accordingly.

Compass axis for wind direction (v3.29)

state_map also works as a pure axis-label list for numeric sensors: entries that never match the state are ignored for data (the numeric value passes through), but the axis and tooltip still use them as labels. Combined with value_transform, this turns a wind-direction sensor (0–360°) into a compass chart — no custom formatter functions needed:

type: custom:statistics-graph-chart-card
title: Daily Wind Direction
graph_start: day
group_by: interval
points_per_hour: 2          # 30-minute buckets
show_y_axis: true
y_axis_ticks: 8             # a label every 45° (N, NE, E, …); use 16 for all sectors
entities:
  - entity: sensor.wind_direction
    name: Wind Direction
    aggregate_func: avg
    decimals: 0
    unit: ""
    value_transform: "return 16 - (((x % 360) + 360) % 360) / 22.5;"
    state_map:              # axis labels, bottom → top (index 0..16)
      - value: ""
      - value: "NNW"
      - value: "NW"
      - value: "WNW"
      - value: "W"
      - value: "WSW"
      - value: "SW"
      - value: "SSW"
      - value: "S"
      - value: "SSE"
      - value: "SE"
      - value: "ESE"
      - value: "E"
      - value: "ENE"
      - value: "NE"
      - value: "NNE"
      - value: "N"

The transform maps 0° (N) to the top of the axis and the tooltip shows the compass name of the hovered value (SSW, not 202°). The empty first entry keeps N from being printed twice (0° and 360° are the same direction).

Two honest limitations of the recipe:

  • The last sliver before due north (≈349°–360°) rounds onto that unlabeled wrap entry, so the tooltip shows a small number there instead of N. If northerly winds dominate your site, give the first entry value: "N" instead — the tooltip then always reads N, at the cost of the axis printing N at the bottom rather than the top.
  • Averaging compass degrees is circular math done linearly: a bucket whose samples straddle the 0°/360° seam (e.g. 350° and 10°) averages to ~180° and gets labeled S. This artifact is inherent to avg on wind degrees — the apexcharts setup this recipe replaces has exactly the same behavior.

📏 Fixed Value Reference Line

Draw a flat horizontal line at the current value of an entity. Useful for showing targets or limits alongside historical data.

type: custom:statistics-graph-chart-card
entities:
  - entity: sensor.room_temperature
    name: Temperature
    color: "#ff6b35"

  - entity: input_number.target_temperature
    name: Target
    color: "#2ecc71"
    fixed_value: true
    show_fill: false
    line_width: 1.5

〰️ Soft Bounds

Use a ~ prefix to create a soft bound — the axis will prefer the value but expand if data exceeds it. Hard bounds (no prefix) force the axis edge regardless of data.

type: custom:statistics-graph-chart-card
entities:
  - entity: sensor.battery_level
    name: Battery
    lower_bound: "~0"    # prefer 0 as minimum; expands if data goes below
    upper_bound: "~100"  # prefer 100 as max; expands if data exceeds

📡 Dynamic Y Axis Bounds

Bind the Y axis min/max to another sensor for a fully dynamic range.

type: custom:statistics-graph-chart-card
entities:
  - entity: sensor.power_output
    name: Power
    lower_bound: 0
    upper_bound: sensor.max_capacity

👆 Tap Actions

Trigger actions when tapping an entity's state row.

type: custom:statistics-graph-chart-card
entities:
  # Open entity detail dialog
  - entity: sensor.temperature
    tap_action:
      action: more-info

  # Navigate to another dashboard
  - entity: sensor.energy
    tap_action:
      action: navigate
      navigation_path: /lovelace/energy

  # Call a service
  - entity: binary_sensor.pump
    tap_action:
      action: call-service
      service: switch.toggle
      service_data:
        entity_id: switch.pump

  # Fire DOM event (browser_mod popup, YAML only)
  - entity: sensor.power
    tap_action:
      action: fire-dom-event
      browser_mod:
        service: browser_mod.popup
        data:
          content:
            type: custom:mini-graph-card
            entity: sensor.power

🌅 Dynamic Graph Hours

Filter data to specific hours each day using sensor values. Ideal for solar panels (sunrise to sunset) or business hours.

type: custom:statistics-graph-chart-card
graph_start_hour: sensor.sunrise_hour
graph_end_hour: sensor.sunset_hour
hours_to_show: 168
show_date_picker: true
entities:
  - entity: sensor.solar_power

Create template sensors that output fractional hours:

template:
  - sensor:
      - name: "Sunrise Hour"
        unique_id: sunrise_hour
        state: >
          {% set dt = state_attr('sun.sun', 'next_rising') | as_datetime | as_local %}
          {{ dt.hour + dt.minute / 60 }}
      - name: "Sunset Hour"
        unique_id: sunset_hour
        state: >
          {% set dt = state_attr('sun.sun', 'next_setting') | as_datetime | as_local %}
          {{ dt.hour + dt.minute / 60 }}

When viewing multiple days, data outside the specified hours is hidden and lines break naturally between days. Both graph_start_hour and graph_end_hour accept fixed numbers (6, 22, 6.5 for 06:30) or entity IDs.


⏩ Sparse Data with Points Per Hour

For sensors that update infrequently (e.g. weather), use a higher points_per_hour with forward-fill. Empty buckets inherit the last known value, producing a clean step-line instead of scattered dots.

type: custom:statistics-graph-chart-card
points_per_hour: 12
hours_to_show: 24
entities:
  - entity: weather.home
    attribute: humidity
    name: Humidity
    smooth: false  # step-like appearance is more accurate for infrequent updates

🎚️ Interval Picker & Attribute Switcher

Add on-card controls for quick time range switching and live attribute exploration — no need to open the editor.

type: custom:statistics-graph-chart-card
card_header: Weather Station
hours_to_show: 24
show_interval_picker: true
interval_picker_position: left
show_attribute_list: true
attribute_list_position: right
entities:
  - entity: weather.home
    name: Temperature
    attribute: temperature
    color: "#ff6b35"

  - entity: weather.home
    name: Humidity
    attribute: humidity
    color: "#00bcd4"

The interval picker displays buttons for the default set: 1H, 2H, 4H, 8H, 12H, 24H, and 7D. Clicking a button temporarily overrides hours_to_show; clicking again deselects it and returns to the original range.

To customize which buttons appear, use interval_options:

# Show only the intervals you need — fits on one row on mobile
show_interval_picker: true
interval_options:
  - "2H"
  - "12H"
  - "24H"
  - "7D"
  - "30D"

Available labels: 1H, 2H, 4H, 8H, 12H, 24H, 3D, 7D, 14D, 30D, 90D, 6M, 1Y. The editor also provides a Visible Intervals checkbox grid under the Interval Picker toggle (General Settings → Overlays).

The attribute list shows a dropdown per entity with a color-coded dot. Select any numeric attribute to instantly re-graph with that data — the graph, state row, and tooltip all update live. The dropdown uses Home Assistant's own translated attribute names, the same wording include_attribute_name / use_only_attribute_name put in the series label, so the picker and the label can't disagree — and if you switch those options on, the label follows whatever attribute you pick here.

Both controls share a single toolbar row and wrap automatically on narrow cards.


🔍 Scrollable Graph

Load a wide time range but show only a portion at a time — scroll to explore.

type: custom:statistics-graph-chart-card
card_header: Weekly Overview
hours_to_show: 168        # 7 days of data
max_visible_interval: 24  # show 24h at a time
scroll_mode: wheel         # or: scrollbar
entities:
  - entity: sensor.temperature
    color: "#ff6b35"

The graph starts scrolled to the right (most recent data). Y-axis labels stay fixed while the graph content scrolls underneath. Scroll position is preserved across HA state updates.

scroll_mode Behavior
scrollbar Thin visible scrollbar (default)
wheel Mouse wheel scrolls horizontally, no visible scrollbar

On mobile/touch devices, swipe always works regardless of the scroll mode setting.

💡 Combines well with the Interval Picker — select "7D" to get a wide range, then scroll through it with a 6-hour visible window.


↔️ Icon Position

Place the header icon on the right side for a different layout feel.

type: custom:statistics-graph-chart-card
card_header: Living Room
card_icon: mdi:thermometer
card_icon_position: right   # default: left
entities:
  - entity: sensor.temperature
    color: "#ff6b35"

🏆 Full Example

A complete card showing most features together.

type: custom:statistics-graph-chart-card
card_header: Home Climate
card_icon: mdi:home-thermometer
card_icon_color: "#ff6b35"
align_header: left
hours_to_show: 24
points_per_hour: 6
height: 180
show_grid: true
show_tooltip: true
animate_graph: false
update_interval: 60

entities:
  - entity: sensor.living_temperature
    name: Temperature
    color: "#ff6b35"
    icon: mdi:thermometer
    y_axis: primary
    show_in_legend: true
    show_extrema: click
    show_average: true
    decimals: 1
    gradient: true
    state_adaptive_color: true
    color_thresholds:
      enabled: true
      transition: smooth
      values:
        - value: 18
          color: "#3498db"
        - value: 22
          color: "#2ecc71"
        - value: 28
          color: "#e74c3c"

  - entity: sensor.living_humidity
    name: Humidity
    color: "#00bcd4"
    icon: mdi:water-percent
    y_axis: secondary
    show_in_legend: true
    decimals: 0
    lower_bound: "~0"
    upper_bound: "~100"

Clone this wiki locally