How Does fill Freeze Differ From fill Remove in SMIL?
In SVG Synchronized Multimedia Integration Language (SMIL)
animations, the fill attribute determines the final state
of an animated property once the animation sequence reaches its end.
Setting fill="freeze" preserves the target element's final
animation value indefinitely after completion, locking the animated
attributes in place. Conversely, setting
fill="remove"—which is the default SMIL behavior—causes the
animated property to discard its animated values and instantly snap back
to its original pre-animation state the moment the duration
finishes.
Understanding the distinction between these two values is critical for crafting predictable vector animations, state changes, and interactive user interfaces without relying on external JavaScript.
Understanding the SMIL
fill Attribute
The fill attribute in SMIL timing borrows concepts
directly from multimedia scheduling standards rather than standard SVG
presentation styling (like paint fills). In SMIL, fill
answers a simple question: what should happen to the presentation values
during the post-active animation interval?
When an animation begins, it overrides or augments an element's base
value. When the specified duration (dur) ends, SMIL must
decide whether to continue applying the animation's influence or clear
it from the rendering pipeline.
The Behavior of
fill="remove"
fill="remove" is the default setting for any SMIL
animation where the fill attribute is omitted.
Under fill="remove", the animation actively manipulates
the target attribute only for the duration specified by
dur. The moment the active duration elapses, the
animation's effect ceases entirely. The animated property reverts to
whatever value it held prior to the animation starting (or to whatever
base value is defined elsewhere in the stylesheet or attribute
list).
Key Characteristics of
fill="remove"
- Default SMIL Behavior: Requires no explicit declaration.
- Instant Reversion: No transition occurs; values jump back immediately upon completion.
- Looping Compatibility: Ideal for discrete, repeating animations that must start cleanly from their initial base value every cycle.
Code Example:
fill="remove"
<svg width="200" height="100" xmlns="http://www.w3.org/2000/svg">
<!-- The circle starts at cx="20", moves to cx="180", then immediately snaps back to cx="20" -->
<circle cx="20" cy="50" r="15" fill="crimson">
<animate
attributeName="cx"
from="20"
to="180"
dur="2s"
fill="remove" />
</circle>
</svg>The Behavior of
fill="freeze"
fill="freeze" keeps the animation active beyond its
nominal duration by extending the final calculated value into an
indefinite post-active phase.
Once the animation completes, SMIL "freezes" the visual state of the
animated attribute at the exact terminal value defined by the
to attribute, the last item in a values list,
or the final frame of a path transformation. The underlying SVG DOM base
value does not permanently change, but the rendered presentation layer
remains fixed on that final frame.
Key Characteristics of
fill="freeze"
- State Persistence: Keeps UI elements in their end state (e.g., icons transforming into "active" states).
- Stacking Transitions: Allows sequential animations to pick up where the previous animation left off without visual flicker.
- Presentation-Layer Override: The element appears modified on screen without requiring script-based DOM manipulation.
Code Example:
fill="freeze"
<svg width="200" height="100" xmlns="http://www.w3.org/2000/svg">
<!-- The circle starts at cx="20", moves to cx="180", and stays permanently at cx="180" -->
<circle cx="20" cy="50" r="15" fill="seagreen">
<animate
attributeName="cx"
from="20"
to="180"
dur="2s"
fill="freeze" />
</circle>
</svg>Comparative Overview
| Feature | fill="freeze" |
fill="remove" |
|---|---|---|
| Default Setting | No | Yes |
| Post-Active State | Retains the final animation value | Reverts to the pre-animation base value |
| Common Use Cases | One-way transitions, modal reveals, UI toggles | Pulsing effects, repeating loops, temporary hover states |
| DOM Value Impact | Presentation layer locked; base DOM attribute unchanged | Presentation layer cleared; base DOM attribute unchanged |
| Chained Animations | Seamless handoff to subsequent animations | Can cause visible snap-back glitches if chained without care |
Choosing Between Freeze and Remove
Choose fill="freeze" when the animation represents a
state change, such as expanding an accordion icon, fading in a
persistent element, or drawing an SVG path to completion. Choose
fill="remove" when designing ambient, looping, or transient
animations where returning to the base graphic is the intended
outcome.