Skip to content

Button Card

custom:lcards-button

The Button card covers everything from simple labels and toggle buttons to complex interactive components like D-pads and multi-segment SVG controls. Elbows are derived from the same base - most features here are also available in the Elbow card.


Quick Start

yaml
# Lozenge button — entity toggle
type: custom:lcards-button
entity: light.living_room
preset: lozenge
tap_action:
  action: toggle
yaml
# Bar-label section header (decorative)
type: custom:lcards-button
preset: bar-label-left
interactive: false
text:
  label:
    content: NAVIGATION

Common Properties

The following properties are shared across LCARdS cards. See Common Card Properties for full details.

CategoryConfig keysReference
Sizingheight, width, min_height, min_width, max_height, max_widthSizing
Overflowoverflow, overflow_x, overflow_yOverflow
Stackingz_indexStacking
Identityid, tagsID & Tags
HA Gridgrid_optionsHA Grid Sizing
Datadata_sources, triggers_updateData Sources
Text labelstextText Fields
Actionstap_action, hold_action, double_tap_actionActions
Animationsanimations, background_animationAnimations
SoundssoundsSounds
Rulesvia id / tagsRules Engine

Config Structure

Annotated map of all top-level keys. You only need the keys relevant to your use case — everything else has sensible defaults.

yaml
type: custom:lcards-button

# ── Identity & entity ──────────────────────────────────────────────────────────
entity: light.living_room   # entity to monitor / control (optional for decorative)
id: my-button               # rules engine targeting (unique per dashboard)
tags: [nav, lights]         # group tags for rules engine

# ── Mode (choose one) ──────────────────────────────────────────────────────────
preset: lozenge             # preset mode  ← most common
component: dpad             # component mode: 'dpad' or 'alert'
svg:                        # custom SVG mode
  content: "<svg>...</svg>"

# ── Core display ───────────────────────────────────────────────────────────────
interactive: true           # false = suppress hover effects (actions still fire)
icon: mdi:lightbulb
icon_area: left             # left | right | top | bottom | none
icon_area_size: 60
icon_area_background:           # string or state-based: default | active | inactive | hover | pressed | unavailable
  default: transparent
  active: "var(--lcars-orange)"
icon_style: {}              # colour, size, position, rotation — see icon_style
divider: {}                 # line between icon area and content

# ── Appearance ─────────────────────────────────────────────────────────────────
style:
  card:
    color:
      background:               # string or state-based object
        default: "var(--ha-card-background)"
        active: "alpha(var(--lcars-orange), 0.15)"
  border:
    color:                      # string or state-based object
      default: "var(--lcars-orange)"
      inactive: "alpha(var(--lcars-orange), 0.3)"
    width: 2
    radius: 8
  text:
    default:
      color:                    # string or state-based object
        default: "var(--lcars-moonlight)"
shape_texture:
  preset: fluid
filters: []

# ── Text labels ────────────────────────────────────────────────────────────────
text:
  default:
    font_family: "Antonio, sans-serif"
  label:
    content: "My Label"
    position: top-left

# ── Actions ────────────────────────────────────────────────────────────────────
tap_action:
  action: toggle
hold_action:
  action: more-info
double_tap_action:
  action: navigate
  navigation_path: /lights

# ── Animations & effects ───────────────────────────────────────────────────────
animations: []
background_animation: []
sounds: {}

# ── Component-specific (only needed for the chosen component mode) ─────────────
dpad:
  segments:
    default:                    # shared properties inherited by all segments
      style:
        fill:                   # stateColorSchema
          default: "var(--lcars-orange)"
          inactive: "alpha(var(--lcars-orange), 0.3)"
    center:                     # per-segment override (up/down/left/right/center)
      tap_action:
        action: toggle
alert:
  color:                        # fill/stroke shorthand — plain strings, not state-based
    shape: "var(--lcars-orange)"    # fill colour for the shield shape
    bars: "var(--lcars-moonlight)"  # stroke colour for the bar lines
ranges: []
ranges_attribute: ""

# ── Layout ─────────────────────────────────────────────────────────────────────
height: 60
width: 200
min_height: 40
max_height: 200
overflow: hidden
z_index: 0
grid_options:
  columns: 4
  rows: 1
data_sources: {}
triggers_update: []

Modes

The card operates in one of three modes, selected by which top-level key is present:

ModeKeyUse for
PresetpresetStandard LCARS buttons — lozenge, bullet, capped, etc.
ComponentcomponentInteractive multi-segment controls (D-pad, alert shape)
Custom SVGsvgYour own SVG with interactive segments

Presets

Standard Buttons

