Fred Hors
Fred Hors

Reputation: 4156

CSS, switch left/right to transform/translate for better performance

I found this good CSS animation for a progress bar.

But I want to transform: translate instead of left/right.

How can I switch to transform it? I tried but it doesn't work:

https://codepen.io/shalimano/pen/wBmNGJ

body{
  background:#ffffff;
  margin:50px 300px;
}

.slider{
  position:absolute;
  width:1000px;
  height:5px;
  overflow-x: hidden;
}

.line{
  position:absolute;
  opacity: 0.4;
  background:#4a8df8;
  width:150%;
  height:5px;
}

.subline{
  position:absolute;
  background:#4a8df8;
  height:5px; 
}
.inc{
animation: increase 2s infinite;
}
.dec{
animation: decrease 2s 0.5s infinite;
}

@keyframes increase {
 from { left: -5%; width: 5%; }
 to { left: 130%; width: 100%;}
}
@keyframes decrease {
 from { left: -80%; width: 80%; }
 to { left: 110%; width: 10%;}
}
<div class="slider">
	  <div class="line"></div>
  <div class="subline inc"></div>
  <div class="subline dec"></div>
</div>

First attempt:

@keyframes increase {
 from { transform: translateX(-5%); width: 5%; }
 to { transform: translateX(130%); width: 100%;}
}
@keyframes decrease {
 from { transform: translateX(-100%); width: 80%; }
 to { transform: translateX(1100%); width: 10%;}
}

But it's not the same.

Upvotes: 2

Views: 3901

Answers (2)

Leonid Volkov
Leonid Volkov

Reputation: 154

One of the main differences between the two methods (transform: translate and left ) of positioning elements is how they react to percentages. You can use px.

Upvotes: -1

Temani Afif
Temani Afif

Reputation: 273750

You should consider the fact that percentage value with translate are related to the element size and not parent size like top/left and in order to have good performance you need to also replace the width by scale so that you only use transform and you will not trigger layout changes.

Here is an approximation of your code using only transform:

body {
  background: #ffffff;
  margin: 50px 10px;
  position:relative;
}

.slider {
  position: absolute;
  left:0;
  right:0;
  height: 5px;
  overflow-x: hidden;
  background: rgba(74, 141, 248, 0.4);
}

.slider:before,
.slider:after {
  content: "";
  position: absolute;
  background: #4a8df8;
  height: 5px;
  width:100%;
  transform:scaleX(0);
  animation: increase 2s infinite linear;
}

.slider:after {
  animation-delay:1s;
}

@keyframes increase {
  from {
    transform:translateX(0%) scaleX(0);
    transform-origin:left;
  }
  50% {
    transform-origin:left;
  }
  60% {
    transform:translateX(0%) scaleX(0.5);
    transform-origin:right;
  }
  80% {
    transform:translateX(20%) scaleX(0.3);
    transform-origin:right;
  }
  100% {
    transform:translateX(0%) scaleX(0);
    transform-origin:right;
  }
}
<div class="slider">
</div>

Upvotes: 3

Related Questions