I have a SPA written with Elm and styled with CSS. When the view changes, a different render function will be called to render the new view. This will also stop rendering the "old" view.
The next requirement is to make view changes smooth. I want to do this as following:
Because of these requirements, for a little moment, the browser should render 2 views at the same time (both the old and the new view). This is where I'm struggling. Adding a transition (using CSS) to the new view is not difficult. However, adding CSS to the "old" view does not really work, because that view is stopped being rendered.
How can I add a nice transition between two views, where both views will be rendered next to each other for a short time and are both sliding from right to left and the opacity of the views change?
This is in general fairly difficult problem in most VDom based frameworks.
You will need to render the old view and the new view at the same time for a period of time. To be able to do that, you will need to also store a snapshot of the old model as well.
You can make a wrapper module that looks something like this:
type Animated model
= NotAnimating model
| Animating String model model
view : (model -> Html msg) -> Animated model -> Html msg
view viewFn model =
case model of
NotAnimating m -> viewFn m
Animating transitionType old new ->
Html.div [class "animated-transition", class transitionType]
[ Html.div [class "transition-out", Html.Attribute.attribute "inert" "inert" ] [ viewFn old ]
, Html.div [ class "transition-in" ] [ viewFn new ]
]
Note the inert
attribute. That will make the old view not accept user events/focus.