Animating React with Finesse
Nikhil Sharma, SDE II Postman
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348374/Mypicture__1_.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348373/looking_up.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348385/WhatsApp_Image_2024-05-21_at_1.50.24_AM.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348384/WhatsApp_Image_2024-05-21_at_1.48.42_AM.jpeg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348383/WhatsApp_Image_2024-05-21_at_1.49.37_AM.jpeg)
Hey, I'm Nikhil 👋
I love to talk about performance, react and design systems
nik72619c
Â
     niksharma1997
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348390/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348394/pasted-from-clipboard.png)
"Everything that you do is an animation"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348359/progressive-web-app-illustration-gif-animation-banner.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348358/1_nZfHYlIIH_WmTuibO-vZzQ.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348357/Adding-a-task.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348361/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348362/image_processing20191116-9633-1xak0mh.gif)
Why do the frames drop?
There's a deadline to produce each frame...
1000ms/60fps = 16.7ms per frame
let myBox = document.querySelector('.my-box');
if (myBox) {
myBox.classList.add('my-special-box')
}
1
oh, something changed! I need to generate a new frame.
3
I need to calculate how much space they take on the screen and where they should be positioned
5
 Now, I should combine these bitmaps in the defined order to form the final frame.
2
now I must apply class my-special-class
 to to that <div>
 element).
4
 I should group elements (that have an output) in multiple layers and convert each layer into a bitmap representation in the memory or the video RAM.
1
JS evaluation
3
Layout
5
Composition
2
Style calculation
4
Paint
Which is ...
Why do we need to know all this?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11336130/pasted-from-clipboard.png)
Optimised pipeline = optimised animations
#1: Avoid reflows
Avoid the CSS properties that cause recalculations like display, instead use visibility or opacity
.element {
opacity: 1;
transition: .3s;
}
.element.closed {
opacity: 0;
pointer-events: none;
}
Make elements paint-ready
the will-change property lets the browser know which elements are paint-expensive.
.box { will-change: auto;}
Optimising JS Animations
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11344759/pasted-from-clipboard.png)
setInterval()
useEffect(() => {
const intervalId = setInterval(() => {
if (circleRef.current) {
position += speed * direction;
if (position >= distance || position <= 0) {
direction *= -1;
}
circleRef.current.style.transform = `translateX(${position}px)`;
// Additional work to make the setInterval animation more intensive
for (let i = 0; i < 10000000; i++) {}
}
}, 16); // Roughly 60fps
return () => clearInterval(intervalId);
}, []);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348351/pasted-from-clipboard.png)
setInterval()
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11344760/pasted-from-clipboard.png)
- Does not guarantee running at the start of each call
- Runs on the main thread
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11344761/mr-bean-mr-beans-holiday.gif)
Missed frame train wagons
       😓