PresetDescription
lozengeFully rounded on both ends, icon area on left
lozenge-rightFully rounded on both ends, icon area on right
bulletRounded right end, flat left — icon area on left
bullet-rightRounded left end, flat right — icon area on right
cappedRounded left end, flat right — icon area on left
capped-rightRounded right end, flat left — icon area on right
barrelFlat corners, no border, icon area on left
barrel-rightFlat corners, no border, icon area on right
filledTransparent border, large text label on right
filled-rightTransparent border, large text label on left
outlineTransparent background, border only — Picard style
outline-rightTransparent background, border only, icon area on right
iconSquare icon-only button with large rounded corners
text-onlyNo background or border — pure text label

Bar Labels

Horizontal bars with an opaque text background that creates a "break" in the bar — classic LCARS header style.

PresetDescription
bar-label-baseBar label foundation — filled button, auto-scaling text, centered
bar-label-leftBar label with left-aligned text
bar-label-centerBar label with centered text
bar-label-rightBar label with right-aligned text
bar-label-squareBar label with square corners
bar-label-lozengeBar label with fully rounded ends
bar-label-bullet-leftBar label with flat left, rounded right
bar-label-bullet-rightBar label with rounded left, flat right
bar-label-capped-leftBar label with rounded left, flat right
bar-label-capped-rightBar label with flat left, rounded right

Card Options

OptionTypeDescription
typestringcustom:lcards-button (required)
entitystringEntity to monitor and control
presetstringButton shape preset — see Presets
componentstringComponent type: dpad or alert — see Component Mode: D-pad
svgobjectCustom SVG config — see Custom SVG Mode
interactivebooleantrue by default. Set false to suppress hover effects — see Decorative Buttons
ranges_attributestringEntity attribute for range conditions — see Range Conditions
state_attributestringAttribute whose string value drives exact-key colour matching — see state_attribute
state_classificationobjectOverride which state bucket unmapped states fall into (else: default|active|inactive) — see state_classification
rangeslistState-driven preset switching — see Component Mode: Alert
controlobjectControl behaviour — see Control
show_iconbooleanShow/hide the icon (default: true)
iconstringMDI icon (e.g. mdi:lightbulb)
icon_areastringIcon position: left, right, top, bottom, none (default: left)
icon_area_sizenumberIcon area width/height in px (default: 60)
icon_area_backgroundstring / objectIcon area background — state map supported
icon_styleobjectAdvanced icon styling — see icon_style Object
dividerobjectDivider between icon area and content — see divider Object
dpadobjectD-pad segment config — see Component Mode: D-pad
alertobjectAlert component config — see Component Mode: Alert
styleobjectVisual styles — see style Object
shape_textureobjectSVG texture inside the button shape — see Shape Texture
filterslistCSS / SVG filters — see filters List

Control

FieldTypeDescription
control.attributestringEntity attribute to control (leave blank to control entity state directly)
yaml
control:
  attribute: brightness   # control light brightness directly

style Object

style.card

FieldTypeDescription
color.backgroundstring / objectCard background — state map supported

style.cursor

FieldTypeDescription
cursorstringCSS cursor shown on hover. Any valid CSS cursor value. Overrides the automatic cursor (which is pointer when interactive: true, default when interactive: false). Common values: pointer, default, none, not-allowed, crosshair, grab, zoom-in, help, wait, progress, move, copy, text.

style.border

FieldTypeDefaultDescription
colorstring / objectthemeBorder colour — state map supported
widthnumber / string / object0Border width in px, a theme token string, or { top, right, bottom, left } per-side
radiusnumber / string / objectthemeCorner radius in px, a theme token string, or { top_left, top_right, bottom_right, bottom_left } per-corner
yaml
style:
  card:
    color:
      background:
        default: "var(--ha-card-background)"
        active: "alpha(var(--lcards-orange), 0.08)"
  border:
    color:
      default: "var(--lcards-gray)"
      active: "var(--lcards-orange)"
    width: 2
    radius: 12          # or per-corner: { top_left: 20, top_right: 4, bottom_left: 4, bottom_right: 20 }

icon_style Object

Fine-grained control over the icon appearance and placement within its area.

FieldTypeDefaultDescription
typestringmdiIcon type: mdi, si (Simple Icons), or entity (entity state icon)
iconstring / objectMDI icon name, or a state map of icon names — overrides the top-level icon field
colorstring / objectthemeIcon colour — state map supported
sizenumber24Icon size in px
positionstringcenterIcon position within its area
xnumberAbsolute X offset in px (overrides position)
ynumberAbsolute Y offset in px (overrides position)
x_percentnumberX as percentage of icon area width (0–100)
y_percentnumberY as percentage of icon area height (0–100)
rotationnumber0Icon rotation in degrees (-360 to 360)
paddingnumber / objectPadding in px (number = all sides, or { top, right, bottom, left })
padding_leftnumberLeft padding in px — overrides padding
padding_rightnumberRight padding in px — overrides padding
padding_topnumberTop padding in px — overrides padding
padding_bottomnumberBottom padding in px — overrides padding
spacingnumber8Space between icon and text area in px
yaml
icon: mdi:thermometer
icon_area: left
icon_style:
  color:
    default: "var(--lcards-gray)"
    active: "var(--lcards-orange)"
  size: 32
  padding: 8

Per-State Icons

Set icon_style.icon to a state map to swap the icon based on entity state (including range conditions):

yaml
entity: light.tv
ranges_attribute: brightness_pct   # range keys compare against brightness 0–100 %
icon: mdi:lightbulb                # default / fallback icon
icon_style:
  icon:
    active: mdi:lightbulb
    inactive: mdi:lightbulb-off
    above:90: mdi:lightbulb-alert
    below:20: mdi:lightbulb-outline

The same resolution order as state-based colours applies (exact state → zero → ranges → non_zero → classified → default). See Range Conditions on Non-Numeric Entities for the ranges_attribute pattern.


divider Object

Thin line between the icon area and the content area.

FieldTypeDefaultDescription
colorstring / objectthemeDivider colour — state map supported
widthnumberthemeDivider thickness in px
yaml
divider:
  color: "var(--lcards-orange)"
  width: 2

filters List

CSS and SVG filters applied to the card.

FieldTypeDescription
modestringcss (default) or svg
typestringCSS type (blur, brightness, contrast, saturate, drop-shadow) or SVG primitive
valuestring / number / objectFilter parameters
yaml
filters:
  - type: blur
    value: 4

  - type: brightness
    value: 0.8

  - type: saturate
    value: 0.5

Text Fields

Multiple text labels can be placed anywhere on the card. See Text Fields for the full reference.

yaml
text:
  default:
    font_family: "Antonio, sans-serif"
    color: "var(--lcards-moonlight)"
  name:
    content: "Temperature"
    position: top-left
    font_size: 11
  value:
    content: "{entity.state}°C"
    position: center
    font_size: 28
    font_weight: bold
    color:
      default: "var(--lcards-moonlight)"
      unavailable: "var(--lcards-alert-red)"

Component Mode: D-pad

D-pad segments: center, up, down, left, right, up-left, up-right, down-left, down-right

The default key under segments applies shared config to all segments.

FieldTypeDescription
entitystringEntity for this segment (state-based colours, icons)
tap_actionobjectAction on tap — see Actions
hold_actionobjectAction on hold
double_tap_actionobjectAction on double-tap
style.fillstring / objectSegment fill colour — state map supported
style.strokestring / objectSegment stroke colour — state map supported
style.stroke-widthnumber / string / objectStroke width in px, CSS string, or state-based map
style.opacitynumber / objectSegment opacity (0–1) or state-based map
textobjectPer-segment text labels
iconstringMDI icon for this segment
animationslistSegment-specific animations
yaml
type: custom:lcards-button
component: dpad
dpad:
  segments:
    default:
      style:
        fill:
          default: "var(--lcards-gray)"
          active: "var(--lcards-orange)"
    center:
      entity: media_player.tv
      tap_action:
        action: call-service
        service: media_player.media_play_pause
        target:
          entity_id: media_player.tv
    up:
      tap_action:
        action: call-service
        service: media_player.volume_up
        target:
          entity_id: media_player.tv
    down:
      tap_action:
        action: call-service
        service: media_player.volume_down
        target:
          entity_id: media_player.tv

Component Mode: Alert

The alert component displays a Starfleet alert symbol with animated bar elements.

alert Object

FieldTypeDescription
alert.color.shapestringFill colour override for the shield shape
alert.color.barsstringStroke colour override for the bar lines
alert.custom_presetsobjectCustom or override presets merged over built-ins (keyed by preset name)
alert.segmentsobjectPer-segment fine-grained style overrides (shape, bars)

ranges List (state-driven preset switching)

FieldTypeDescription
ranges[].presetstringComponent preset name to apply when this range matches (required)
ranges[].attributestringOverride ranges_attribute for this entry only
ranges[].abovenumberMatch when value is ≥ this threshold
ranges[].belownumberMatch when value is < this threshold
ranges[].equalsstring / number / booleanMatch when value equals this
ranges[].color.shapestringTransient shape fill override while this range is active
ranges[].color.barsstringTransient bars stroke override while this range is active
yaml
type: custom:lcards-button
component: alert
preset: default          # default, red, yellow, blue, green, grey, black

# State-driven preset switching
entity: sensor.threat_level
ranges:
  - preset: red
    above: 80
  - preset: yellow
    above: 50
  - preset: default
    above: 0

Custom SVG Mode

svg Object

