A comprehensive Elm package for smooth, high-performance DOM animations and scrolling.
One API. Multiple Engines.
Elm Motion gives you a consistent builder API for configuring animations and scrolls across multiple Engines.
Define your animations once, then run them with any Engine.
-- Define once
fadeIn : AnimBuilder eng -> AnimBuilder eng
fadeIn =
Opacity.begin
>> Opacity.from 0
>> Opacity.to 1
>> Opacity.end
-- Use with any Engine
Transition.animate model.animState <|
Transition.for "entranceAnim"
>> fadeIn
Keyframe.animate model.animState <|
Keyframe.for "entranceAnim"
>> fadeIn
Sub.animate model.animState <|
Sub.for "entranceAnim"
>> fadeIn
WAAPI.animate model.animState <|
WAAPI.for "entranceAnim"
>> fadeIn
ScrollTimeline.animate motionCmd Document <|
ScrollTimeline.for "entranceAnim"
>> fadeIn
ViewTimeline.animate motionCmd <|
ViewTimeline.for "entranceAnim"
>> fadeInThe builder API makes animations and their building blocks composable, so you can easily build animations from smaller pieces.
-- Standard timing for all animations
standardTiming : AnimBuilder eng -> AnimBuilder eng
standardTiming =
Transition.duration 300
>> Transition.easing QuadOut
-- Define animations
fadeIn : AnimBuilder eng -> AnimBuilder eng
fadeIn =
Opacity.begin
>> Opacity.to 1
>> Opacity.end
slideIn : AnimBuilder eng -> AnimBuilder eng
slideIn =
Translate.begin
>> Translate.toX 0
>> Translate.end
-- Compose together
Transition.animate model.animState <|
Transition.for "headerEntranceAnim"
>> standardTiming
>> fadeIn
>> slideInThe same philosophy applies to scrolling — define once, use with any Scroll Engine.
-- Define once
scrollToSection : ScrollBuilder -> ScrollBuilder
scrollToSection =
Scroll.forDocument
>> Scroll.toElement "section-id"
>> Scroll.speed 500
>> Scroll.build
-- Use with any Scroll Engine
Cmd.scroll ScrollDone scrollToSection
Task.scroll scrollToSection
Sub.scroll ScrollMsg model.scrollState scrollToSectionelm install phollyer/elm-motionimport Anim.Builder exposing (AnimBuilder)
import Anim.Engine.Transition as Transition
import Anim.Property.Opacity as Opacity
import Process
import Task
-- 1. Initialize state, then trigger the fade once the header has painted at opacity 0
type alias Model =
{ animState : Transition.AnimState }
init : ( Model, Cmd Msg )
init =
( { animState =
Transition.init <|
[ Opacity.init "headerAnim" 0 ]
}
, Process.sleep 0
|> Task.perform (always Animate)
)
-- 2. Define your animation
fadeInHeader : AnimBuilder eng -> AnimBuilder eng
fadeInHeader =
Opacity.begin
>> Opacity.to 1
>> Opacity.end
-- 3. Trigger it
type Msg
= Animate
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Animate ->
( { model | animState =
Transition.animate model.animState <|
Transition.for "headerAnim"
>> Transition.duration 400
>> fadeInHeader
}
, Cmd.none
)
-- 4. Render
view : Model -> Html Msg
view model =
Html.div
(Transition.attributes "headerAnim" model.animState)
[ Html.text "Animated header with logo and nav" ]import Scroll.Builder as Scroll
import Scroll.Engine.Cmd as Cmd exposing (ScrollBuilder)
-- 1. Define your scroll
scrollToSection : String -> ScrollBuilder -> ScrollBuilder
scrollToSection targetId =
Scroll.forDocument
>> Scroll.toElement targetId
>> Scroll.speed 400
>> Scroll.build
-- 2. Trigger it
type Msg
= ScrollTo String
| ScrollComplete
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ScrollTo targetId ->
( model
, Cmd.scroll ScrollComplete <|
scrollToSection targetId
)
ScrollComplete ->
( model, Cmd.none )
-- 3. Render
view : Model -> Html Msg
view _ =
-- Your scrollable contentThe WAAPI, ScrollTimeline and ViewTimeline engines require the
@phollyer/elm-motion
JavaScript companion.
npm install @phollyer/elm-motionThe companion carries its own version number, separate from the Elm package -
any 1.x companion works with any 1.x Elm package.
See the npm package README for setup, port wiring and error reporting.
Full documentation at phollyer.github.io/elm-motion
linear easing functionElm Motion is free and open source, built and maintained in my own time. If it helps you or your team, please consider sponsoring my work on GitHub - it directly supports the ongoing development of elm-motion and my other Elm packages. You can sponsor monthly or make a one-time donation of any amount.
Company and Corporate sponsors are featured below. Individual backers and fans are listed in SPONSORS.md. Thank you to everyone who helps keep this work going. 💖
Corporate Sponsors
Your logo here — become a Corporate Sponsor.
Company Sponsors
Your logo here — become a Company Sponsor.
Uses code from linuss/smooth-scroll.
The JavaScript companion bundles scroll-timeline-polyfill (Apache-2.0).
BSD-3-Clause