I've spend some time testing your repl with performance time in web browser dev tools. My conclusions are:
In modern web browser we have
- The Main thread
- The Compositor thread
The second one is really nice because helps the main thread by taking some responsibilities on itself.
Typically, the main thread is responsible for:
Running your JavaScript.
Calculating your HTML elements’ CSS styles.
Laying out your page. Painting your elements into one or more bitmaps.
Handing these bitmaps over to the compositor thread.
Typically, the compositor thread is responsible for:
Drawing bitmaps to the screen via the GPU.
Asking the main thread to update bitmaps for visible or soon-to-be-visible parts of the page.
Figuring out which parts of the page are visible. Figuring out which
parts are soon-to-be-visible when you’re scrolling.
Moving parts of the page when you scroll.
Source: http://sking7.github.io/articles/572118798.html
CSS-based animations, and Web Animations where supported natively, are
typically handled on a thread known as the "compositor thread". This
is different from the browser's "main thread", where styling, layout,
painting, and JavaScript are executed. This means that if the browser
is running some expensive tasks on the main thread, these animations
can keep going without being interrupted.
Other changes to transforms and opacity can, in many cases, also be
handled by the compositor thread.
If any animation triggers paint, layout, or both, the "main thread"
will be required to do work. This is true for both CSS- and
JavaScript-based animations, and the overhead of layout or paint will
likely dwarf any work associated with CSS or JavaScript execution,
rendering the question moot.
Source: https://developers.google.com/web/fundamentals/design-and-ux/animations/animations-and-performance
So compositor is pretty nice when we have to deal with animations. Using px as measure unit is easy and can be done by the compositor thread but using % makes our browser to calculate every "step" of our animation so the main thread has to help us with it. By using await you block the main thread so your browser waits to get recalculated position. When you use absolute unit the compositor thread executes the animation so even if you block the main thread, your animation is running smoothly.
Replace your code with
async function toggleSidebar() {
sidebarVisible = !sidebarVisible;
console.log("1");
await sleep(800);
console.log("2");
heavy(40);
}
You can notice using % causes:
Animation runs
- console.log 1
- animation stops
- console.log 2
- animation runs
Using px:
- console.log 1
- Animation still runs
- console.log 2
- animation ends