Is it possible to use CSS translateX(100%) to make a moving animation?

Viewed 1041

In my animation, I like to use transformation. This is also possible to make It with left/right property. But I like to use the transform. I need to move the freeze-loading-bar 100% to right and It should be an infinite loop.

How can I move the loading-bar to right 100%/ fully?

*,
*::before,
*::after {
  box-sizing: border-box;
}

.app-view {
  height: 200px;
  max-width: 300px;
  margin: 1rem auto;
  background-color: #fff;
  box-shadow: -2px 2px 4px 0 #e0e0e0ad, 1px -1px 9px 0 #dddddd2e;

  padding: 2rem;

  display: flex;
  align-items: center;
  justify-content: center;
}

.freeze-loading {
  position: relative;
  width: 100%;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  
  /** disual purpose **/
  /** overflow: hidden; **/
  
}

.freeze-loading-bar {
  position: absolute;
  left: 0;
  width: 80px;
  height: 100%;
  background-color: rgb(0, 132, 255);
  animation: freeze-loading-bar 2s linear infinite;
}

@keyframes freeze-loading-bar {
    from {
        transform: translateX(-100px);
    }

    to {
        transform: translateX(100%);
    }
}
<div class="app-view">
  <div class="freeze-loading">
    <div class="freeze-loading-bar"></div>
  </div>
</div>

6 Answers

Keep the element full width (using left/right) then use a gradient for the coloration to color only a portion of it. Now you can rely on translateX(100%) whataver the width of the coloration is:

.freeze-loading {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin: 1rem auto;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  overflow: hidden;
}

.freeze-loading-bar {
  --w:80px;  /* the width of coloration */

  position: absolute;
  left: calc(-1*var(--w));
  right: 0;
  height: 100%;
  background:
   linear-gradient(rgb(0, 132, 255) 0 0) 
   0 / var(--w) 100%  
   no-repeat;
   animation: freeze-loading-bar 2s linear infinite;
}

@keyframes freeze-loading-bar {
  to {
    transform: translateX(100%);
  }
}
<div class="freeze-loading">
  <div class="freeze-loading-bar"></div>
</div>

<div class="freeze-loading">
  <div class="freeze-loading-bar" style="--w:150px;"></div>
</div>

Another kind of animation:

.freeze-loading {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin: 1rem auto;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  overflow: hidden;
}

.freeze-loading-bar {
  --w:80px; /* the width of coloration */

  position: absolute;
  left: 0;
  right: var(--w);
  height: 100%;
  background:
   linear-gradient(rgb(0, 132, 255) 0 0) 
   0 / var(--w) 100%  
   no-repeat;
   animation: freeze-loading-bar 1s linear infinite alternate;
}

@keyframes freeze-loading-bar {
  to {
    transform: translateX(100%);
  }
}
<div class="freeze-loading">
  <div class="freeze-loading-bar"></div>
</div>

<div class="freeze-loading">
  <div class="freeze-loading-bar" style="--w:150px;"></div>
</div>


Another syntax:

.freeze-loading {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin: 1rem auto;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  overflow: hidden;
}

.freeze-loading-bar {
  --w:80px;  /* the width of coloration */

  position: absolute;
  left: 0;
  right: 0;
  height: 100%;
  background:
   linear-gradient(rgb(0, 132, 255) 0 0) 
   0 / var(--w) 100%  
   no-repeat;
  animation: freeze-loading-bar 2s linear infinite;
  transform: translateX(calc(-1*var(--w)));
}

@keyframes freeze-loading-bar {
  to  {
     transform: translateX(100%);
  }
}
<div class="freeze-loading">
  <div class="freeze-loading-bar"></div>
</div>

<div class="freeze-loading">
  <div class="freeze-loading-bar" style="--w:150px;"></div>
</div>

And yet another one:

.freeze-loading {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin: 1rem auto;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  overflow: hidden;
}

.freeze-loading-bar {
  --w:80px;  /* the width of coloration */

  position: absolute;
  right: 0;
  width:calc(100% + var(--w));
  height: 100%;
  background:
   linear-gradient(rgb(0, 132, 255) 0 0) 
   0 / var(--w) 100%  
   no-repeat;
  animation: freeze-loading-bar 2s linear infinite;
}

@keyframes freeze-loading-bar {
  to  {
     transform: translateX(100%);
  }
}
<div class="freeze-loading">
  <div class="freeze-loading-bar"></div>
