JSFiddle - React, Tailwind, and code Playground

by joshmoto

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://js.stripe.com/v3/"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css">
<div class="container mt-3">

  <form action="/charge" method="post" id="preorder-form">

    <div class="form-group">
      <label for="name">Name on card</label>
      <div class="input-group">
        <input id="card-name" type="text" class="form-control" aria-describedby="input-name" placeholder="Name on card">
      </div>
    </div>

    <div class="form-group">
      <label for="card-number">Card Number</label>
      <div class="input-group">
        <div class="input-group-prepend">
          <span class="input-group-text" id="input-number"><i class="fab fa-cc-visa"></i></span>
        </div>
        <span id="card-number" class="form-control" aria-describedby="input-name">
          <!-- Stripe Card Element -->
        </span>
        <div class="invalid-feedback"></div>
      </div>
    </div>

    <div class="form-row">
      <div class="col-6">

        <div class="form-group">
          <label for="card-exp">Expiration</label>
          <div class="input-group">
            <div class="input-group-prepend">
              <span class="input-group-text" id="input-number"><i class="far fa-calendar"></i></span>
            </div>
            <span id="card-exp" class="form-control" aria-describedby="input-exp">
              <!-- Stripe Card Expiry Element -->
            </span>
            <div class="invalid-feedback"></div>
          </div>
        </div>

      </div>
      <div class="col-6">

        <div class="form-group">
          <label for="card-cvc">CVC</label>
          <div class="input-group">
            <div...

SCSS

.input-group-text {
  padding: 0rem .75rem;
  font-size: 1.5rem;
  background: #fff;
}

.input-group-prepend {

  .input-group-text {
    padding-right: 0;
    border-right: #fff 1px solid;
    z-index: 1;
  }
}

.input-group-append {

  .input-group-text {
    padding-left: 0;
    border-left: #fff 1px solid;
    z-index: 1;
  }
}

JavaScript

// create a Stripe client
var stripe = Stripe('pk_test_A45s2laXHrCRj6Tow44dk67z');

// Create an instance of Elements
var elements = stripe.elements();

// try to match bootstrap 4 styling
var style = {
    base: {
        'lineHeight': '1.6',
        'fontSize': '1.11rem',
        'color': '#495057',
        'fontFamily': '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"'
    }
};


// card mount
var card = elements.create('cardNumber', {
    'placeholder': '0000 0000 0000 0000',
    'style': style
});
card.mount('#card-number');

// card feedback
card.addEventListener('change', function(event) {
    var id = $('#card-number');
    if(event.error) {
        id.next().html(event.error.message);
        id.addClass('is-invalid').removeClass('is-valid');
    } else {
        id.next().html();
        id.addClass('is-valid').removeClass('is-invalid');
    }
});


// expiry mount
var exp = elements.create('cardExpiry', {
    'placeholder': 'MM / YY',
    'style': style
});
exp.mount('#card-exp');

// expiry feedback
exp.addEventListener('change', function(event) {
    var id = $('#card-expiry');
    if(event.error) {
        id.next().html(event.error.message);
        id.addClass('is-invalid').removeClass('is-valid');
    } else {
        id.next().html();
        id.addClass('is-valid').removeClass('is-invalid');
    }
});


// cvc mount
var cvc = elements.create('cardCvc', {
    'placeholder': '###',
    'style': style
});
cvc.mount('#card-cvc');

// cvc feedback
cvc.addEventListener('change', function(event) {
    var id = $('#card-cvc');
    if(event.error) {
        id.next().html(event.error.message);
        id.addClass('is-invalid').removeClass('is-valid');
    } else {
        id.next().html();
        id.addClass('is-valid').removeClass('is-invalid');
    }
});