Nice article and examples, but this seems like an exceptionally complicated and prone-to-bugs solution for what is ultimately a nice to have. I'm all for subtle UI sugar, I pay it a lot of attention in my own work, but subtlety (and usability) really is key IMO.
I was clicking through on Firefox android and noticed a small number of minor things, incl. bounding box issues, animations that went off screen, and glitches when an example was toggled while in motion. Not sure if these are intentional (or expected). No doubt easily fixed. But they paint a picture for edge cases. I'm sure there's some amazing use cases for these techniques, but there's also a good case for simple CSS (and restraint!)
This is a home-grown solution but the version in Framer is extensively tested (though still not perfect ofc).
The version in Framer has stuff like infinitely deep scale correction and shared element transitions so because of the filesize overhead (~10kb) I would only use this for complex stuff that is otherwise prohibitively tough (shared element transitions, layout etc).
However I do want to make the point that this approach should be more robust and simpler to maintain for even simple examples.
If you imagine an iOS-style pill toggle. The "simplest" way to animate this would be to have `translateX(0)` when off and something like `translateX(100px)` when on.
However, if there were no animations, this isn't how you'd write it. You'd probably do something like switch `flex-start` to `flex-end` on the parent.
This is easier to change the design and also maintain between breakpoints. But it can't be animated. Except with these technique, where you'd simply write
Hey thanks for the detailed response. I'm actually all for progressive enhancement, and appreciate the philosophy you're getting at here. I still think, generally speaking, you're either designing for animation or not. With CSS, if something works with a transition it also works without. Once you start meddling with animation states in JS you've taken point on all that otherwise abstracted away state-based logic. What happens when an animation get interrupted, memory use, timing functions, etc. Sure, if you weren't animating a pill-box you might use flex. But if a transform works, why not use that for both animated and inanimate versions? It's certainly not any less correct or legible.
Excellent article. Explains the FLIP concept in CSS animation performance. Doesn't really have much to do with Framer, besides it being the inspiration for the article
One thing I noticed that often isn't caught due to platform differences is when "Hide types" is pressed, a scrollbar will appear on most browsers on Windows 10. This draws the eye so harshly that most - if not all - of the magic of the animation is ruined.
I wish that Windows 10 had an option to "hide scrollbars until necessary" like macOS does, but sadly this continues to be a bit of an edge case for FE work.
Given Edge’s recent work on overlay scrollbars (#edge-overlay-scrollbars-win-style flag) that are still displayed at all times for any element with overflow: scroll, only slimmer, I’m not holding my breath.
So you can hide the scrollbars in CSS if you want to, but doing so is also an accessibility pipe-bomb waiting to happen: things in motion in visually impaired systems plus no scroll bars when navigating a space is hellacious.
Framer takes a slightly different approach in their docs which appears to be a mixture of pinning objects down and shoving margins around as well.
I use Framer on some projects and I love its declarative approach to creating nice animations. It allows someone like me who doesn't know much about the topic to create really nice experiences.
But one thing that has been confusing me is its performance. The same simple animation might be smooth 60fps 9 times out of 10, but chug significantly the 10th time, on the same device etc. Any advice on how to profile this?
I would start with the Performance tab in Chrome. Or if you're on a mobile device double checking you're not in low-powered mode, where animations are throttled to 30fps.
I've recently had a similar problem making a game with javascript. I stated making it render with plain dom elements and transforms because it was simpler, however I noticed that sometimes it stuttered.
After looking at performance tab it turned out that dom modifications trigger uBlock to run it's internal checker(presumably to check in case you are adding some ads onto the page). It's not a problem in a normal circumstances, but when you are updating dom 10+ times a second it sometimes chugs. Rewrote rendering to use canvas and the problem went away.
Love the website style and interactiveness, in particular those sections that can be expanded for that extra bit of explanation that makes all the difference!
One thing it didn't explain (or I might've missed): How do you animate the neighbors this way when a component changes? Aka if my size increases it shows how to animate that, but without doing anything else the neighbor component would just jump to its new position, or?
I was clicking through on Firefox android and noticed a small number of minor things, incl. bounding box issues, animations that went off screen, and glitches when an example was toggled while in motion. Not sure if these are intentional (or expected). No doubt easily fixed. But they paint a picture for edge cases. I'm sure there's some amazing use cases for these techniques, but there's also a good case for simple CSS (and restraint!)
The version in Framer has stuff like infinitely deep scale correction and shared element transitions so because of the filesize overhead (~10kb) I would only use this for complex stuff that is otherwise prohibitively tough (shared element transitions, layout etc).
However I do want to make the point that this approach should be more robust and simpler to maintain for even simple examples.
If you imagine an iOS-style pill toggle. The "simplest" way to animate this would be to have `translateX(0)` when off and something like `translateX(100px)` when on.
However, if there were no animations, this isn't how you'd write it. You'd probably do something like switch `flex-start` to `flex-end` on the parent.
This is easier to change the design and also maintain between breakpoints. But it can't be animated. Except with these technique, where you'd simply write
<motion.div layout />
And it would be. Much more maintainable.
Agreed. The “magic” is just CSS used effectively, explained elegantly.
One thing I noticed that often isn't caught due to platform differences is when "Hide types" is pressed, a scrollbar will appear on most browsers on Windows 10. This draws the eye so harshly that most - if not all - of the magic of the animation is ruined.
I wish that Windows 10 had an option to "hide scrollbars until necessary" like macOS does, but sadly this continues to be a bit of an edge case for FE work.
Framer takes a slightly different approach in their docs which appears to be a mixture of pinning objects down and shoving margins around as well.
But one thing that has been confusing me is its performance. The same simple animation might be smooth 60fps 9 times out of 10, but chug significantly the 10th time, on the same device etc. Any advice on how to profile this?
Would love to hear what you find!
After looking at performance tab it turned out that dom modifications trigger uBlock to run it's internal checker(presumably to check in case you are adding some ads onto the page). It's not a problem in a normal circumstances, but when you are updating dom 10+ times a second it sometimes chugs. Rewrote rendering to use canvas and the problem went away.
Might me something similar here.
For those copying/getting inspired by the code, don't forget to add the missing empty-array for the useLayoutEffet dependency param.
You need to run it without the dependency array or add all layout-changing props and state to it.
https://svelte.dev/repl/a1628b3298eb4a91a840578aaf056574?ver...
Since it's using float: right to realign the box, add more items to the array to see what happens