<div class="wrapper">
<form class="form">
<div class="background"></div>
<div class="foreground">
<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">Security Code</label>
<div id="card-cvv-field" class="hosted-field"></div>
<div class="error"></div>
</div>
</div>
<button class="button">Pay now</button>
<div class="response"></div>
</div>
</form>
</div>
*,
:after,
:before {
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
padding: 20px;
letter-spacing: 0.02em;
}
.wrapper {
max-width: 460px;
margin: 0 auto;
}
form {
position: relative;
margin-bottom: 30px;
background: #fff;
box-sizing: border-box;
border-radius: 12px;
padding: 20px;
overflow: hidden;
}
@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: #FFC3C4;
border: none;
color: #44465F;
border-radius: 100em;
font-size: 16px;
margin-top: 16px;
width: 100%;
cursor: pointer;
transition: background-color 200ms ease-in-out;
}
.button:disabled {
cursor: not-allowed;
}
.button-loading::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
border-radius: 100em;
}
.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: #fff;
}
.required::after {
content: "*";
color: red;
}
.field-container {
margin-bottom: 20px;
}
.field-columns {
display: flex;
justify-content: space-between;
}
.field-columns > * {
flex: 0 1 46%;
}
.hosted-field,
.demo-field {
height: 48px;
padding: 0 24px;
border: 1px solid #e0e0e0;
border-radius: 100em;
background-color: #fff;
}
.demo-field {
appearance: none;
width: 100%;
font-size: 16px;
letter-spacing: 0.02em;
color: #000645;
}
.hosted-field-invalid {
border-color: #cc0001;
}
.hosted-field-focus,
.demo-field:focus {
border-color: #210096;
box-shadow: 0px 1px 12px rgba(33, 0, 150, 0.25);
outline: none;
}
.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;
border-radius: 3px;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Card brand identification */
.foreground {
position: relative;
z-index: 1;
}
.background {
z-index: 0;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgb(113,216,156);
background: linear-gradient(197deg, rgba(113,216,156,1) 0%, rgba(90,142,192,1) 61%, rgba(63,58,232,1) 100%);
transition: opacity 400ms ease-in-out;
}
.brand-amex .background {
background: linear-gradient(106.48deg, #0071CE 20.32%, rgba(74, 173, 255, 0.5) 81.38%);
transform: matrix(1, 0, 0, -1, 0, 0);
}
.brand-mastercard .background {
background: linear-gradient(106deg, #000000 20%, #606060 81%);
transform: matrix(1, 0, 0, -1, 0, 0);
}
.brand-visa .background {
background: linear-gradient(106deg, #222357 20%, #254aa5 81%);
transform: matrix(1, 0, 0, -1, 0, 0);
}
.brand-amex .button {
background-color: #DFDFDF;
}
.brand-mastercard .button {
background-color: #FFC3C4;
}
.brand-visa .button {
background-color: #858ae3;
color: #fff
}
.brand-amex .hosted-field-focus {
border-color: #DFDFDF;
}
.brand-mastercard .hosted-field-focus {
border-color: #FFC3C4;
}
.brand-visa .hosted-field-focus {
border-color: #858ae3;
}
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 form = document.querySelector(".form");
var submitButton = form.querySelector(".button");
var responseContainer = document.querySelector(".response");
[cardName, cardNumber, cardExpiry, cardCvv].forEach(function (field) {
field.on("change", function (event) {
console.log(event);
var errorElement = document.querySelector(
"." + event.fieldType + "-container .error"
);
toggleError(errorElement, event);
});
});
cardNumber.on("change", function (event) {
form.classList.remove(
"has-brand",
"brand-amex",
"brand-mastercard",
"brand-visa",
"brand-unknown"
);
if (event.cardBrand) {
form.classList.add(`brand-${event.cardBrand}`);
if (event.cardBrand !== "unknown") {
form.classList.add("has-brand");
}
}
});
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_AUTH_TOKEN"
})
.then(function (response) {
resetSubmitButton();
// handle create card account succeeded
responseContainer.classList.add("response-success");
responseContainer.innerText = "Card account successfully created.";
})
.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");
}
This Pen doesn't use any external CSS resources.