<!--[if IE 9]>
<style>
body {
  padding-top: 5em;
}

.hosted-field--label {
  top: -1.2em;
}

.form-controls__steps {
  top: -1.2em;
}
</style>
<![endif]-->
<div class="container">
  <div class="container-wrap per">
    
    <div class="form-controls__steps">1/4</div>

    <nav class="form-controls">
      <a href="" class="form-controls__prev form-controls--hidden">
        <svg width="19" height="32" viewBox="0 0 19 32" xmlns="http://www.w3.org/2000/svg"><title>next</title><path fill="#ffffff" d="M5.657 15.556L18.385 2.828 15.555 0 0 15.556l15.556 15.557 2.83-2.83" fill-rule="evenodd"/></svg>
      </a>
      <a href="" class="form-controls__next form-controls--hidden">
        <svg width="19" height="32" viewBox="0 0 19 32" xmlns="http://www.w3.org/2000/svg"><title>prev</title><path fill="#ffffff" d="M12.727 15.556L0 2.828 2.828 0l15.557 15.556L2.828 31.113 0 28.283" fill-rule="evenodd"/></svg>
      </a>
    </nav>

    <form action="/" method="post" id="cardForm">
      <div class="field-container">
        <label class="hosted-field--label " for="card-number">Card Number
        </label>
        <div class="hosted-field" id="card-number"></div>
      </div>

      <div class="field-container field-container--hidden">
        <label class="hosted-field--label " for="expiration-date">
          Exp (MM/YY)
        </label>
        <div class="hosted-field" id="expiration-date"></div>
      </div>

      <div class="field-container field-container--hidden">
        <label class="hosted-field--label " for="cvv">
        CVV
      </label>
        <div class="hosted-field" id="cvv"></div>
      </div>

      <div class="field-container field-container--hidden field-container--button">
        <input id="button-pay" type="submit" value="Pay" />
      </div>
    </form>

    <div class="form-info">
      <p class="field-message">Let's add your card number.</p>
    </div>
    
  </div>
</div>

<!-- Load the required client component. -->
<script src="https://js.braintreegateway.com/web/3.52.1/js/client.min.js"></script>

<!-- Load Hosted Fields component. -->
<script src="https://js.braintreegateway.com/web/3.52.1/js/hosted-fields.min.js"></script>
/*----- VARIABLES -----*/

$primary: #282828;
$success: #4CAF50;
$error: #f44336;
$small-screen: 467px;
$bouncy: cubic-bezier(.20, 1.3, .7, 1);

/*----- GENERAL -----*/

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

body,
html {
  overflow: hidden;
  height: 100%;
  background-color: $primary;
  background: linear-gradient(185grad, darken($primary, 20%), $primary) ;
  color: lighten($primary, 85%);
  font-family: 'Roboto Mono', monospace;
  font-weight: 300;
  
  @media (max-width: $small-screen) {
    font-size: 85%;
  }
}

html {
  box-sizing: border-box;
}

a {
  text-decoration: none;
  font-size: 2em;
}


/*----- POSITIONING -----*/

.container {
  display: flex;
  width: 80%;
  margin: 0 auto;
  flex-direction: column;
  justify-content: center;
  height: 100%;
  perspective: 100;
  position: relative;
  
  @media (max-width: $small-screen) {
    width: 90%;
  }
}

#cardForm {
  height: 5em;
  width: 100%;
  height: 5.5em;
  margin-bottom: 1em;
  position: relative;
  transform: translateX(0em);
}


/*----- HF CONTAINERS -----*/

.field-container {
  position: absolute;
  width: 100%;
  border: 1px solid #fff;
  z-index: 2;
  opacity: 1;
  transition: all 500ms $bouncy;
 -webkit-backface-visibility: hidden;
  transform-style: preserve-3d;
  transform-origin: bottom;
  transition: transform 0.5s $bouncy, opacity 0.5s;
  opacity: 1;
}

.field-container:nth-child(1) {
  animation: inputIntro 0.5s $bouncy;
}

.field-container--hidden {
  opacity: 0;
  transform: translate(0em, 0em) rotateX(180deg);
  z-index: -1;
}

.field-container--button {
  border: 0;
}

.hosted-field {
  height: 5.5em;
  width: 100%;
  display: block;
  padding-left: 1em;
}


/*----- HF LABELS -----*/

.hosted-field--label {
  color: #FFF;
  position: absolute;
  top: 0.9em;
  left: 0.5em;
  transition: transform 0.2s $bouncy, color 0.2s;
  transform-origin: 0 0;
  font-size: 2em;
  line-height: 1;
}