</div>

<div class="freeze-loading">
  <div class="freeze-loading-bar" style="--w:150px;"></div>
</div>

Responsiveness-wise, use %, not px, than the math is simple,

If the bar's width is 20% ( 1/5 of parent's )
translateX from -100% to 500% (100% * 5)

*,
*::before,
*::after {
  box-sizing: border-box;
}

.app-view {
  height: 200px;
  max-width: 300px;
  margin: 1rem auto;
  background-color: #fff;
  box-shadow: -2px 2px 4px 0 #e0e0e0ad, 1px -1px 9px 0 #dddddd2e;
  padding: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.freeze-loading {
  position: relative;
  width: 100%;
  height: 5px;
  box-shadow: inset 0 0px 4px 0 #ddd;
  overflow: hidden;
}

.freeze-loading-bar {
  position: relative;
  top: 0;
  width: 20%;
  height: 100%;
  background-color: rgb(0, 132, 255);
  animation: freeze-loading-bar 2s linear infinite;
}

@keyframes freeze-loading-bar {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(500%);
  }
}
<div class="app-view">
  <div class="freeze-loading">
    <div class="freeze-loading-bar"></div>
  </div>
</div>

--> An easy workaround for beginners

.freeze-loading {
  position: relative;
  width: 100%;
  max-width: 300px;
  margin: 1rem auto;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  overflow: hidden;
}

.freeze-loading-bar {
  width: 20%;
  position: absolute;
  transform: translateX(-150%);
  height: 100%;
  animation: freeze-loading-bar 2s linear infinite;
  background: #8965da;
}

@keyframes freeze-loading-bar {
  to {
    transform: translateX(550%);
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="stylesheet2.css" />
  </head>
  <body>
    <div class="freeze-loading">
      <div class="freeze-loading-bar"></div>
    </div>

  </body>
</html>

Your example does not quite work, because the percentage in the transform is relative to the width of the loading bar, i.e. 100% of 80px instead of 100% of the parent (which has the intended loading bar length).

To fix this, you can use the ::after element to make the moving bar full width, but show only a part of the moving bar:

*,
*::before,
*::after {
  box-sizing: border-box;
}

.app-view {
  height: 200px;
  max-width: 300px;
  margin: 1rem auto;
  background-color: #fff;
  box-shadow: -2px 2px 4px 0 #e0e0e0ad, 1px -1px 9px 0 #dddddd2e;

  padding: 2rem;

  display: flex;
  align-items: center;
  justify-content: center;
}

.freeze-loading {
  display:block;
  position: relative;
  width: 100%;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  
  /** disual purpose **/
  overflow: hidden;
  
}

.freeze-loading-bar {
  --loading-bar-width: 80px;
  position: relative;
  width: 100%;
  height: 100%;
  background-color: transparent;
  animation: freeze-loading-bar 2s linear infinite;
}

.freeze-loading-bar::after {
  content: '';
  display: block;
  --loading-bar-width: 80px;
  position: absolute;
  left: 0;
  width: var(--loading-bar-width);
  height: 100%;
  background-color: rgb(0, 132, 255);
  
}

@keyframes freeze-loading-bar {
    from {
        transform: translateX(calc(var(--loading-bar-width) * -1));
    }

    to {
        transform: translateX(100%);
    }
}
<div class="app-view">
  <div class="freeze-loading">
    <div class="freeze-loading-bar"></div>
  </div>
</div>

.freeze-loading {
  position: relative;
  width: 100%;
  height: 5px;
  box-shadow: inset 1px 0px 4px 0 #ddd;
  overflow: hidden;  // <== LOOK HERE
  
  /** disual purpose **/
  /** overflow: hidden; **/
  
}

.freeze-loading-bar {
  position: absolute;
  left: 0; // <= LOOK HERE 
  width: 80px;
  height: 100%;
  background-color: rgb(0, 132, 255);
  animation: freeze-loading-bar 2s linear infinite;
}


@keyframes freeze-loading-bar {
    from {
        left: -80px; // <== HERE
    }

    to {
        left: calc(100% + 80px); // AND HERE
    }
}

Of course you need to get add some javascript if you need smooth animations. But CSS works fine too.

    @keyframes freeze-loading-bar {
    from {
        transform: translateX(-100%);
    }

    to {
        transform: translateX(100%);
    }
}

This might solve the issue you are having.

Related