<div class="wrapper">
  <form class="form">
    <div class="cardName-container field-container">
      <label for="card-name-field">Cardholder Name</label>
      <div id="card-name-field" class="hosted-field"></div>
      <div class="error"></div>
    </div>
    <div class="cardNumber-container field-container">
      <label for="card-number-field">Card Number</label>
      <div id="card-number-field" class="hosted-field"></div>
      <div class="error"></div>
    </div>
    <div class="field-columns">
      <div class="cardExpiry-container field-container">
        <label for="card-expiry-field">Expiry Date</label>
        <div id="card-expiry-field" class="hosted-field"></div>
        <div class="error"></div>
      </div>
      <div class="cardCvv-container field-container">
        <label for="card-cvv-field">CVV</label>
        <div id="card-cvv-field" class="hosted-field"></div>
        <div class="error"></div>
      </div>
    </div>
    <button class="button">Submit</button>
    <div class="response"></div>
    <div class="disclaimer">
      Payment securely processed by Assembly Payments.
    </div>
  </form>
</div>
*,
:after,
:before {
  box-sizing: border-box;
}
body {
  font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  padding: 20px;
}
.wrapper {
  max-width: 460px;
  margin: 0 auto;
}
form {
  margin-bottom: 30px;
  background: #fff;
  border: 1px solid #e0e0e0;
  box-sizing: border-box;
  border-radius: 12px;
  padding: 20px;
}
@media (min-width: 600px) {
  form {
    padding: 40px;
  }
}
.button {
  display: block;
  position: relative;
  align-items: center;
  appearance: none;
  display: inline-flex;
  justify-content: center;
  line-height: 1;
  padding: 0 20px;
  height: 60px;
  text-decoration: none;
  background-color: #000645;
  border: none;
  color: #fff;
  border-radius: 3px;
  font-size: 16px;
  margin-top: 16px;
  width: 100%;
  cursor: pointer;
}
.button:hover {
  box-shadow: 0px 1px 12px rgba(33, 0, 150, 0.25);
}
.button:disabled {
  cursor: not-allowed;
}
.button-loading::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #000645;
}
.button-loading::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  width: 24px;
  height: 24px;
  border-color: currentColor;
  border-style: solid;
  border-radius: 99999px;
  border-width: 2px;
  border-left-color: transparent;
  color: #fff;
  animation: rotate 450ms linear 0ms infinite;
}
label {
  display: block;
  margin-bottom: 4px;
  font-size: 14px;
  color: #000645;
}
.field-container {
  margin-bottom: 20px;
}
.field-columns {
  display: flex;
  justify-content: space-between;
}
.field-columns > * {
  flex: 0 1 40%;
}
.hosted-field {
  height: 40px;
  padding: 0 12px;
  border: 1px solid #e0e0e0;
  border-radius: 3px;
}
.hosted-field-invalid {
  border-color: #cc0001;
}
.hosted-field-valid {
  border-color: #10b981;
}
.hosted-field-focus {
  border-color: #210096;
  box-shadow: 0px 1px 12px rgba(33, 0, 150, 0.25);
}
.error {
  color: #cc0001;
  background-color: #ffe6e6;
  padding: 2px 8px;
  margin-top: 12px;
  font-size: 14px;
  border-radius: 3px;
  display: none;
}
.error.visible {
  display: inline-block;
}
.disclaimer {
  color: #828282;
  font-size: 14px;
  margin-top: 24px;
  text-align: center;
}
.response {
  display: none;
  margin-top: 16px;
  color: #fff;
  padding: 10px 20px;
  text-align: center;
  font-size: 14px;
}
.response-success {
  display: block;
  background-color: #dff9ec;
  color: #1b643a;
}
.response-error {
  display: block;
  background-color: #ffe6e6;
  color: #cc0001;
}
@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
var styles = {
  input: {
    color: "#000645",
    "font-family": "system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
    "letter-spacing": "0.02em"
  },
  ".invalid": {
    color: "#cc0001"
  },
  "::placeholder": {
    color: "#757575"
  },
  ".invalid .card-icon": {
    color: "#cc0001"
  }
};

var hostedFields = assembly.hostedFields({
  environment: "pre-live"
});
var cardName = hostedFields.create("cardName", {
  placeholder: "Full Name",
  styles: styles
});
var cardNumber = hostedFields.create("cardNumber", {
  placeholder: "•••• •••• •••• ••••",
  styles: styles,
});
var cardExpiry = hostedFields.create("cardExpiry", {
  placeholder: "MM/YY",
  styles: styles
});
var cardCvv = hostedFields.create("cardCvv", {
  placeholder: "•••",
  styles: styles
});

cardName.mount("#card-name-field");
cardNumber.mount("#card-number-field");
cardExpiry.mount("#card-expiry-field");
cardCvv.mount("#card-cvv-field");

var inputs = [cardName, cardNumber, cardExpiry, cardCvv];

inputs.forEach(function (field) {
  field.on("change", function (event) {
    var errorElement = document.querySelector(
      "." + event.fieldType + "-container .error"
    );
    toggleError(errorElement, event);
  });
});

var form = document.querySelector(".form");
var submitButton = form.querySelector(".button");
var responseContainer = document.querySelector(".response");

function toggleError(element, event) {
  if (event.error) {
    element.innerText = event.error.message;
    element.classList.add("visible");
  } else {
    element.innerText = "";
    element.classList.remove("visible");
  }
}

form.addEventListener("submit", function (event) {
  event.preventDefault();
  submitButton.disabled = true;
  submitButton.classList.add("button-loading");

  hostedFields
    .createCardAccount({
      token: "YOUR_TOKEN",
      user_id: "YOUR_USER_ID"
    })
    .then(function (response) {
      resetSubmitButton();
      // handle create card account succeeded
      responseContainer.classList.add("response-success");
      responseContainer.innerText = "Card account successfully created.";
    resetForm()
    })
    .catch(function (response) {
      resetSubmitButton();
      // handle errors
      responseContainer.classList.add("response-error");
      if (response.errors && response.errors.token) {
        responseContainer.innerText = "Your token is not authorized.";
      } else {
        responseContainer.innerText =
          "There was an error creating your card account.";
      }
    });
});

function resetSubmitButton() {
  submitButton.disabled = false;
  submitButton.classList.remove("button-loading");
}

function resetForm() {
  inputs.forEach(function (input) {
    input.clear()
  })
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/classlist/1.2.20180112/classList.min.js
  2. https://hosted-fields.assemblypay.com/assembly.js