Skip to content

Instantly share code, notes, and snippets.

@trszdev
Last active June 22, 2019 18:33
Show Gist options
  • Save trszdev/dbeebf212fb7bb59b43e96681d08a710 to your computer and use it in GitHub Desktop.
Save trszdev/dbeebf212fb7bb59b43e96681d08a710 to your computer and use it in GitHub Desktop.
HTML/CSS/JS - payment page with input masking and native form validation (https://jsfiddle.net/pu57Lns8/1/)
<!--
Minimal example of payment page with input masking and native form validation
https://jsfiddle.net/pu57Lns8/1/
One of the caveats in this example maybe using "minlength" attribute while changing input value programmatically:
this won't check real validity.
From html5 spec (minlength attribute): If an element has a minimum allowed value length, its dirty value flag is true,
VALUE WAS LAST CHANGED BY A USER EDIT (AS OPPOSED TO A CHANGE MADE BY A SCRIPT),
its value is not the empty string, and the code-unit length of the element’s value
is less than the element’s minimum allowed value length, then the element is suffering from being too short.
Original answer: https://stackoverflow.com/a/53261163
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Payment form example</title>
<style>
.card {
width: 400px;
height: 250px;
border-radius: 20px;
background: #ccc;
position: absolute;
top: 25px;
left: 110px;
}
.payment-form {
position: relative;
font-family: Arial, Helvetica, sans-serif;
font-size: 20px;
}
.input {
padding: 0 5px;
height: 30px;
font-size: 20px;
}
.magnet-strip {
position: absolute;
top: 40px;
background: #444;
width: 100%;
height: 40px;
}
.cvc {
position: absolute;
bottom: 60px;
right: 40px;
width: 40px;
}
.hex-card {
top: 0;
left: 0;
background: #f44;
}
.bank-logo {
font-size: 22px;
font-weight: bold;
color: #fff;
position: absolute;
left: 30px;
top: 30px;
}
.hex {
font-size: 30px;
font-family: "Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter", monospace;
font-weight: bold;
position: absolute;
bottom: 100px;
right: 50%;
transform: translateX(50%);
width: 343px;
}
.label {
font-size: 14px;
}
.label-cvc {
position: absolute;
bottom: 100px;
right: 41px;
}
.label-hex {
position: absolute;
bottom: 140px;
right: 21px;
}
</style>
</head>
<body>
<form class="payment-form" id="payment-form">
<input type=submit hidden>
<div class="card cvc-card">
<div class="magnet-strip"></div>
<label for=cvc class="label label-cvc">CVC</label>
<input tabindex=2 id=cvc class="input cvc" size=3 required maxlength=3 pattern="\d{3}">
</div>
<div class="card hex-card">
<div class="bank-logo">$$$ mybank</div>
<label for=hex class="label label-hex">Card number</label>
<input tabindex=1 id=hex class="input hex" size=19 required maxlength=19 pattern=".{19}" placeholder="1234 1234 1234 1234">
</div>
</form>
<script>
document.getElementById('payment-form').onsubmit = e => {
alert(['hex', 'cvc'].map(x => document.getElementById(x).value))
e.preventDefault()
}
document.getElementById('hex').oninput = e => {
const pure = e.target.value.replace(/[^\d]/g, '')
const parts = pure.match(/(.{4}|.{1,3})/g) || []
const newValue = parts.join(' ')
e.target.value = newValue
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment