How Does SMIL restart="never" Prevent Re-Triggering?
In SMIL (Synchronized Multimedia Integration Language) and SVG
animations, setting restart="never" ensures that an
animation element runs exactly once across its document timeline. When
user interactions or event conditions are bound to the
begin attribute, this setting instructs the timing engine
to ignore all subsequent triggering events after the initial activation,
effectively disabling re-invocation.
The SMIL Instance Time List
The SMIL timing model relies on dynamic lists of "instance times" for
both the start and end of an animation. When an animation uses
interactive triggers, such as begin="button.click", the
browser registers event listeners on the referenced element. Each time
the specified user action occurs, the timing engine attempts to resolve
and insert a new start time into the animation's instance list.
The restart attribute dictates how the timing engine
handles these incoming events:
always(default): Adds a new start time on every trigger, resetting or interrupting any active playback.whenNotActive: Allows adding a new start time only if the current animation cycle has completed.never: Restricts the instance list to a single start time for the entire document session.
Event Processing Under
restart="never"
When restart="never" is declared on an element such as
<animate> or <animateTransform>,
the engine evaluates the first qualifying event, resolves the start
time, and initiates playback.
Once that first start time is established, the SMIL engine flags the element as non-restartable. Subsequent user interactions—such as repeated mouse clicks, hover events, or DOM dispatch events—still fire in the DOM, but the SMIL scheduler discards them. Because no additional start instances are added to the timeline, the animation cannot be restarted, queued, or looped through interactive triggers.
Practical Application and State Persistence
Using restart="never" is standard for creating one-time
transitions and single-use interactive UI elements in SVG. Combined with
fill="freeze", the element transitions to its final state
and locks permanently against further user input, preventing animation
glitching caused by rapid clicking or overlapping triggers.