I am developing a loading page that will be displayed while the page content itself is rendered. It is a simple text that blinks, while circles move from left to right.
The problem is that during times when JavaScript is rendering intensively, the animation hangs and freezes. A colleague told me that it could be a problem when changing the position and size of elements with CSS (because blinking does seem to work without problems).
How can I avoid this behavior? What could I do to keep the animation flowing rather than jumpy?
This is the code with a forced load to show the crash:
// código para crear bloqueo al generar alta intensidad de JS
setInterval(function() {
for (let j = 0; j < 10000; j++) {
let o = new Array(20000);
}
}, 1500);
@keyframes csLoadingBlink {
0%, 80% {
opacity: 1;
}
40% {
opacity: 0;
}
}
@keyframes csLoadingMoveButton {
0% {
top: 0;
width: 2rem;
height: 2rem;
left: 0;
}
100% {
top: 1rem;
width: 0rem;
height: 0rem;
left: 100%;
}
}
.cs-loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.cs-brand {
white-space: nowrap;
animation: csLoadingBlink 3s linear infinite;
}
.cs-brand span {
white-space: nowrap;
display: inline-block;
color: #000369;
vertical-align: middle;
}
.cs-name {
border-right: 1px solid;
padding-right: 1rem;
margin-right: 1rem;
font-size: 2.5rem;
line-height: 3rem;
}
.cs-name sup {
font-size: 0.75rem;
}
.cs-slogan {
font-family: Arial, sans-serif;
font-size: 1.5rem;
}
.cs-animation {
width: 100%;
height: 2rem;
margin-top: 1rem;
position: relative;
}
.cs-animation span,
.cs-animation::before {
display: block;
content: "";
position: absolute;
line-height: 2rem;
width: 2rem;
height: 2rem;
border-radius: 50%;
background: #000369;
}
.cs-animation span {
animation: csLoadingMoveButton 3s linear infinite;
animation-fill-mode: backwards;
}
.cs-animation span:nth-of-type(1) {
animation-delay: 0s;
}
.cs-animation span:nth-of-type(2) {
animation-delay: 1s;
}
.cs-animation span:nth-of-type(3) {
animation-delay: 2s;
}
<div class="cs-loading">
<div class="cs-brand">
<span class="cs-name">Compañía</span>
<span>Mejor Slogan del Mundo</span>
</div>
<div class="cs-animation">
<span></span>
<span></span>
<span></span>
</div>
</div>
Using a worker it seems that it does not get stuck
(inline example taken from https://stackoverflow.com/a/6454685/1423096 )
the
if ( 5 > Math.floor(Math.random() * 100) ) {
is so that the console.log doesn't affect the render.Introduction:
There are currently four things that the browser can encourage " low price " :
translate
,scale
,rotate
andopacity
.If you animate anything else you will most likely not reach the
60fps
.Problem:
As you point out in your question, the problem is because you are changing the position and size of the elements using:
left
andtop
to change the position.width
andheight
to change the size.As we saw before, these rules are not within the rules optimized for animations.
Solution:
To change the position we can replace
top
yleft
withtransform: translate(x, y)
and to change the size we can replaceheight
ywidth
withtransform: scale(x, y)
Then:
coodenada x
) we can usetranslate(x)
.scale(n)
.transform-origin: center;
Example without modifying the markup:
Example 2 modifying the markup: