Use an element's position in the viewport to drive animation progress.
Animations run automatically as the element moves through view, so you do not need an AnimState.
update and subscriptions are optional and only matter when you want events.
📖 For setup, browser support, and examples, see the ViewTimeline Engine Documentation and the Engine Overview.
Type alias for the animation group name.
Select the animation group that subsequent property builders will target.
ViewTimeline.for "hero-card"
>> Opacity.begin
>> Opacity.from 0
>> Opacity.to 1
>> Opacity.end📖 See Triggering Animations for details.
Fire-and-forget view-driven animation using the browser's ViewTimeline.
port motionCmd : Encode.Value -> Cmd msg
ViewTimeline.animate motionCmd <|
ViewTimeline.for "hero-card"
>> Opacity.begin
>> Opacity.from 0
>> Opacity.to 1
>> Opacity.end📖 See Event Reference for details.
Lifecycle events from the ViewTimeline engine.
Started String — the element entered the animation range. Fires every
time the element re-enters range, not just on the first entry.Ended String — the element scrolled past the end of the animation rangeCancelled String — the animation was cancelled (e.g. element removed)Iteration String Int — the animation looped; the Int is the cumulative iteration countProgress String Float — the timeline's current progress (0..1) while in range.
Only emitted when withProgressEvents True was set on the builder.AnimError String — a message arrived but could not be decodedOpt in to per-frame Progress events.
Off by default.
Progress events can create a lot of noise in your update loop,
especially when debugging the Msg flow in your app. Therefore
they are suppressed by default and you need to explicitly opt in
to receive them.
This is a precedence function, so it can operate as a global setting for all groups in the builder chain, or you can set it on a per-group basis which overrides any global setting for that group.
ViewTimeline.withProgressEvents True -- global setting
>> ViewTimeline.for "box"
>> ViewTimeline.withProgressEvents False -- overrides global for this group
>> ... -- other buildersSet the minimum interval in milliseconds between per-frame
propertyUpdate emissions from the JavaScript runtime.
The visual animation is driven by the browser compositor and is never affected by this setting - it only controls how much port traffic is generated.
This is a precedence function, so it can operate as a global setting for all groups in the builder chain, or you can set it on a per-group basis which overrides any global setting for that group.
0 (the default) to emit on every requestAnimationFrame tick.16 for ~60 Hz, 33 for ~30 Hz.Note: Higher throttle values reduce Elm-side mid-flight precision for queries and interruption bookkeeping.
ViewTimeline.setUpdateThrottle 33 -- global default
>> ViewTimeline.for "hero"
>> ViewTimeline.setUpdateThrottle 0 -- dense updates for interactions
>> ViewTimeline.for "background"
>> ViewTimeline.setUpdateThrottle 50 -- lower traffic for passive motion
>> ... -- other builders📖 See React for details.
Message type used with update.
type Msg
= GotViewMsg ViewTimeline.AnimMsg
| ...Turn an engine message into an event.
Messages that do not belong to this engine return Nothing.
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GotViewMsg animMsg ->
case ViewTimeline.update animMsg of
Just (ViewTimeline.Ended animGroup) ->
...
_ ->
( model, Cmd.none )📖 See Subscriptions for details.
Subscribe to lifecycle events for this engine.
This is only required if you want to receive events.
subscriptions : Model -> Sub Msg
subscriptions _ =
ViewTimeline.subscriptions GotViewMsg motionMsg📖 See Render for details.
Attach the animation group identifier to an element.
div (ViewTimeline.attributes "hero-card") [ ... ]Use horizontal viewport tracking for the timeline.
Vertical scroll is the default, so this is only needed when the container scrolls horizontally.
-- Animate an element entering from the side in a horizontal layout
ViewTimeline.animate motionCmd <|
ViewTimeline.horizontal
>> ViewTimeline.for "slide"
>> Opacity.begin
>> Opacity.from 0
>> Opacity.to 1
>> Opacity.end📖 See Range for details.
The unit for a Range offset value.
Perc — percentage of the named range (Cover 20 Perc → cover 20%)Px — fixed pixel offset (Cover 100 Px → cover 100px)A position along the view timeline, used to configure rangeStart and rangeEnd.
Each constructor takes a numeric value and a Unit:
rangeStart (Entry 0 Perc) -- entry 0%
rangeEnd (Exit 100 Px) -- exit 100pxSet when the animation starts relative to the element's position in the viewport.
Optional — defaults to Cover 0 Perc when not called.
This is a precedence function, so it can act as a global default for the
whole builder chain or be set after for to override the range for a
specific group.
-- Start animating as the element enters the viewport
ViewTimeline.rangeStart (Entry 0 Perc)
>> ViewTimeline.for "section-a"
-- Give one section its own range inside the same pipeline
>> ViewTimeline.rangeStart (Entry 10 Perc)Set when the animation ends relative to the element's position in the viewport.
Optional — defaults to Cover 100 Perc when not called.
This is a precedence function, so it can act as a global default for the
whole builder chain or be set after for to override the range for a
specific group.
-- End animating as the element begins to leave the viewport
ViewTimeline.rangeEnd (Exit 0 Perc)
>> ViewTimeline.for "section-a"
-- Give one section its own range inside the same pipeline
>> ViewTimeline.rangeEnd (Exit 60 Perc)These functions are precedence functions, so they can operate as a global setting for all groups in the builder chain, or you can set them on a per-group basis which overrides any global setting for that group.
ViewTimeline.iterations 3 -- global setting
>> ViewTimeline.for "box"
>> ViewTimeline.iterations 5 -- overrides global for this group
>> ... -- other buildersSet how many times an animation should repeat.
Make an animation alternate direction on each iteration.
alternate only has a visible effect when the animation runs more than once,
so calling it when iterations is unset or 1 automatically bumps
iterations to 2. An explicit iterations count set before or after
alternate is preserved.
📖 See Easing for details.
Set the global easing function.
heroEntrance : AnimBuilder { eng | withEasing : () } -> AnimBuilder { eng | withEasing : () }
heroEntrance =
easing EaseInOut
>> fadeInHeroTitle
>> slideInHeroArtwork
>> revealPrimaryCtaSet the global spring.
draggableCardSettle : AnimBuilder { eng | withSpring : () } -> AnimBuilder { eng | withSpring : () }
draggableCardSettle =
spring Spring.wobbly
>> settleCardPosition
>> settleCardShadowSet the default length unit for all length-bearing properties.
responsivePanelMotion : AnimBuilder { eng | withCssUnit : () } -> AnimBuilder { eng | withCssUnit : () }
responsivePanelMotion =
cssUnit Unit.Vw
>> slidePanelIn
>> growPanelHeightSet the default length unit for the X axis.
responsiveDrawerMotion : AnimBuilder { eng | withCssUnit : () } -> AnimBuilder { eng | withCssUnit : () }
responsiveDrawerMotion =
cssUnitX Unit.Vw
>> slideDrawerX
>> alignDrawerLabelXSet the default length unit for the Y axis.
responsiveSheetMotion : AnimBuilder { eng | withCssUnit : () } -> AnimBuilder { eng | withCssUnit : () }
responsiveSheetMotion =
cssUnitY Unit.Vh
>> slideSheetY
>> alignSheetHeaderYSet the default length unit for the Z axis.
layeredSceneMotion : AnimBuilder { eng | withCssUnit : () } -> AnimBuilder { eng | withCssUnit : () }
layeredSceneMotion =
cssUnitZ Unit.Px
>> pushSceneBackgroundBack
>> bringFloatingCardForwardSet the default length unit used for width values in ViewTimeline animations.
responsiveCardWidth : EngineBuilder -> EngineBuilder
responsiveCardWidth =
cssUnitWidth LengthUnit.Vw
>> growCardWidth
>> settleCardSpacingSet the default length unit used for height values in ViewTimeline animations.
responsivePanelHeight : EngineBuilder -> EngineBuilder
responsivePanelHeight =
cssUnitHeight LengthUnit.Vh
>> expandPanelHeight
>> alignPanelHeaderYSet a discrete CSS property to hold during the animation.
Used for non-interpolatable properties like display or visibility that need
to be set to a specific value while the animation is active.
This function is a precedence function, so it can operate as a global setting for all groups in the builder chain, or you can set it on a per-group basis which overrides any global setting for that group.
ViewTimeline.animate motionCmd <|
ViewTimeline.discreteEntry "display" "block"
>> ViewTimeline.for "box"
>> ViewTimeline.discreteEntry "visibility" "visible"
>> Opacity.begin
>> Opacity.from 0
>> Opacity.to 1
>> Opacity.endAdd a discrete CSS property for exit animations.
Exit animations need to hold their initial state until the very end of the animation, at which point they flip to the final state. Therefore you need to set both entry and exit values for the property.
This function is a precedence function, so it can operate as a global setting for all groups in the builder chain, or you can set it on a per-group basis which overrides any global setting for that group.
Use when an element is disappearing (e.g., going from
display: block to display: none).
import Anim.Engine.ViewTimeline as ViewTimeline
import Anim.Property.Opacity as Opacity
ViewTimeline.animate motionCmd <|
ViewTimeline.discreteExit "display" "block" "none"
>> ViewTimeline.for "box"
>> Opacity.begin
>> Opacity.to 0
>> Opacity.endSet the transform order.
The transform order specifies how translate, rotate, skew and scale transforms
are combined. Start the list with the transform to apply first.
This is a precedence function, so it can operate as a global setting for all groups in the builder chain, or you can set it on a per-group basis which overrides any global setting for that group.
Any missing transforms are automatically appended in the default order
(Translate → Rotate → Skew → Scale).
import Anim.Extra.TransformOrder exposing (TransformProperty(..))
ViewTimeline.animate motionCmd <|
ViewTimeline.transformOrder [ Scale, Rotate, Translate, Skew ] -- global setting
>> ViewTimeline.for "box"
>> ViewTimeline.transformOrder [ Rotate, Translate ] -- overrides global for this group
>> Translate.begin
>> Translate.fromXY 0 0
>> Translate.toXY 100 0
>> Translate.end
Builder type for view-driven animations.
Use this in type annotations when a builder function should only work with ViewTimeline.
📖 See Engine Capabilities for patterns and examples.