<div class="container noselect center" id="container">
    <button class="button fill-container center" id="button">DOWNLOAD</button>
    <canvas class="bar fill-container center" id="bar"></canvas>
    <!-- <div class="text fill-container center"><span class="center">DOWNLOAD</span></div> -->
    <div class="done fill-container center"><span class="center">DONE</span></div>
    <div class="cancel fill-container center">
        <div class="cancel-button" id="cancel-button">X</div>
    </div>
    <div class="canceling fill-container center"><span class="center">CANCELING</span></div>
</div>
*{box-sizing: border-box;}

html {
    font-family: sans-serif;
  /* 1 */
    -ms-text-size-adjust: 100%;
  /* 2 */
    -webkit-text-size-adjust: 100%;
  /* 2 */
}

html {
    color: #222;
    font-size: 1em;
    line-height: 1.4;
}

body{
    background: #eee;
}

.container > * {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.container{
  overflow: hidden;
  width: 180px;
  height: 60px;
  background: #181818;
  font-family: sans-serif;
  font-weight: bold;
  font-size: 0.8em;
}

.container .button{
  background: #181818;
  cursor: pointer;
  border: 0;
  outline: 0;
  color: #eee;
  font-family: sans-serif;
  font-weight: bold;
  font-size: inherit;
}

.container .done{
    background: #50a952;
    color: #eee;
}

.container .cancel-button{
  background: RGBA(226,79,82, 1);
  color: #eee;
  text-align: center;
  right: 0;
  position: absolute;
  padding: 2px 5px;
  cursor: pointer;
}


.center{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.fill-container{
    width: 100%;
    height: 100%;
}

/*Elemenst that start hidden*/
.container .bar,
.container .done,
.container .canceling,
.container .cancel,
.container.finished .button {
  transform: translate(-50%, -150%);
}

.container .canceling{
    background: #d2cb5a;
    color: #181818;
}

/* Set the states of the animations */

/* slide in animation */
.container.downloading .bar,
.container.idle .button,
.container.finished .done,
.container.canceling .canceling,
.container.downloading .cancel {
    animation-duration: 0.3s;
    animation-name: slidein;
    transform: translate(-50%, -50%);
    animation-timing-function: cubic-bezier(0.44, 0.46, 0, 1);
}

/* slide out animation */
.container.downloading .button,
.container.finished .cancel,
.container.canceling .button,
.container.canceling .cancel,
.container.finished .bar,
.container.idle .done,
.container.idle.canceled .canceling {
    animation-duration: 0.3s;
    animation-name: slideout;
    transform: translate(-50%, -150%);
    animation-timing-function: cubic-bezier(0.44, 0.46, 0, 1);
}

/*out left*/
.container.canceling .bar{
    animation-duration: 0.3s;
    animation-name: slideout-left;
    transform: translate(-150%, -50%);
    animation-timing-function: cubic-bezier(.67,0,0,1);
}

@keyframes slidein {
  from {
    transform: translate(-50%, 150%);
  }

  to {
    transform: translate(-50%, -50%);
  }
}

@keyframes slideout {
  from {
    transform: translate(-50%, -50%);
  }

  to {
    transform: translate(-50%, -150%);
  }
}

@keyframes slideout-left {
  from {
    transform: translate(-50%, -50%);
  }

  to {
    transform: translate(-150%, -50%);
  }
}
const $buttonContainer = document.getElementById('container');
const $button = document.getElementById('button');
const canvas = document.getElementById('bar');
const $cancelButton = document.getElementById('cancel-button');
const ctx = canvas.getContext('2d');
let animationFrameID = 0;
let percentage = 0;
let width = 0;
let stateUpdate = null;
let count = 0;

const state = {
  downloading: false,
  idle: false,
  finished: true,
  canceling: false
};

let random = new Random(Random.engines.mt19937().autoSeed());

$button.onclick = function(){

  if(state.downloading == false){
    state.downloading = true;
  }

  //Starts download
  if(state.downloading && state.canceling == false){
    count = 0;
    $buttonContainer.classList.remove('idle', 'canceling', 'finished', 'canceled');
    $buttonContainer.classList.add('downloading');
    state.finished = false;
    percentage = 0;
    width = 0;
    stateUpdate = fillBar;
    animationFrameID = requestAnimationFrame(update);
  }

};

$cancelButton.onclick = function(){

  if(state.finished == false && state.canceling == false){
    //cancels download
    count = 0;
    $buttonContainer.classList.remove('downloading', 'idle', 'canceling', 'canceled');
    $buttonContainer.classList.add('canceling');
    state.canceling = true;
    stateUpdate = canceling;
  }

}

//Fills the progress bar
function fillBar(){

  percentage += random.bool(5, 40) ? random.real(0, 0.1) : 0;
  width += ( (canvas.width * percentage) - width) * 0.05;

  //when the download is done
  if(percentage >= 1){

    stateUpdate = finishfillBar;

  }

}

//when the download is done
function finishfillBar(){

  width += ((canvas.width * percentage) - width) * 0.9;

  //when the bar is completely filled
  if(width >= (canvas.width * percentage)){
    stateUpdate = finished;
    percentage = Math.min(percentage, 1);
    state.finished = true;
    $buttonContainer.classList.remove('downloading');
    $buttonContainer.classList.add('finished');
  }

}

//When Canceling
function canceling(){
  count++;

  //wait some time and set as canceled
  if(count >= 50){
    $buttonContainer.classList.remove('downloading', 'finished', 'canceling');
    $buttonContainer.classList.add('idle', 'canceled');
    state.canceling = false;
    stateUpdate = null;
    cancelAnimationFrame(animationFrameID);
  }

}

//when the bar is completely filled
function finished(){
  count++;

  //Wait some time to hide 'done' message
  if(count >= 60){
    count = 0;
    $buttonContainer.classList.remove('downloading', 'finished', 'canceling');
    $buttonContainer.classList.add('idle');
    state.downloading = false;
    cancelAnimationFrame(animationFrameID);
  }

}

function update(){
  animationFrameID = requestAnimationFrame(update);

  if(stateUpdate != null) stateUpdate();

  ctx.clearRect(0,0,canvas.width, canvas.height);

  ctx.fillStyle = '#3f3f3f';
  ctx.fillRect(0, 0, width, canvas.height);
  ctx.fillStyle = '#eee';
  ctx.fillRect(canvas.width * percentage, 0, 2, canvas.height);

}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.rawgit.com/ckknight/random-js/master/lib/random.min.js