<div class="btn-wrapper">
  <button class="btn" id="downloadBtn">
    <span class="btn__text btn__starter-text">Download</span>
  </button>
  <span class="btn__text btn__ender-text">Open File</span>
</div>
// --------------------------------
// Pen Settings
// --------------------------------

html,
body {
  width: 100%;
  height: 100%;
}

// Importing Varela Round Font
@import 'https://fonts.googleapis.com/css?family=Varela+Round';

body {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Varela Round', sans-serif;
}

// --------------------------------
// Styling
// --------------------------------
$btn-height: 2.5rem;

// Colors
$black: #040404;
$grey: #969696;

.btn-wrapper {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  cursor: pointer;
}

.btn {
  position: relative;
  display: flex;
  // Tell the browser what property is going to change.
  // cf https://aerotwist.com/blog/bye-bye-layer-hacks/
  will-change: transform, background-color;
  width: 10rem;
  height: $btn-height;
  border-radius: 2px;
  border: none;
  padding: 0;
  background-color: $black;
  color: white;
  transition: all ease-out .2s;
  transform-origin: bottom;
  outline: none;
  overflow: hidden;
  
  &:hover {
    background-color: $grey;
  }
  
  // This pseudo-element will be the btn loading bar 
  &::before {
    content: '';
    display: block;
    transition: transform 1s ease-out 2s;
    transform: scaleX(0);
  }
}

.btn.is-active {
  transform: scaleY(0.1);
  background-color: $grey;
  
  .btn__starter-text {
    opacity: 0;
  }
  
  &::before {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-radius: 8px;
    background-color: $black;
    transition: transform 1s ease-out;
    transform: scaleX(1);
    transform-origin: left;
    transition-delay: .2s;
  }
}

.btn.dl-completed {
  transform: scale(.5, .1);
    
  & + .btn__ender-text {
    opacity: 1;
    transform: none;
  }
}

// Always reset the will-change property once the animation is finished
.btn.animation-ended {
  will-change: auto;
}

.btn__text {
  display: block;
  width: 100%;
  text-align: center;
  line-height: $btn-height;
}

.btn__ender-text {
  position: absolute;
  display: block;
  top: 0;
  left: 0;
  opacity: 0;
  will-change: opacity;
  color: $black;
  transform: translateY(1rem);
  transition: all ease-out .3s 1s;
  transition-delay: .3s;
  pointer-events: none;
}
View Compiled
var btn = document.querySelector('#downloadBtn')

function startDownload() {
  btn.addEventListener('click', function() {
    this.classList.add('is-active')
    
    setTimeout(function() {
      btn.classList.add('dl-completed')
      btn.classList.add('animation-ended')
    }, 1200)
  })
}

startDownload();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.4/TweenMax.min.js