.hosted-field--label--moved,
.not-empty {
  transform: scale(0.8) translate(0em, -3em);
  transition: transform 0.2s $bouncy, color 0.2s;
  color: #fff;
}


/*----- HF MESSAGES -----*/

.field-message {
  font-size: 1em;
  margin: 1em;
  opacity: .3;
  
  @media (max-width: $small-screen) {
    margin: 0;
  }
}

.field-message--error {
  color: $error;
}


/*----- HF SUBMIT -----*/

#button-pay {
  -webkit-appearance: none;
  width: 100%;
  border: 0;
  text-align: center;
  font-size: 2em;
  padding: 0.9em;
  color: #000;
  background: #fff;
  cursor: pointer;
}


/*----- HF CONTROLS -----*/

.form-controls__steps {
  font-size: 1.5em;
  position: absolute;
  right: 1em;
  transform: translateY(-1.9em);
  opacity: .3;
}

.form-controls {
  position: absolute;
  right: 0;
  z-index: 5;
  animation: arrowIntroScale 0.3s 0.4s $bouncy backwards;
  transition: transform 0.3s $bouncy;
  @media (max-width: $small-screen) {
     right: 0.5em;
  }
  
  a {
    display: inline-block;
    padding: 1em 0.5em;
    transform: scale(0.8);
    transition: transform 0.3s $bouncy;
    
    @media (max-width: $small-screen) {
      padding: 0.7em 0.1em;
      transform: scale(0.6);
    }
  }
  a:hover {
    transform: scale(0.9);
    transition: transform 0.1s $bouncy;
  }
  .form-controls--hidden {
    transform: scale(0);
    transition: transform 0.3s $bouncy;
  }
  .form-controls--hidden:hover {
    transform: scale(0);
  }
}
.form-controls--back {
  transition: transform 0.2s $bouncy;
  transform: translateX(2em);
}

.form-controls--end {
  transition: transform 0.2s $bouncy;
  transform: translateY(-5em) translateX(-3.5em);
}


/*----- BT CLASSES -----*/

.braintree-hosted-fields-valid {
  background: rgba($success, 0.5);
  animation: success 0.5s $bouncy;
}

.braintree-hosted-fields-invalid {
  background: rgba($error, 0.5);
  color: #fff;
  animation: error 0.5s $bouncy;
}


/*----- ANIMATIONS -----*/

@keyframes inputIntro {
  0% {
    transform: translate(0, 0.2em) rotateX(90deg) scale(0.9);
  }
  100% {
    transform: translate(0, 0) rotateX(0) scale(1);
  }
}

@keyframes arrowIntroScale {
  0% {
    transform: translate(-1em, 0) scale(0);
  }
  100% {
    transform: translate(0, 0) scale(1);
  }
}

@keyframes error {
  0% {
    background: $primary;
    transform: scale(1);
  }
  50% {
    background: rgba($error, 1);
    transform: scale(1.1);
  }
  100% {
    background: rgba($error, 0.5);
    transform: scale(1);
  }
}

@keyframes success {
  0% {
    background: $primary;
    transform: scale(1);
  }
  50% {
    background: darken($success, 10%);
    transform: scale(1.1);
  }
  100% {
    background: rgba($success, 0.5);
    transform: scale(1);
  }
}



var form = document.querySelector('#cardForm');

// Input switcher
var formItems = [];
var currentFormItem = 0;

$('.field-container').each(function() {
  formItems.push(this);
})

// Add the functionality for what happens when people will click on next
function formControlNext() {
  $(formItems[currentFormItem]).addClass('field-container--hidden');
  $(formItems[currentFormItem + 1]).removeClass('field-container--hidden');

  currentFormItem = currentFormItem + 1;
  checkFormVisibility();
  changeStepperNumber();

  hideNext();

  return false;
}

function hideNext() {
  if (!$(formItems[currentFormItem + 1]).find('.hosted-field').hasClass('hosted-field')) {
    $('.form-controls__next').addClass('form-controls--hidden');
  }
  
  $('.form-controls__prev').addClass('form-controls--back');
}

function formControlPrev() {
  $(formItems[currentFormItem]).addClass('field-container--hidden');
  $(formItems[currentFormItem - 1]).removeClass('field-container--hidden');

  currentFormItem = currentFormItem - 1;
  checkFormVisibility();
  changeStepperNumber();
}

function showNext() {
  $('.form-controls__next').removeClass('form-controls--hidden');
  $('.form-controls__prev').removeClass('form-controls--back');
}