FieldTypeDescription
svg.contentstringInline SVG markup
svg.srcstringURL to an external SVG file
svg.viewBoxstringOverride the SVG viewBox attribute
svg.preserveAspectRatiostringSVG preserveAspectRatio value
svg.enable_tokensbooleanResolve {theme:...} tokens inside the SVG markup
svg.allow_scriptsbooleanAllow <script> elements inside the SVG (default: false)
svg.segmentsobjectInteractive segment configs keyed by element id — use default for shared config
yaml
type: custom:lcards-button
svg:
  content: |
    <svg viewBox="0 0 200 100">
      <rect id="btn-a" x="10" y="10" width="80" height="80" fill="var(--lcards-orange)" rx="8"/>
      <rect id="btn-b" x="110" y="10" width="80" height="80" fill="var(--lcards-blue)" rx="8"/>
    </svg>
  segments:
    default:
      style:
        fill:
          active: "var(--lcards-orange-medium)"
    btn-a:
      entity: light.zone_a
      tap_action:
        action: toggle
    btn-b:
      entity: light.zone_b
      tap_action:
        action: toggle

SVG elements with id attributes become interactive segments.

Note: When using CSS custom properties in SVG fill attributes, browser support can vary. Using currentColor in the SVG with CSS color styling via JavaScript is a reliable cross-browser alternative. The example above works in modern browsers and the HA web app.


Shape Texture

shape_texture renders an SVG-native texture or animation inside the button shape fill — clipped to the shape boundary. Available in preset mode only. Elbow cards also support this feature.

yaml
shape_texture:
  preset: fluid
  opacity: 0.4            # 0–1, or state-based map
  mix_blend_mode: screen
  speed: 1.0              # 0 = static
  config: {}

Available Presets

PresetDescriptionKey Config
gridScrolling orthogonal grid linesline_spacing, pattern (both/horizontal/vertical)
diagonalScrolling diagonal hatchingline_spacing
hexagonalScrolling hexagonal gridhex_radius
dotsScrolling dot griddot_radius, spacing
fluidOrganic swirling fractalNoisebase_frequency, num_octaves
plasmaDual-colour turbulence washcolor_a, color_b, base_frequency
shimmerDirectional light-sweepangle, highlight_width, speed
flowDirectional streaming currentswave_scale, scroll_speed_x
levelFill bar with optional wavefill_pct, direction, wave_height
pulseBreathing radial glowradius, min_size, speed
scanlinesCRT-style scan-line overlayline_spacing, direction
imageUser-supplied image clipped to shapeurl, size, position, repeat
All color fields accept var(--lcards-*), {theme:...}, rgba(), hex, or a state-based map.

For full parameter reference see Shape Texture System.


Background Animations

See Background Animations for full docs.

yaml
background_animation:
  - preset: grid
    config:
      line_spacing: 40
      color: "alpha(var(--lcards-orange), 0.3)"

Decorative / Non-Interactive Buttons

By default every button shows a pointer cursor and changes colour on hover. For purely decorative panels that should not signal interactivity, set interactive: false.

What changesinteractive: true (default)interactive: false
Cursor on hoverpointer (hand)default (arrow)
Background colour on hoverChanges to hover colour from preset/styleNo change
Hover animationsFireSuppressed
Tap / hold actionsFire normallyFire normally
yaml
type: custom:lcards-button
entity: light.corridor
preset: lozenge
interactive: false          # decorative — no hand cursor or hover colour change
tap_action:
  action: toggle             # action still works if you want it

To keep hover effects but override only the cursor shape, use style.cursor independently:

yaml
type: custom:lcards-button
style:
  cursor: crosshair          # any valid CSS cursor string

Annotated Example

A lozenge button with entity binding, state-based colours, templates, an animation, and actions:

yaml
type: custom:lcards-button
entity: light.workbench
preset: lozenge

text:
  default:
    font_family: "Antonio, sans-serif"
  label:
    content: Workbench
    position: top-left
    font_size: 11
    text_transform: uppercase
    color: "var(--lcards-moonlight)"
  value:
    content: "[[[return entity.state === 'on' ? Math.round(entity.attributes.brightness / 255 * 100) + '%' : 'Off']]]"
    position: center
    font_size: 26
    font_weight: bold
    color:
      default: "var(--lcards-moonlight)"
      inactive: "var(--lcards-gray)"

icon: mdi:desk-lamp
icon_area: left
icon_style:
  color:
    default: "var(--lcards-gray)"
    active: "var(--lcards-orange)"
  size: 28

style:
  border:
    color:
      default: "var(--lcards-gray)"
      active: "var(--lcards-orange)"
    width: 2

tap_action:
  action: toggle

hold_action:
  action: more-info

animations:
  - trigger: on_tap
    preset: bounce
    params:
      scale_max: 1.05
      bounces: 2
    duration: 400

  - trigger: on_entity_change
    entity: light.workbench
    to_state: "on"
    check_on_load: true
    preset: glow
    params:
      color: "var(--lcards-orange)"
      blur_max: 12
    loop: true