requestAnimationFrame()
useEffect(() => {
const animate = () => {
if (circleRef.current) {
position += speed * direction;
if (position >= distance || position <= 0) {
direction *= -1;
}
circleRef.current.style.transform = `translateX(${position}px)`;
// Additional work to make the animation more intensive
for (let i = 0; i < 10000000; i++) {}
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
return () => cancelAnimationFrame(animate);
}, []);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348352/pasted-from-clipboard.png)
requestAnimationFrame()
- Functions are run at the start instead
- Runs when the browser is ready to paint
- Auto-optimised resource management
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11344762/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348410/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348988/giphy.gif)
CSS is better than js?
- Hardware-accelarated
- Runs on compositor-thread
- Browser-controlled
- Complex animations
CSS is better than js?
useEffect(() => {
const circle = circleRef.current;
if (circle) {
circle.animate(
[{ transform: "translateX(0)" }, { transform: "translateX(200px)" }],
{
duration: 2000,
iterations: Infinity,
direction: "alternate",
}
);
}
}, []);
.circle {
width: 50px;
height: 50px;
background-color: blue;
border-radius: 50%;
position: relative;
animation: moveCircle 2s infinite alternate;
}
@keyframes moveCircle {
from {
transform: translateX(0);
}
to {
transform: translateX(200px);
}
}
CSS
Web Animation API
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348410/pasted-from-clipboard.png)
Using libraries
They are battle-tested, apply all such performance optimisations out of the box
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11346832/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11346838/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11346840/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11346832/pasted-from-clipboard.png)
import React from 'react';
import { motion } from 'framer-motion';
const CircleAnimationFramerMotion = () => {
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<motion.div
animate={{ x: [0, 200, 0] }}
transition={{ duration: 2, repeat: Infinity, repeatType: 'reverse' }}
style={{
width: '50px',
height: '50px',
backgroundColor: 'red',
borderRadius: '50%',
}}
></motion.div>
</div>
);
};
export default CircleAnimationFramerMotion;
Efficiency is doing things right; effectiveness is doing the right things.
– Peter Drucker
Intersection Observer API
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
setIsIntersecting(entry.isIntersecting);
});
},
{ threshold: 0.1 } // Adjust the threshold as needed
);
if (circleRef.current) {
observer.observe(circleRef.current);
}
return () => {
if (circleRef.current) {
observer.unobserve(circleRef.current);
}
};
}, []);
getBoundingClientRect()
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11346946/pasted-from-clipboard.png)
Avoid recalculations
items.forEach((item) => {
item.style.transform =
"translateY(" + container.getBoundingClientRect().height + "px)";
});
// VS
const containerHeight = container.getBoundingClientRect().height + "px";
items.forEach((item) => {
item.style.transform = "translateY(" + containerHeight + "px)";
Debounce and throtlling
const throttleTime = 100;
function onScroll(event) {
if (Date.now() > prevTime + throttleTime) {
callback();
}
}
window.addEventListener("scroll", onScroll);
![](https://s3.amazonaws.com/media-p.slid.es/uploads/983750/images/11348320/pasted-from-clipboard.png)
- Pixel pipeline
- Using the lighter css styles
- Optimising js animations using requestAnimationFrame
- Using CSS animations + web API
- Avoiding redundant work
Quick recap!
Important Links
Thank You!
Questions?
Process
During the ideation phase, expect to discuss the project in depth to clearly understand the goals and requirements.
1
Ideation
Our team makes each part of the build phase seamless with regular check-ins and deliverables.
2
Build
It's time to take the product live - the end if the build phase but the beginning of being in market.
3
Launch
Philosophy
Once all is removed that can be removed, that is how designs are truly in their simplest form.
Meet the Team
CFO
George
CEO
Elaine
Advisor
Susan
Our Services
We offer a variety of services and plans tailored to business needs of any kind and of any size.
- Thoughtful process
- Dedicated team
- Pixel-perfect work
- 24/7 support
ACME
Competitors
- Fragmented workflow
- Too many clients
- Rushed deliveries
- 9-5 support
1
Discovery of requirements for a project.
3
Creating a Plan that sets the requirements for the design and build phases.
5
Build the project to an MVP to test and evaluate. Iterate using these learnings.
2
Research into the project space, competitors and the market.
4
Review and Iterate on the designs with testing of ideas, client feedback and prototypes.
- Conceptualization
- Product Design
- Development
- UI/UX Testing
- Branding
Our Services
ACME Offices
Country | City | Contact |
---|---|---|
USA | Los Angeles | +1 555 0194 |
USA | New York | +1 555 0142 |
Sweden | Stockholm | +46 555 0077 |
UK | London | +44 555 0211 |
South Korea | Seoul | +82 555 0138 |
The Summit is what drives us, but the climb itself is what matters.
– Conrad Anker
Available 24/7
Contact us via email or phone
Photo by Raimond Klavins
ACME Design Inc started a two-person operation in 2011. In their hometown of Los Angeles, California, the founders came together with a vision to design and build beautiful, simple web and mobile products.
In ten years, the team has grown to over one hundred members with offices in four countries. In that time the goal has always remained the same: to design impactful solutions to complex problems.
Our Story
Thank You!
Questions?
Palette
By nik72619c
Palette
- 68