Skip to content

Reusable YAML card examples

Real-world card examples

The two cards on this page show how same_as, calc(), constants, groups, and ref() can reduce repetition in complete card configurations.

Each example includes the full YAML, making it easier to see which parts are defined once, which parts are reused, and how the final layout is positioned.

Example Card 30

Electricity card with total and per-phase horseshoe gauges

Card 30 is an electricity card built with data from the DSMR Reader integration.

It displays:

  • total electricity consumption in the main horseshoe
  • individual consumption for phases L1, L2, and L3

Several parts of the card are repeated:

  • three horizontal divider lines
  • three phase groups, each containing a name, state, and separator circle
  • shared color stops used by both the horseshoe and the icon

Every reusable item also has a named id. This makes the configuration easier to follow and keeps same_as references explicit.

Card configuration

Entity definitions
- type: custom:flex-horseshoe-card
  entities:
    - entity: sensor.dsmr_reading_electricity_currently_delivered
      name: 'Total'
      area: ':30:'
    - entity: sensor.dsmr_reading_phase_currently_delivered_l1
      name: 'L1'
    - entity: sensor.dsmr_reading_phase_currently_delivered_l2
      name: 'L2'
    - entity: sensor.dsmr_reading_phase_currently_delivered_l3
      name: 'L3'
    - entity: sensor.dsmr_reading_electricity_currently_delivered
External palette definition
  palettes:
    rainbow: /local/palettes/rainbow-palette-new.json

The constants section contains reusable styles and color stops for ref(), together with numeric values used by calc().

Constants definition
  constants:
    centerX: 50
    centerY: 50
    lineStep: 11
    lineLength: calc(4 * 20 + 5)
    disabledLineStyle:
      stroke: var(--disabled-text-color)
      stroke-width: 2
    defaultColorStops:
      mode: gradient
      gap: 3
      colors:
        0: var(--fhs-sys-rainbow-blue)
        1: var(--fhs-sys-rainbow-green)
        2: var(--fhs-sys-rainbow-yellow)
        3: var(--fhs-sys-rainbow-orange)
        4: var(--fhs-sys-rainbow-red)
        5: var(--fhs-sys-rainbow-purple)

The three groups define the final card positions of the repeated phase layouts.

Info

Groups do not currently support same_as.

Groups can also scale or rotate their items:

Groups
1
2
3
4
5
6
7
8
groups:
  L1:
    xpos: 125
    ypos: 23
    scale:
      x: 1
      y: 1
    rotate: 90
Groups definition
  layout:
    groups:
      L1:
        xpos: 23
        ypos: 72
      L2:
        xpos: 73
        ypos: 72
      L3:
        xpos: 48
        ypos: 83
Area and icon definitions
    areas:
      - id: all
        entity_index: 0
        xpos: 0
        ypos: 100
        styles:
          - font-size: 0.75em
          - text-transform: none
          - text-anchor: start

    icons:
      - id: first
        entity_index: 0
        xpos: 50
        ypos: 10
        size: 1.5
        color_stops: ref(defaultColorStops)

The first horizontal line defines the shared position, size, and style. The remaining lines reuse it and move downward by a calculated amount.

Horizontal line definitions
    hlines:
      - id: first
        xpos: calc(centerX)
        ypos: 64
        length: calc(4 * 20 + 5)
        styles:
          - ref(disabledLineStyle)
          - opacity: 0.8
      - id: second
        same_as: first
        same_as_dypos: calc(1 * lineStep)
      - id: third
        same_as: first
        same_as_dypos: calc(2 * lineStep)
Vertical line definition
1
2
3
4
5
6
7
    vlines:
      - id: first
        xpos: 50
        ypos: 69.5
        length: 11
        styles:
          - stroke: var(--disabled-text-color)

The first small circle defines the shared local position, radius, and styling. The other two reuse that definition and receive their final position from their assigned group.

Circle definitions
    circles:
      - id: first
        group: L1
        xpos: calc(centerX - 3)
        ypos: calc(centerY - 3)
        radius: 2
        styles:
          - fill: var(--primary-text-color)
          - opacity: 0.5
      - id: second
        group: L2
        same_as: first
      - id: third
        group: L3
        same_as: first

      - id: bigone
        xpos: calc(centerX)
        ypos: calc(-centerY)
        radius: 175     # Radius in pixels
        styles:
          - fill: var(--primary-background-color)
          - opacity: 0.7
          - stroke: var(--disabled-text-color)
          - stroke-width: 2

