Skip to content

Card Animations

LCARdS cards support anime.js-powered animations triggered by user interactions or entity state changes. Each card can have multiple animations with different triggers.

anime.js v4

LCARdS uses anime.js v4, which has a different API from v3. Key differences users should know:

  • The ease property uses v4 naming convention: inOutQuad, outElastic, inOutSine (no ease prefix). v3-style names like easeInOutQuad are passed through as-is and may work, but v4 names are preferred.
  • The easing property from v3 is not supported — always use ease.
  • Spring physics: { type: 'spring', params: { stiffness: 150, damping: 20 } } syntax is the same.

Available Presets

See the Preset Reference for full parameter tables and examples for all built-in presets.

CategoryPresets
Motionbounce, blink, fade, glow, pulse, rotate, scale, scale-reset, shake, slide, strobe
Texttext-glitch, text-reveal, text-scramble, text-typewriter
Visual Effectscascade, flicker, ripple, shimmer
SVGdraw, march
Utilitymotionpath, set

Basic Structure

Animations are defined in a card's animations array:

yaml
animations:
  - id: tap-pulse           # Optional identifier
    trigger: on_tap
    preset: pulse
  - trigger: on_entity_change
    preset: glow
    entity: binary_sensor.motion
    to_state: "on"
    params:
      color: "{theme:colors.alert.red}"

Triggers

TriggerWhen it fires
on_tapCard is tapped or clicked
on_holdLong-press on the card
on_hoverMouse enters the card
on_leaveMouse leaves the card
on_loadCard is rendered on page load
on_entity_changeA watched entity changes state

Animation Options

OptionTypeDefaultDescription
triggerstringWhen to run (required)
presetstringAnimation preset name (required)
idstringOptional identifier — alphanumeric, hyphens, and underscores only
enabledbooleantrueSet to false to disable without removing
durationnumberpreset defaultDuration in ms (0–10 000). Accepts a map_range descriptor.
delaynumber0Delay before starting (ms). Accepts a map_range descriptor.
loopboolean / numberpreset defaulttrue = infinite loop, false = once, number = iteration count
alternatebooleanpreset defaultReverse direction on each loop
easestring / objectpreset defaultEasing function — see below
paramsobjectPreset-specific parameters. Each value may be a map_range descriptor.
targetstringCSS selector or data-field-id to restrict which element animates
entitystringcard entityEntity to watch (for on_entity_change)
attributestringAttribute to read instead of entity state. Applies to from_state, to_state, and while. Use brightness_pct for a 0–100 light brightness percentage.
from_statestringFire-and-forget gate: only trigger when transitioning FROM this value
to_statestringFire-and-forget gate: only trigger when transitioning TO this value
whileobjectLifecycle condition (loop: true required): plays while true, stops when false — see Entity Change Triggers
check_on_loadbooleantrueEvaluate condition on card load. Starts a looping animation immediately if the while condition is already met, or fires once if already in to_state. Set to false to react only to state transitions after load.

to_state / from_state vs while: to_state and from_state are fire-and-forget gates — they control when an animation starts but will not stop a looping animation. Use while to auto-stop a loop when the condition clears.


map_range descriptors

Parameters that accept a number (duration, delay, any params field) can instead be a map_range descriptor that maps a live entity value linearly into the parameter range:

yaml
- trigger: on_entity_change
  entity: sensor.wind_speed
  preset: rotate
  loop: true
  params:
    speed:
      map_range:
        entity: sensor.wind_speed
        input: [0, 50]           # entity value range
        output: [2000, 200]      # animation duration — faster when windier
        clamp: true

map_range works in both inline config.animations and rule-based apply.animations.

FieldRequiredDescription
entityHA entity to read
attributeAttribute instead of state (supports brightness_pct)
input[min, max] input range
output[min, max] numeric, or ['#hex', '#hex'] for colour interpolation
clampClamp input to range (default true)

Easing Functions

LCARdS uses anime.js v4 easing names (without the ease prefix used in v3):

yaml
ease: "inOutQuad"       # Standard in-out (v4) — was easeInOutQuad in v3
ease: "outElastic"      # Elastic bounce out
ease: "inOutSine"       # Smooth sine curve
ease: "linear"          # Constant speed
ease:                    # Spring physics
  type: spring
  params:
    stiffness: 150
    damping: 20

Common easing names (v4):

CategoryNames
QuadinQuad, outQuad, inOutQuad
CubicinCubic, outCubic, inOutCubic
SineinSine, outSine, inOutSine
ExpoinExpo, outExpo, inOutExpo
ElasticinElastic, outElastic, inOutElastic
BackinBack, outBack, inOutBack
BounceinBounce, outBounce, inOutBounce
Otherlinear, steps(N)

Comprehensive Example

A button showing: load animation, tap feedback, hover glow, entity change with state filter, and a text scramble targeted to a specific field.

yaml
type: custom:lcards-button
entity: light.workbench
preset: lozenge
text:
  label:
    content: Workbench
    position: top-left
  state:
    content: "{entity.state}"
    position: center

animations:
  # Entrance animation — runs once on load
  - trigger: on_load
    preset: fade
    params:
      from: 0
      to: 1
    duration: 800

  # Tap feedback — quick bounce
  - trigger: on_tap
    preset: bounce
    params:
      scale_max: 1.08
      bounces: 2
    duration: 400

  # Hover glow — looping while mouse is over
  - trigger: on_hover
    preset: glow
    params:
      color: "var(--lcars-orange)"
      blur_max: 12

  # Entity turns on — pulse while on
  - trigger: on_entity_change
    entity: light.workbench
    preset: pulse
    loop: true
    while:
      state: 'on'
    check_on_load: true
    params:
      max_scale: 1.05

  # Entity turns off — brief fade-down
  - trigger: on_entity_change
    entity: light.workbench
    to_state: "off"
    preset: fade
    params:
      from: 1
      to: 0.7
    duration: 300
    loop: 1
    alternate: true

See Also