* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
max-width: 900px;
width: 100%;
}
.card-display {
perspective: 1000px;
margin-bottom: 40px;
}
.credit-card {
width: 100%;
max-width: 420px;
height: 260px;
margin: 0 auto;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
border-radius: 20px;
padding: 30px;
color: white;
position: relative;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
transition: transform 0.6s;
transform-style: preserve-3d;
}
.credit-card.flipped {
transform: rotateY(180deg);
}
.card-front, .card-back {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
padding: 30px;
backface-visibility: hidden;
border-radius: 20px;
}
.card-back {
transform: rotateY(180deg);
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
}
.card-chip {
width: 50px;
height: 40px;
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
border-radius: 8px;
margin-bottom: 20px;
position: relative;
overflow: hidden;
}
.card-chip::before {
content: '';
position: absolute;
width: 100%;
height: 25%;
background: rgba(0,0,0,0.1);
top: 25%;
}
.card-chip::after {
content: '';
position: absolute;
width: 100%;
height: 25%;
background: rgba(0,0,0,0.1);
top: 50%;
}
.card-number {
font-size: 24px;
letter-spacing: 4px;
margin-bottom: 25px;
font-weight: 300;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.card-info {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.card-holder, .card-expiry {
flex: 1;
}
.card-label {
font-size: 10px;
text-transform: uppercase;
letter-spacing: 1px;
opacity: 0.8;
margin-bottom: 5px;
}
.card-value {
font-size: 16px;
text-transform: uppercase;
letter-spacing: 1px;
}
.card-logo {
position: absolute;
top: 30px;
right: 30px;
font-size: 48px;
opacity: 0.8;
}
.magnetic-strip {
width: 100%;
height: 50px;
background: #000;
margin: 30px 0 20px 0;
}
.cvv-section {
background: white;
height: 40px;
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0 15px;
border-radius: 4px;
margin-bottom: 15px;
}
.cvv-value {
color: #000;
font-size: 18px;
letter-spacing: 2px;
}
.signature-strip {
background: rgba(255,255,255,0.8);
height: 35px;
border-radius: 4px;
position: relative;
}
.form-container {
background: white;
border-radius: 20px;
padding: 40px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
.form-title {
font-size: 28px;
font-weight: 700;
color: #2c3e50;
margin-bottom: 30px;
text-align: center;
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group.full-width {
grid-column: 1 / -1;
}
.form-label {
display: block;
font-size: 14px;
font-weight: 600;
color: #2c3e50;
margin-bottom: 8px;
}
.form-input {
width: 100%;
padding: 14px 16px;
border: 2px solid #e9ecef;
border-radius: 10px;
font-size: 16px;
transition: all 0.3s;
font-family: inherit;
}
.form-input:focus {
outline: none;
border-color: #3498db;
box-shadow: 0 0 0 4px rgba(52, 152, 219, 0.1);
}
.form-input.error {
border-color: #e74c3c;
}
.form-input.success {
border-color: #27ae60;
}
.input-wrapper {
position: relative;
}
.input-icon {
position: absolute;
right: 16px;
top: 50%;
transform: translateY(-50%);
font-size: 20px;
pointer-events: none;
}
.input-icon.success {
color: #27ae60;
}
.input-icon.error {
color: #e74c3c;
}
.error-message {
color: #e74c3c;
font-size: 13px;
margin-top: 6px;
display: none;
}
.error-message.show {
display: block;
}
.submit-btn {
width: 100%;
padding: 16px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 18px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
margin-top: 10px;
}
.submit-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.4);
}
.submit-btn:active {
transform: translateY(0);
}
.submit-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.card-types {
display: flex;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
}
.card-type-icon {
width: 50px;
height: 32px;
border: 2px solid #e9ecef;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
opacity: 0.4;
transition: all 0.3s;
}
.card-type-icon.active {
opacity: 1;
border-color: #3498db;
background: rgba(52, 152, 219, 0.1);
}
@media (max-width: 768px) {
.form-row {
grid-template-columns: 1fr;
}
.credit-card {
max-width: 100%;
height: 220px;
padding: 25px;
}
.card-number {
font-size: 20px;
}
.form-container {
padding: 30px 20px;
}
}
// Luhn Algorithm for credit card validation
function luhnCheck(cardNumber) {
let sum = 0;
let isEven = false;
for (let i = cardNumber.length - 1; i >= 0; i--) {
let digit = parseInt(cardNumber[i]);
if (isEven) {
digit *= 2;
if (digit > 9) {
digit -= 9;
}
}
sum += digit;
isEven = !isEven;
}
return sum % 10 === 0;
}
// Detect card type
function detectCardType(number) {
const patterns = {
visa: /^4/,
mastercard: /^5[1-5]/,
amex: /^3[47]/,
discover: /^6(?:011|5)/
};
for (let type in patterns) {
if (patterns[type].test(number)) {
return type;
}
}
return null;
}
// Format card number with spaces
function formatCardNumber(value) {
return value.replace(/\s/g, '').replace(/(\d{4})/g, '$1 ').trim();
}
// Format expiry date
function formatExpiryDate(value) {
const cleaned = value.replace(/\D/g, '');
if (cleaned.length >= 2) {
return cleaned.slice(0, 2) + '/' + cleaned.slice(2, 4);
}
return cleaned;
}
// Validate expiry date
function validateExpiry(expiry) {
const [month, year] = expiry.split('/');
if (!month || !year || month.length !== 2 || year.length !== 2) return false;
const monthNum = parseInt(month);
const yearNum = parseInt('20' + year);
const currentYear = new Date().getFullYear();
const currentMonth = new Date().getMonth() + 1;
if (monthNum < 1 || monthNum > 12) return false;
if (yearNum < currentYear) return false;
if (yearNum === currentYear && monthNum < currentMonth) return false;
return true;
}
// Elements
const cardNumber = document.getElementById('cardNumber');
const cardHolder = document.getElementById('cardHolder');
const expiryDate = document.getElementById('expiryDate');
const cvv = document.getElementById('cvv');
const cardForm = document.getElementById('cardForm');
const creditCard = document.getElementById('creditCard');
// Display elements
const displayCardNumber = document.getElementById('displayCardNumber');
const displayCardHolder = document.getElementById('displayCardHolder');
const displayExpiry = document.getElementById('displayExpiry');
const displayCVV = document.getElementById('displayCVV');
const cardLogo = document.getElementById('cardLogo');
// Card Number Input
cardNumber.addEventListener('input', (e) => {
let value = e.target.value.replace(/\s/g, '').replace(/\D/g, '');
e.target.value = formatCardNumber(value);
const cleanNumber = value.replace(/\s/g, '');
displayCardNumber.textContent = e.target.value || '#### #### #### ####';
// Validate and show feedback
const isValid = cleanNumber.length >= 13 && luhnCheck(cleanNumber);
updateFieldValidation(cardNumber, 'cardNumberIcon', 'cardNumberError', isValid && cleanNumber.length >= 13);
// Detect and highlight card type
const cardType = detectCardType(cleanNumber);
document.querySelectorAll('.card-type-icon').forEach(icon => {
icon.classList.remove('active');
if (cardType && icon.dataset.type === cardType) {
icon.classList.add('active');
}
});
});
// Card Holder Input
cardHolder.addEventListener('input', (e) => {
const value = e.target.value.toUpperCase();
displayCardHolder.textContent = value || 'YOUR NAME';
const isValid = value.length >= 3 && /^[A-Z\s]+$/.test(value);
updateFieldValidation(cardHolder, 'cardHolderIcon', 'cardHolderError', isValid);
});
// Expiry Date Input
expiryDate.addEventListener('input', (e) => {
let value = e.target.value.replace(/\D/g, '');
e.target.value = formatExpiryDate(value);
displayExpiry.textContent = e.target.value || 'MM/YY';
const isValid = e.target.value.length === 5 && validateExpiry(e.target.value);
updateFieldValidation(expiryDate, 'expiryIcon', 'expiryError', isValid);
});
// CVV Input
cvv.addEventListener('input', (e) => {
e.target.value = e.target.value.replace(/\D/g, '');
displayCVV.textContent = e.target.value || '***';
const isValid = e.target.value.length >= 3;
updateFieldValidation(cvv, 'cvvIcon', 'cvvError', isValid);
});
// CVV Focus - Flip card
cvv.addEventListener('focus', () => {
creditCard.classList.add('flipped');
});
cvv.addEventListener('blur', () => {
creditCard.classList.remove('flipped');
});
// Update field validation visual feedback
function updateFieldValidation(input, iconId, errorId, isValid) {
const icon = document.getElementById(iconId);
const error = document.getElementById(errorId);
if (input.value.length > 0) {
if (isValid) {
input.classList.remove('error');
input.classList.add('success');
icon.style.display = 'block';
error.classList.remove('show');
} else {
input.classList.remove('success');
input.classList.add('error');
icon.style.display = 'none';
error.classList.add('show');
}
} else {
input.classList.remove('error', 'success');
icon.style.display = 'none';
error.classList.remove('show');
}
}
// Form submission
cardForm.addEventListener('submit', (e) => {
e.preventDefault();
const cleanNumber = cardNumber.value.replace(/\s/g, '');
const isCardValid = cleanNumber.length >= 13 && luhnCheck(cleanNumber);
const isHolderValid = cardHolder.value.length >= 3;
const isExpiryValid = validateExpiry(expiryDate.value);
const isCvvValid = cvv.value.length >= 3;
if (isCardValid && isHolderValid && isExpiryValid && isCvvValid) {
alert('✅ Payment validated successfully!\n\nCard Type: ' + (detectCardType(cleanNumber) || 'Unknown') + '\nThis is a demo - no actual payment processed.');
} else {
alert('❌ Please fix the errors in the form');
}
});
No comments yet. Be the first!