The grouped state definitions follow the same pattern. The first phase state defines the local layout, and the other two reuse it within their own groups.

State definitions
    states:
      - id: all
        entity_index: 0
        xpos: calc(centerX)
        ypos: 56
        styles:
          - font-size: 2.5em
          - font-weight: bold
      - id: first
        group: L1
        entity_index: 1
        xpos: calc(centerX)
        ypos: calc(centerY)
        styles:
          - text-anchor: start
          - font-size: 1.2em
      - id: second
        group: L2
        entity_index: 2
        same_as: first
      - id: third
        group: L3
        entity_index: 3
        same_as: first

The names reuse the same local structure. Only the connected entity and group assignment change.

Name definitions
    names:
      - id: all
        entity_index: 0
        xpos: calc(centerX)
        ypos: 98
        ellipsis: 20
        styles:
          - font-size: 1.4em
          - text-transform: none
      - id: first
        entity_index: 1
        group: L1
        xpos: calc(centerX - 6)
        ypos: calc(centerY)
        styles:
          - text-anchor: end
          - font-size: 1.2em
      - id: second
        entity_index: 2
        group: L2
        same_as: first
      - id: third
        entity_index: 3
        group: L3
        same_as: first

The main horseshoe uses the shared color-stop definition through ref(defaultColorStops).

Horseshoe definition
    horseshoes:
      - id: first
        entity_index: 0
        xpos: calc(centerX)
        ypos: -45
        radius: 70
        tickmarks_radius: 43
        arc_degrees: 70
        flip: both

        show:
          horseshoe: true
          scale_tickmarks: false
          horseshoe_style: colorstopgradient
          scale_style: fixed
          labels_at: ticks_major
          ticks: true
          label_badges: true
          label_background: none

        horseshoe_scale:
          min: 0
          max: 5
          width: 6
          color: var(--primary-background-color)
          ticksize: 0.1
          gap: 3
          styles:
            - opacity: 0.7

        horseshoe_tickmarks:
          ticks_major:
            ticksize: 1
            color_mode: colorstopgradient
            width: 12
            offset: -3
            thickness: 3
            styles:
              - opacity: 0.9
          ticks_minor:
            ticksize: 0.2
            color_mode: colorstopgradient
            thickness: 2
            width: 6
            offset: -12
            styles:
              - opacity: 0.7

        horseshoe_labels:
          distance_min: 0.3
          ticksize_min: 0.3
          orientation: horizontal
          background:
            width: 10
            gap: 3
            styles:
              - opacity: 0.05
              - stroke: var(--primary-text-color)
          badges:
            radius: 6
            color: var(--card-background-color)
            border_color: var(--divider-color)
            padding: 0
            height: 10
          styles:
            - font-size: 0.7em

        horseshoe_state:
          width: 12

        color_stops: ref(defaultColorStops)

Example Card 32

Electricity card with one total and three reused phase horseshoe gauges

Card 32 also uses the DSMR Reader integration.

It displays four vertical horseshoes: one for total electricity consumption and one for each individual phase.

The repeated parts are:

  • four vertical horseshoes
  • four state values
  • four entity names

This card does not use groups. Instead, each reused item moves to the right through calculated horizontal offsets.

Card configuration

Entity definitions
- type: custom:flex-horseshoe-card
  entities:
    - entity: sensor.dsmr_reading_electricity_currently_delivered
      decimals: 2
      name: 'Total'
      area: ':32:'
    - entity: sensor.dsmr_reading_phase_currently_delivered_l1
      decimals: 2
      name: 'L1'
      area: 'Electricity'
    - entity: sensor.dsmr_reading_phase_currently_delivered_l2
      decimals: 2
      name: 'L2'
    - entity: sensor.dsmr_reading_phase_currently_delivered_l3
      decimals: 2
      name: 'L3'
    - entity: sensor.dsmr_reading_electricity_currently_delivered
      decimals: 2
External palette definition
  palettes:
    rainbow: /local/palettes/rainbow-palette-new.json

The constants define the starting position, the horizontal spacing, and the very large radius used to make the horseshoes appear almost straight.

Constants definition
1
2
3
4
5
6
  constants:
    radius0: 5000     # Large radius used to emulate a straight horseshoe
    xpos0: 20         # Horizontal position of the first horseshoe
    ypos0: 45         # Vertical position of the first horseshoe
    dxPos1: 25        # Horizontal shift from Total to L1
    dxPos2: 21        # Horizontal shift between the remaining phases
