Premium Login form Template
Preview
Edit
Download
Run
Download Options
HTML File
Download as .html file
CSS File
Download as .css file
JavaScript File
Download as .js file
Combined HTML
All code in one HTML file
Project ZIP
All files in a ZIP archive
Cancel
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Premium Login Experience</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"> </head> <body class="premium-gradient min-h-screen flex items-center justify-center p-4 relative overflow-hidden"> <!-- Dark Mode Toggle --> <div class="dark-mode-toggle"> <input type="checkbox" id="darkModeToggle" class="toggle-checkbox sr-only"> <label for="darkModeToggle" class="toggle-label"> <span class="toggle-ball"></span> <span class="sr-only">Toggle dark mode</span> </label> </div> <!-- Floating Orbs --> <div class="floating-orb hidden md:block"></div> <div class="floating-orb hidden md:block"></div> <div class="floating-orb hidden md:block"></div> <div class="floating-orb hidden md:block"></div> <!-- Login Container --> <div class="entrance-animation glass-morphism rounded-3xl p-8 md:p-10 w-full max-w-md mx-4 shadow-2xl relative login-container"> <!-- Header --> <div class="text-center mb-8 md:mb-10"> <div class="w-16 h-16 md:w-20 md:h-20 bg-gradient-to-br from-white/20 to-white/10 rounded-2xl flex items-center justify-center mx-auto mb-4 md:mb-6 backdrop-blur-sm border border-white/20"> <svg class="w-8 h-8 md:w-10 md:h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"> </path> </svg> </div> <h1 class="text-3xl md:text-4xl font-bold text-white mb-2 md:mb-3 bg-gradient-to-r from-white to-white/80 bg-clip-text"> Welcome Back </h1> <p class="text-white/70 text-base md:text-lg">Enter your credentials to access your account</p> </div> <!-- Login Form --> <form id="loginForm" class="space-y-4 md:space-y-6"> <!-- Email Input --> <div class="input-container"> <div class="relative"> <svg class="absolute left-4 top-1/2 transform -translate-y-1/2 w-5 h-5 text-white/60 z-10" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207"> </path> </svg> <input type="email" id="email" name="email" class="premium-input ripple-effect" placeholder=" " required autocomplete="email"> <label class="floating-label" for="email">Email Address</label> </div> </div> <!-- Password Input --> <div class="input-container"> <div class="relative"> <svg class="absolute left-4 top-1/2 transform -translate-y-1/2 w-5 h-5 text-white/60 z-10" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"> </path> </svg> <input type="password" id="password" name="password" class="premium-input ripple-effect" placeholder=" " required autocomplete="current-password"> <label class="floating-label" for="password">Password</label> <button type="button" id="togglePassword" class="absolute right-4 top-1/2 transform -translate-y-1/2 text-white/60 hover:text-white transition-colors z-10" aria-label="Toggle password visibility"> <svg id="eyeIcon" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"> </path> </svg> </button> </div> <div class="strength-meter"> <div id="strengthFill" class="strength-fill" style="width: 0%"></div> </div> </div> <!-- Remember Me & Forgot Password --> <div class="flex items-center justify-between"> <label class="flex items-center cursor-pointer"> <input type="checkbox" id="rememberMe" class="sr-only" aria-labelledby="rememberMeLabel"> <div class="relative"> <div class="w-5 h-5 bg-white/10 border border-white/30 rounded transition-all duration-300"> </div> <svg class="absolute inset-0 w-5 h-5 text-white opacity-0 transition-opacity duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"> </path> </svg> </div> <span id="rememberMeLabel" class="ml-3 text-white/80">Remember me</span> </label> <a href="#" class="text-white/80 hover:text-white transition-colors font-medium text-sm md:text-base">Forgot password?</a> </div> <!-- Login Button --> <button type="submit" id="loginButton" class="premium-button ripple-effect"> <span id="buttonText">Sign In</span> <div id="loadingDots" class="loading-dots hidden"> <div class="loading-dot"></div> <div class="loading-dot"></div> <div class="loading-dot"></div> </div> </button> <!-- Divider --> <div class="relative my-6 md:my-8"> <div class="absolute inset-0 flex items-center"> <div class="w-full border-t border-white/20"></div> </div> <div class="relative flex justify-center"> <span class="px-4 bg-transparent text-white/60 text-sm">Or continue with</span> </div> </div> <!-- Social Login --> <div class="grid grid-cols-3 gap-3 md:gap-4 social-buttons"> <button type="button" class="social-button ripple-effect" data-provider="Google" aria-label="Sign in with Google"> <svg class="w-5 h-5" viewBox="0 0 24 24"> <path fill="currentColor" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" /> <path fill="currentColor" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" /> <path fill="currentColor" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" /> <path fill="currentColor" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" /> </svg> <span class="hidden md:inline ml-2">Google</span> </button> <button type="button" class="social-button ripple-effect" data-provider="Apple" aria-label="Sign in with Apple"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" /> </svg> <span class="hidden md:inline ml-2">Apple</span> </button> <button type="button" class="social-button ripple-effect" data-provider="GitHub" aria-label="Sign in with GitHub"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /> </svg> <span class="hidden md:inline ml-2">GitHub</span> </button> </div> <!-- Sign Up Link --> <div class="text-center mt-6 md:mt-8"> <p class="text-white/70 text-sm md:text-base"> Don't have an account? <a href="#" class="text-white hover:underline font-semibold ml-1">Create one now</a> </p> </div> </form> </div> <!-- Success Modal --> <div id="successModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center p-4 opacity-0 pointer-events-none transition-all duration-500 z-50"> <div class="glass-morphism rounded-2xl p-6 md:p-8 text-center max-w-sm w-full transform scale-75 transition-transform duration-500"> <div class="success-checkmark"> <svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path> </svg> </div> <h3 class="text-xl md:text-2xl font-bold text-white mb-2">Welcome!</h3> <p class="text-white/80 text-sm md:text-base">You have successfully signed in to your account.</p> </div> </div> <!-- Notification --> <div id="notification" class="notification"> <div class="flex items-center"> <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> </svg> <span id="notificationText" class="text-sm md:text-base"></span> </div> </div> </body> </html>
CSS
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); * { font-family: 'Inter', sans-serif; } .premium-gradient { background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #f5576c 75%, #4facfe 100%); background-size: 400% 400%; animation: gradientShift 15s ease infinite; } @keyframes gradientShift { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .glass-morphism { background: rgba(255, 255, 255, 0.08); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.15); box-shadow: 0 25px 45px rgba(0, 0, 0, 0.1); } .floating-orb { position: absolute; border-radius: 50%; background: linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05)); animation: floatOrb 8s ease-in-out infinite; filter: blur(1px); } .floating-orb:nth-child(1) { width: 80px; height: 80px; top: 10%; left: 10%; animation-delay: 0s; } .floating-orb:nth-child(2) { width: 120px; height: 120px; top: 10%; right: 10%; animation-delay: -2s; } .floating-orb:nth-child(3) { width: 60px; height: 60px; bottom: 10%; left: 15%; animation-delay: -4s; } .floating-orb:nth-child(4) { width: 100px; height: 100px; bottom: 10%; right: 20%; animation-delay: -6s; } @keyframes floatOrb { 0%, 100% { transform: translateY(0px) translateX(0px) rotate(0deg); opacity: 0.3; } 25% { transform: translateY(-30px) translateX(20px) rotate(90deg); opacity: 0.6; } 50% { transform: translateY(-15px) translateX(-20px) rotate(180deg); opacity: 0.4; } 75% { transform: translateY(-25px) translateX(15px) rotate(270deg); opacity: 0.5; } } .entrance-animation { animation: entranceSlide 1.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); } @keyframes entranceSlide { 0% { opacity: 0; transform: translateY(50px) scale(0.9); } 100% { opacity: 1; transform: translateY(0) scale(1); } } .input-container { position: relative; margin-bottom: 1.5rem; } .floating-label { position: absolute; left: 48px; top: 50%; transform: translateY(-50%); color: rgba(255, 255, 255, 0.6); transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); pointer-events: none; font-size: 16px; } .premium-input { width: 100%; padding: 16px 16px 16px 48px; background: rgba(255, 255, 255, 0.05); border: 2px solid rgba(255, 255, 255, 0.1); border-radius: 12px; color: white; font-size: 16px; transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); outline: none; } .premium-input:focus, .premium-input:not(:placeholder-shown) { border-color: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.08); transform: translateY(-2px); box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(255, 255, 255, 0.1); } .premium-input:focus+.floating-label, .premium-input:not(:placeholder-shown)+.floating-label { top: -8px; left: 12px; font-size: 12px; color: rgba(255, 255, 255, 0.9); background: linear-gradient(135deg, #667eea, #764ba2); padding: 2px 8px; border-radius: 4px; font-weight: 500; } .premium-button { position: relative; width: 100%; padding: 16px; background: linear-gradient(135deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.1)); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; color: white; font-weight: 600; font-size: 16px; cursor: pointer; overflow: hidden; transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); outline: none; } .premium-button:before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); transition: left 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94); } .premium-button:hover { transform: translateY(-3px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2); background: linear-gradient(135deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.2)); } .premium-button:hover:before { left: 100%; } .premium-button:active { transform: translateY(-1px); } .social-button { position: relative; display: flex; align-items: center; justify-content: center; padding: 12px 16px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 10px; color: white; text-decoration: none; transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); overflow: hidden; } .social-button:hover { background: rgba(255, 255, 255, 0.1); transform: translateY(-2px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } .ripple-effect { position: relative; overflow: hidden; } .ripple { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.3); transform: scale(0); animation: rippleAnimation 0.6s linear; pointer-events: none; } @keyframes rippleAnimation { to { transform: scale(4); opacity: 0; } } .success-checkmark { width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, #4facfe, #00f2fe); display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; transform: scale(0); animation: checkmarkPop 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; } @keyframes checkmarkPop { to { transform: scale(1); } } .particle { position: absolute; width: 4px; height: 4px; background: rgba(255, 255, 255, 0.6); border-radius: 50%; pointer-events: none; animation: particleFloat 3s ease-out forwards; } @keyframes particleFloat { 0% { opacity: 1; transform: translateY(0) scale(1); } 100% { opacity: 0; transform: translateY(-100px) scale(0); } } .loading-dots { display: inline-flex; gap: 4px; } .loading-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: loadingDots 1.4s ease-in-out infinite both; } .loading-dot:nth-child(1) { animation-delay: -0.32s; } .loading-dot:nth-child(2) { animation-delay: -0.16s; } .loading-dot:nth-child(3) { animation-delay: 0s; } @keyframes loadingDots { 0%, 80%, 100% { transform: scale(0); opacity: 0.5; } 40% { transform: scale(1); opacity: 1; } } .notification { position: fixed; top: 20px; right: 20px; padding: 16px 24px; background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 12px; color: white; transform: translateX(400px); transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); z-index: 1000; max-width: calc(100% - 40px); box-sizing: border-box; } .notification.show { transform: translateX(0); } .strength-meter { height: 4px; background: rgba(255, 255, 255, 0.1); border-radius: 2px; margin-top: 8px; overflow: hidden; } .strength-fill { height: 100%; border-radius: 2px; transition: all 0.3s ease; background: linear-gradient(90deg, #ff4757, #ffa502, #2ed573); } /* Dark mode toggle */ .dark-mode-toggle { position: fixed; top: 20px; left: 20px; z-index: 1000; } .toggle-checkbox { position: absolute; opacity: 0; cursor: pointer; height: 0; width: 0; } .toggle-label { display: flex; align-items: center; justify-content: space-between; cursor: pointer; width: 50px; height: 26px; background: rgba(255, 255, 255, 0.2); border-radius: 50px; position: relative; transition: background-color .2s; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); } .toggle-label .toggle-ball { content: ''; position: absolute; top: 2px; left: 2px; width: 22px; height: 22px; border-radius: 50%; transition: 0.3s; background: white; box-shadow: 0 0 2px 0 rgba(10, 10, 10, 0.29); } .toggle-checkbox:checked+.toggle-label .toggle-ball { left: calc(100% - 2px); transform: translateX(-100%); } .toggle-label:active .toggle-ball { width: 28px; } /* Responsive adjustments */ @media (max-width: 768px) { .login-container { padding: 2rem; margin: 1rem; width: calc(100% - 2rem); } .floating-orb { display: none; } .premium-input { padding: 14px 14px 14px 44px; font-size: 15px; } .floating-label { left: 44px; font-size: 15px; } .premium-input:focus+.floating-label, .premium-input:not(:placeholder-shown)+.floating-label { left: 10px; font-size: 11px; } .social-button { padding: 10px 12px; } } @media (max-width: 480px) { .login-container { padding: 1.5rem; border-radius: 20px; } .premium-input { padding: 12px 12px 12px 40px; } .floating-label { left: 40px; } .premium-button { padding: 14px; } .social-buttons { grid-template-columns: 1fr; gap: 10px; } .social-button { justify-content: flex-start; padding-left: 16px; } .social-button svg { margin-right: 8px; } } /* Accessibility improvements */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } /* Focus styles for better accessibility */ .premium-input:focus-visible, .premium-button:focus-visible, .social-button:focus-visible { outline: 2px solid rgba(255, 255, 255, 0.8); outline-offset: 2px; } /* Password strength colors */ .strength-weak { background: linear-gradient(90deg, #ff4757, #ff4757); } .strength-medium { background: linear-gradient(90deg, #ff4757, #ffa502); } .strength-strong { background: linear-gradient(90deg, #ff4757, #ffa502, #2ed573); }
JavaScript
// Enhanced functionality with dark mode and improved features class PremiumLogin { constructor() { this.initializeElements(); this.bindEvents(); this.initializeAnimations(); this.checkDarkModePreference(); } initializeElements() { this.form = document.getElementById('loginForm'); this.emailInput = document.getElementById('email'); this.passwordInput = document.getElementById('password'); this.togglePassword = document.getElementById('togglePassword'); this.eyeIcon = document.getElementById('eyeIcon'); this.loginButton = document.getElementById('loginButton'); this.buttonText = document.getElementById('buttonText'); this.loadingDots = document.getElementById('loadingDots'); this.rememberMe = document.getElementById('rememberMe'); this.strengthFill = document.getElementById('strengthFill'); this.successModal = document.getElementById('successModal'); this.notification = document.getElementById('notification'); this.notificationText = document.getElementById('notificationText'); this.darkModeToggle = document.getElementById('darkModeToggle'); this.body = document.body; } bindEvents() { // Form submission this.form.addEventListener('submit', (e) => this.handleSubmit(e)); // Password toggle this.togglePassword.addEventListener('click', () => this.togglePasswordVisibility()); // Password strength this.passwordInput.addEventListener('input', (e) => this.updatePasswordStrength(e.target.value)); // Remember me checkbox this.rememberMe.addEventListener('change', () => this.toggleRememberMe()); // Social login buttons document.querySelectorAll('.social-button').forEach(button => { button.addEventListener('click', (e) => this.handleSocialLogin(e)); }); // Ripple effects document.querySelectorAll('.ripple-effect').forEach(element => { element.addEventListener('click', (e) => this.createRipple(e)); }); // Input animations [this.emailInput, this.passwordInput].forEach(input => { input.addEventListener('focus', () => this.createParticles(input)); }); // Dark mode toggle this.darkModeToggle.addEventListener('change', () => this.toggleDarkMode()); } initializeAnimations() { // Stagger animation for form elements const elements = document.querySelectorAll('.input-container, .premium-button, .social-button'); elements.forEach((el, index) => { el.style.animationDelay = `${index * 0.1}s`; el.classList.add('entrance-animation'); }); } checkDarkModePreference() { const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const storedDarkMode = localStorage.getItem('darkMode'); if (storedDarkMode === 'true' || (storedDarkMode === null && prefersDark)) { this.darkModeToggle.checked = true; this.enableDarkMode(); } } toggleDarkMode() { if (this.darkModeToggle.checked) { this.enableDarkMode(); localStorage.setItem('darkMode', 'true'); } else { this.disableDarkMode(); localStorage.setItem('darkMode', 'false'); } } enableDarkMode() { this.body.classList.add('dark-mode'); // Change gradient to darker colors this.body.style.background = 'linear-gradient(135deg, #4b6cb7 0%, #182848 100%)'; } disableDarkMode() { this.body.classList.remove('dark-mode'); // Revert to original gradient this.body.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #f5576c 75%, #4facfe 100%)'; } async handleSubmit(e) { e.preventDefault(); if (!this.validateForm()) return; this.setLoadingState(true); try { // Simulate API call await this.simulateLogin(); this.showSuccess(); } catch (error) { this.showNotification('Login failed. Please try again.', 'error'); } finally { this.setLoadingState(false); } } validateForm() { const email = this.emailInput.value.trim(); const password = this.passwordInput.value; if (!email || !this.isValidEmail(email)) { this.showNotification('Please enter a valid email address.', 'error'); this.emailInput.focus(); return false; } if (!password || password.length < 6) { this.showNotification('Password must be at least 6 characters long.', 'error'); this.passwordInput.focus(); return false; } return true; } isValidEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } simulateLogin() { return new Promise((resolve) => { setTimeout(resolve, 2000); }); } setLoadingState(loading) { if (loading) { this.buttonText.style.display = 'none'; this.loadingDots.classList.remove('hidden'); this.loginButton.disabled = true; } else { this.buttonText.style.display = 'inline'; this.loadingDots.classList.add('hidden'); this.loginButton.disabled = false; } } showSuccess() { this.successModal.style.opacity = '1'; this.successModal.style.pointerEvents = 'auto'; this.successModal.querySelector('.glass-morphism').style.transform = 'scale(1)'; // Create celebration particles this.createCelebrationParticles(); setTimeout(() => { this.hideSuccess(); }, 3000); } hideSuccess() { this.successModal.style.opacity = '0'; this.successModal.style.pointerEvents = 'none'; this.successModal.querySelector('.glass-morphism').style.transform = 'scale(0.75)'; } showNotification(message, type = 'info') { this.notificationText.textContent = message; // Set notification color based on type if (type === 'error') { this.notification.style.background = 'rgba(239, 68, 68, 0.2)'; this.notification.style.borderColor = 'rgba(239, 68, 68, 0.3)'; } else if (type === 'success') { this.notification.style.background = 'rgba(16, 185, 129, 0.2)'; this.notification.style.borderColor = 'rgba(16, 185, 129, 0.3)'; } else { this.notification.style.background = 'rgba(255, 255, 255, 0.1)'; this.notification.style.borderColor = 'rgba(255, 255, 255, 0.2)'; } this.notification.classList.add('show'); setTimeout(() => { this.notification.classList.remove('show'); }, 4000); } togglePasswordVisibility() { const isPassword = this.passwordInput.type === 'password'; this.passwordInput.type = isPassword ? 'text' : 'password'; this.eyeIcon.innerHTML = isPassword ? `<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"></path>` : `<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path>`; } updatePasswordStrength(password) { let strength = 0; const hasLength = password.length >= 8; const hasLower = /[a-z]/.test(password); const hasUpper = /[A-Z]/.test(password); const hasNumber = /[0-9]/.test(password); const hasSpecial = /[^A-Za-z0-9]/.test(password); if (hasLength) strength += 20; if (hasLower) strength += 20; if (hasUpper) strength += 20; if (hasNumber) strength += 20; if (hasSpecial) strength += 20; this.strengthFill.style.width = `${strength}%`; // Update strength meter color if (strength < 40) { this.strengthFill.className = 'strength-fill strength-weak'; } else if (strength < 80) { this.strengthFill.className = 'strength-fill strength-medium'; } else { this.strengthFill.className = 'strength-fill strength-strong'; } } toggleRememberMe() { const checkbox = this.rememberMe.parentElement.querySelector('div'); const checkmark = this.rememberMe.parentElement.querySelector('svg'); if (this.rememberMe.checked) { checkbox.style.background = 'linear-gradient(135deg, #4facfe, #00f2fe)'; checkbox.style.borderColor = 'rgba(79, 172, 254, 0.5)'; checkmark.style.opacity = '1'; } else { checkbox.style.background = 'rgba(255, 255, 255, 0.1)'; checkbox.style.borderColor = 'rgba(255, 255, 255, 0.3)'; checkmark.style.opacity = '0'; } } handleSocialLogin(e) { const provider = e.currentTarget.dataset.provider; this.showNotification(`Redirecting to ${provider} authentication...`, 'info'); // Simulate redirect delay setTimeout(() => { this.showNotification(`${provider} login would redirect in a real application.`, 'info'); }, 1500); } createRipple(e) { const button = e.currentTarget; const rect = button.getBoundingClientRect(); const size = Math.max(rect.width, rect.height); const x = e.clientX - rect.left - size / 2; const y = e.clientY - rect.top - size / 2; const ripple = document.createElement('div'); ripple.classList.add('ripple'); ripple.style.width = ripple.style.height = size + 'px'; ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; button.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); } createParticles(input) { const rect = input.getBoundingClientRect(); const particleCount = 5; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); particle.style.left = (rect.left + Math.random() * rect.width) + 'px'; particle.style.top = (rect.top + rect.height) + 'px'; document.body.appendChild(particle); setTimeout(() => { particle.remove(); }, 3000); } } createCelebrationParticles() { const particleCount = 30; const successModal = this.successModal.querySelector('.glass-morphism'); const rect = successModal.getBoundingClientRect(); for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); particle.style.left = (rect.left + Math.random() * rect.width) + 'px'; particle.style.top = (rect.top + Math.random() * rect.height) + 'px'; particle.style.width = particle.style.height = (Math.random() * 6 + 2) + 'px'; particle.style.background = `hsl(${Math.random() * 360}, 100%, 80%)`; particle.style.animationDuration = (Math.random() * 2 + 1) + 's'; document.body.appendChild(particle); setTimeout(() => { particle.remove(); }, 3000); } } } // Initialize the premium login experience document.addEventListener('DOMContentLoaded', () => { new PremiumLogin(); });
Output Preview
Desktop
Mobile
Fullscreen