$('.form-controls__next').click(function() {
  formControlNext();

  return false;
})

$('.form-controls__prev').click(function() {
  formControlPrev();

  return false;
})

// Update the number of steps and update the content to match input
function changeStepperNumber() {
  if (currentFormItem === 3) {
    $('.form-controls__steps').text('4 / 4');
    $('.field-message').text('Time to buy that sweet sweet bag.');
    $('.form-controls').addClass('form-controls--end');
  } else if (currentFormItem === 2) {
    $('.form-controls__steps').text('3 / 4');
    $('.field-message').text('This is on the back of your card.');
    $('.form-controls').removeClass('form-controls--end');
  } else if (currentFormItem === 1) {
    $('.form-controls__steps').text('2 / 4');
    $('.field-message').text('When will your card expire?');
  } else {
    $('.form-controls__steps').text('1 / 4');
    $('.field-message').text('Let\'s add your card number.');
  }
}

// Show/hide the appropriate controls
function checkFormVisibility() {
  if (currentFormItem === 0) {
    $('.form-controls__prev').addClass('form-controls--hidden');
  } else {
    $('.form-controls__prev').removeClass('form-controls--hidden');
  }

  if (currentFormItem === 3) {
    $('.form-controls__next').addClass('form-controls--hidden');
  } else {
    $('.form-controls__next').removeClass('form-controls--hidden');
  }
}

// Create Braintree components
braintree.client.create({
  authorization: 'sandbox_g42y39zw_348pk9cgf3bgyw2b'
}, function(err, client) {
  if (err) {
    console.error(err);
    return;
  }

  braintree.hostedFields.create({
    client: client,
    styles: {
      'input': {
        'font-size': '2em',
        'font-weight': '300',
        'font-family': 'sans-serif',
        'color': '#fff'
      },
      ':focus': {
        'color': '#fff'
      },
      '.invalid': {
        'color': '#fff'
      },
      '@media screen and (max-width: 361px)': {
        'input': {
          'font-size': '1em'
        }
      }
    },
    fields: {
      number: {
        selector: '#card-number'
      },
      cvv: {
        selector: '#cvv'
      },
      expirationDate: {
        selector: '#expiration-date'
      }
    }
  }, function(err, hostedFields) {
    if (err) {
      console.error(err);
      return;
    }

    hostedFields.on('validityChange', function(event) {
      var field = event.fields[event.emittedBy];

      if (field.isValid) {
        // Show Next button if inputs are valid
        showNext();

        // Update message to reflect success
        $('.field-message').text('Nice! Let\'s move on…');
      } else if (!field.isPotentiallyValid) {
        // Hide next button
        $('.form-controls__next').addClass('form-controls--hidden');
        // Change the top message based on the input error
        switch ($(field.container).attr('id')) {
          case 'card-number':
            $('.field-message').text('Please check if you typed the correct card number.');
            break;
          case 'expiration-date':
            $('.field-message').text('Please check your expiration date.');
            break;
          case 'cvv':
            $('.field-message').text('Please check your security code.');
            break;
        }
      } else {
        switch ($(field.container).attr('id')) {
          case 'card-number':
            $('.field-message').text('Let\'s add your card number.');
            break;
          case 'expiration-date':
            $('.field-message').text('When will your card expire?');
            break;
          case 'cvv':
            $('.field-message').text('This is on the back of your card.');
            break;
        }
      }
    });

    hostedFields.on('focus', function(event) {
      var field = event.fields[event.emittedBy];

      $(field.container).prev('.hosted-field--label').addClass('hosted-field--label--moved');
      $(field.container).parent().addClass('field-container--active');
    });

    hostedFields.on('blur', function(event) {
      var field = event.fields[event.emittedBy];

      $(field.container).prev('.hosted-field--label').removeClass('hosted-field--label--moved');
      $(field.container).parent().removeClass('field-container--active');
    });

    hostedFields.on('empty', function(event) {
      var field = event.fields[event.emittedBy];

      $(field.container).prev('.hosted-field--label').removeClass('not-empty');
    });

    hostedFields.on('notEmpty', function(event) {
      var field = event.fields[event.emittedBy];

      $(field.container).prev('.hosted-field--label').addClass('not-empty');
    });

    form.addEventListener('submit', function(event) {
      event.preventDefault();

      hostedFields.tokenize(function(err, payload) {
        if (err) {
          console.error(err);
          return;
        }

        // This is where you would submit payload.nonce to your server
        alert('Submit your nonce to your server here!');
      });
    });
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js