Area definitions
  layout:
    areas:
      - entity_index: 0
        xpos: 0
        ypos: 100
        styles:
          - font-size: 0.75em
          - text-transform: none
          - text-anchor: start
      - entity_index: 1
        xpos: 50
        ypos: 8
        styles:
          - font-size: 1.7em
          - text-transform: none

The first state defines the shared vertical position and style. Each following state reuses the previous definition and shifts to the right.

State definitions
    states:
      - entity_index: 0
        xpos: calc(xpos0)
        ypos: 85
        styles:
          - font-size: 1.0em
      - entity_index: 1
        same_as: 0
        same_as_dxpos: calc(dxPos1)
      - entity_index: 2
        same_as: 1
        same_as_dxpos: calc(dxPos2)
      - entity_index: 3
        same_as: 2
        same_as_dxpos: calc(dxPos2)

The names use the same horizontal reuse pattern.

Name definitions
    names:
      - entity_index: 0
        xpos: calc(xpos0)
        ypos: 95
        styles:
          - font-size: 1.0em
      - entity_index: 1
        same_as: 0
        same_as_dxpos: calc(dxPos1)
      - entity_index: 2
        same_as: 1
        same_as_dxpos: calc(dxPos2)
      - entity_index: 3
        same_as: 2
        same_as_dxpos: calc(dxPos2)

A very small arc of 0.7 degrees, combined with a large radius and a -90 degree rotation, makes the first horseshoe appear as a vertical progress bar.

Horseshoe definition: Total
    horseshoes:
      - entity_index: 0
        xpos: calc(-radius0 + xpos0 + 5)
        ypos: 45
        radius: calc(radius0)
        rotate: -90       # Rotates the horseshoe 90 degrees counterclockwise
        arc_degrees: 0.7  # A large radius requires a very small arc
        flip: y           # Flips the Y-axis so zero appears at the bottom

        show:
          horseshoe: true
          scale_tickmarks: false
          horseshoe_style: colorstopgradient
          scale_style: fixed
          labels_at: ticks_major
          ticks: true
          label_badges: true
          label_background: none

        horseshoe_scale:
          min: 0
          max: 5
          width: 6
          color: var(--primary-background-color)
          ticksize: 0.1   # One tick every 0.1 kWh
          gap: 3
          styles:
            - opacity: 0.7

        horseshoe_tickmarks:
          ticks_major:
            ticksize: 1
            color_mode: colorstopgradient
            width: 12
            offset: -3
            thickness: 1
            styles:
              - stroke: var(--primary-text-color)
              - fill: var(--primary-text-color)
              - opacity: 0.9
          ticks_minor:
            ticksize: 0.1
            color_mode: colorstopgradient
            thickness: 1
            width: 6
            offset: -12
            styles:
              - stroke: var(--primary-text-color)
              - fill: var(--primary-text-color)
              - opacity: 0.7

        horseshoe_labels:
          distance_min: 0.3
          ticksize_min: 0.3
          orientation: horizontal
          offset: -34
          badges:
            radius: 6
            color: var(--card-background-color)
            border_color: var(--divider-color)
            padding: 0
            height: 10
          styles:
            - font-size: 0.7em

        horseshoe_state:
          width: 12
          styles:
            - stroke-linecap: butt

        color_stops:
          gap: 3
          colors:
            0: var(--fhs-sys-rainbow-blue)
            1: var(--fhs-sys-rainbow-green)
            2: var(--fhs-sys-rainbow-yellow)
            3: var(--fhs-sys-rainbow-orange)
            4: var(--fhs-sys-rainbow-red)
            5: var(--fhs-sys-rainbow-purple)

The other three horseshoes need only a few lines of YAML.

The L1 horseshoe reuses the complete Total configuration, shifts to the right, and hides the labels. L2 and L3 each reuse the previous horseshoe and move right by the same calculated offset.

This avoids repeating the full horseshoe definition three more times.

Horseshoe definitions: L1, L2, and L3
      - entity_index: 1
        same_as: 0
        same_as_dxpos: calc(dxPos1)
        show:
          labels_at: none
      - entity_index: 2
        same_as: 1
        same_as_dxpos: calc(dxPos2)
      - entity_index: 3
        same_as: 2
        same_as_dxpos: calc(dxPos2)