Library for animating layout changes perfomantly using the FLIP technique
Use cases:
- List reordering
- DOM node additions/removals
- Shared element transitions
- Animating "unanimatable" CSS properties(e.g.
display
,flex-direction
,grid-template-rows
)
Highlights:
- Smallish footprint(~2kB gzipped)
- Handles nested DOM structures by compensation for parent transforms
- Automatically detects DOM changes by leveraging MutationObservers
- Shared element transition(basic)
- Shared element transition(advanced)
- Personal site
- Grid animations
- List reordering
NPM:
npm install mjukna
CDN:
- https://cdn.jsdelivr.net/npm/mjukna/dist/browser.js
- https://unpkg.com/[email protected]/dist/browser.js
// Register all list items
mjukna(document.querySelectorAll('li'));
// Remove the first one one
document.querySelector('li').remove();
Will result in:
Type: Element
| iterable of Element
s | Array of objects
Type: object
staggerBy
-Number
in milliseconds to delay each element withenterFilter
- predicatefunction
that gets called for each element added to the DOM. Returntrue
to run enter animation.enterAnimation
- Hook to run custom enter animations. The provided function will be called with to arguments, the element and a done callback.exitAnimation
- Same asenterAnimation
but for removed DOM nodesspring
- Parameters for the spring physics
Example including all available options:
{
staggerBy: 20,
enterFilter: (element) => element.classList.contains('list-item'),
enterAnimation: (element, done) => externalLibFadeIn(element).then(done),
exitAnimation:(element, done) => externalLibFadeOut(element).then(done),
spring: {
stiffness: 10,
damping: 0.5
}
}
When an element enters the DOM, an anchor element can be set as the origin for element. The added element will be transformed to the same size/position as the anchor element and then animated to its normal position.
As an example, making a modal expand from a button might look something like this:
mjukna({
anchor: document.querySelector('modal-button'),
element: () => document.querySelector('modal')
})
const modal = document.createElement('div');
modal.classList.add('modal');
document.body.appendChild(modal);
One common problem when using FLIP animations is that nested content can get distorted, especially text content. This library solves this by keeping track of parent child relations and applies compensating transforms to child elements.
Say an element with a text element should double in width while the text should change from left-align to right. This can be achieved with the following mjukna code:
.box {
width: 200px;
background: chocolate;
}
.box h2 {
display: inline-block;
}
.box.big {
width: 400px;
text-align: right;
}
<div class="box">
<h2>Brown Fox</h2>
</div>
mjukna(document.querySelectorAll('.box, .box h2'));
document.querySelector('.box').classList.add('big')
Note that we need to register both the parent and the child.
Also note that the example changes width
and text-align, only the transform
-property is changed by the library. That's the magic of FLIP :)
When animating text you need to keep two things in mind:
- The containing element must fully enclose the text(e.g. inline-block)
- If text in the first or the final position wraps multiple lines, each word needs to be wrapped in an inline-block element.
Example:
.box {
width: 70px;
background: chocolate;
text-align: center;
}
.box span {
display: inline-block;
}
.box.big {
width: 200px;
font-size: smaller;
}
<div class="box">
<h2><span>One</span> <span>two</span> <span>three</span></h2>
</div>
mjukna(document.querySelectorAll('.box, .box span'));
document.querySelector('.box').classList.add('big')
Say hi on Twitter