-
Interactive liquid login form animation
HTML
CSS
JavaScript
System_Auth
Operator ID
Passcode
INITIALIZE
:root { /* Core Palette */ --bg-color: #05050A; --primary: #FF0055; /* Hot Magenta */ --secondary: #00F0FF; /* Electric Cyan */ --tertiary: #7000FF; /* Neon Purple */ /* Status Colors */ --error: #FF1010; --success: #00FF66; --glass-bg: rgba(10, 10, 15, 0.4); --glass-border: rgba(0, 240, 255, 0.2); --glass-highlight: rgba(255, 255, 255, 0.1); } * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--bg-color); min-height: 100vh; display: flex; justify-content: center; align-items: center; overflow: hidden; position: relative; transition: --primary 0.5s, --secondary 0.5s; } /* Dynamic State Classes applied to body via JS */ body.error-state { --primary: var(--error); --secondary: #FF4D4D; --glass-border: rgba(255, 16, 16, 0.4); } body.success-state { --primary: var(--success); --secondary: #00CC52; --glass-border: rgba(0, 255, 102, 0.4); } .svg-filters { position: absolute; width: 0; height: 0; } /* Fluid Background */ .liquid-container { position: absolute; width: 100vw; height: 100vh; filter: url('#goo'); z-index: 0; overflow: hidden; } .blob { position: absolute; border-radius: 50%; /* 40-degree gradient angle for optimal visual flow and blending */ background: linear-gradient(40deg, var(--primary), var(--secondary)); animation: float 10s infinite ease-in-out alternate; transition: transform 0.3s ease, width 0.4s ease, height 0.4s ease, background 0.5s ease; } .blob-1 { width: 350px; height: 350px; top: 15%; left: 25%; animation-duration: 14s; background: linear-gradient(40deg, var(--tertiary), var(--primary)); } .blob-2 { width: 280px; height: 280px; top: 45%; left: 65%; animation-duration: 18s; animation-direction: alternate-reverse; } .blob-cursor { width: 100px; height: 100px; position: absolute; transform: translate(-50%, -50%); pointer-events: none; background: var(--secondary); opacity: 0.8; box-shadow: 0 0 40px var(--secondary); } @keyframes float { 0% { transform: translate(0, 0) scale(1) rotate(0deg); } 50% { transform: translate(60px, -40px) scale(1.15) rotate(90deg); } 100% { transform: translate(-40px, 60px) scale(0.9) rotate(180deg); } } /* 3D Glassmorphism Card Container */ .card-wrapper { perspective: 1200px; z-index: 10; } .login-card { width: 420px; padding: 50px 40px; background: var(--glass-bg); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid var(--glass-border); border-top: 1px solid var(--glass-highlight); border-left: 1px solid var(--glass-highlight); border-radius: 24px; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5), inset 0 0 20px rgba(0, 0, 0, 0.2); transition: transform 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94), border-color 0.5s ease; transform-style: preserve-3d; position: relative; } /* Error Shake Animation */ @keyframes shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-15px) rotateY(-5deg); } 40% { transform: translateX(15px) rotateY(5deg); } 60% { transform: translateX(-10px) rotateY(-3deg); } 80% { transform: translateX(10px) rotateY(3deg); } } .login-card.shake { animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both; } .login-card h2 { color: #fff; text-align: center; margin-bottom: 35px; font-size: 32px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; text-shadow: 0 0 10px rgba(255, 255, 255, 0.3); transform: translateZ(30px); transition: color 0.5s ease, text-shadow 0.5s ease; } /* Status Message UI */ .status-message { position: absolute; top: 20px; left: 0; width: 100%; text-align: center; font-size: 13px; font-weight: 700; letter-spacing: 2px; opacity: 0; transform: translateZ(40px) translateY(-10px); transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); pointer-events: none; } .status-message.show { opacity: 1; transform: translateZ(40px) translateY(0); } body.error-state .status-message { color: var(--error); text-shadow: 0 0 10px rgba(255, 16, 16, 0.6); } body.success-state .status-message { color: var(--success); text-shadow: 0 0 10px rgba(0, 255, 102, 0.6); } .input-group { position: relative; margin-bottom: 30px; transform: translateZ(20px); transition: opacity 0.4s ease, transform 0.4s ease; } .input-group input { width: 100%; padding: 16px 20px; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; color: #fff; font-size: 16px; outline: none; transition: all 0.3s ease; } .input-group input:focus { border-color: var(--secondary); background: rgba(0, 0, 0, 0.6); box-shadow: 0 0 20px rgba(0, 240, 255, 0.1); } body.error-state .input-group input { border-color: rgba(255, 16, 16, 0.4); } body.success-state .input-group input { border-color: rgba(0, 255, 102, 0.4); } .input-group label { position: absolute; top: 50%; left: 20px; transform: translateY(-50%); color: rgba(255, 255, 255, 0.5); pointer-events: none; transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1); font-size: 16px; letter-spacing: 1px; } .input-group input:focus ~ label, .input-group input:valid ~ label { top: -12px; left: 15px; font-size: 12px; color: var(--bg-color); background: var(--secondary); padding: 2px 8px; border-radius: 4px; font-weight: bold; } body.error-state .input-group input:focus ~ label, body.error-state .input-group input:valid ~ label { background: var(--error); } body.success-state .input-group input:focus ~ label, body.success-state .input-group input:valid ~ label { background: var(--success); } /* Gooey Button */ .gooey-btn-container { filter: url('#goo'); position: relative; width: 100%; height: 65px; margin-top: 40px; transform: translateZ(25px); } .gooey-btn { width: 100%; height: 100%; background: linear-gradient(40deg, var(--primary), var(--tertiary)); border: none; border-radius: 12px; color: #fff; font-size: 18px; font-weight: 700; letter-spacing: 1px; cursor: pointer; position: relative; z-index: 2; transition: all 0.3s ease; text-shadow: 0 2px 4px rgba(0,0,0,0.3); } .gooey-btn:active { transform: scale(0.92); } .drop { position: absolute; background: var(--primary); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1; transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } /* Splatter effect logic */ .gooey-btn-container.splatter .drop:nth-child(2) { transform: translate(-150px, -50px) scale(1.4); background: var(--secondary); } .gooey-btn-container.splatter .drop:nth-child(3) { transform: translate(150px, -30px) scale(1.2); } .gooey-btn-container.splatter .drop:nth-child(4) { transform: translate(-120px, 50px) scale(1.5); background: var(--secondary); } .gooey-btn-container.splatter .drop:nth-child(5) { transform: translate(130px, 40px) scale(1.1); }
const cursorBlob = document.getElementById('cursor-blob'); const cardWrapper = document.getElementById('card-wrapper'); const loginCard = document.getElementById('login-card'); const inputs = document.querySelectorAll('.input-group input'); const inputGroups = document.querySelectorAll('.input-group'); const submitBtn = document.getElementById('submit-btn'); const btnContainer = document.getElementById('btn-container'); const statusMsg = document.getElementById('status-msg'); const cardTitle = document.getElementById('card-title'); // Fluid Cursor Tracking document.addEventListener('mousemove', (e) => { cursorBlob.style.left = `${e.clientX}px`; cursorBlob.style.top = `${e.clientY}px`; }); // 3D Parallax Hover cardWrapper.addEventListener('mousemove', (e) => { const rect = cardWrapper.getBoundingClientRect(); const x = e.clientX - rect.left - rect.width / 2; const y = e.clientY - rect.top - rect.height / 2; loginCard.style.transform = `rotateX(${-y / 20}deg) rotateY(${x / 20}deg)`; }); cardWrapper.addEventListener('mouseleave', () => { loginCard.style.transform = `rotateX(0deg) rotateY(0deg)`; }); // Hover Splatter Effect on Button btnContainer.addEventListener('mouseenter', () => btnContainer.classList.add('splatter')); btnContainer.addEventListener('mouseleave', () => btnContainer.classList.remove('splatter')); // Form Submission Logic submitBtn.addEventListener('click', () => { const username = document.getElementById('username').value; const password = document.getElementById('password').value; // Reset states document.body.className = ''; loginCard.classList.remove('shake'); statusMsg.classList.remove('show'); // Loading State Execution submitBtn.innerText = "AUTHENTICATING..."; submitBtn.style.pointerEvents = 'none'; cursorBlob.style.width = '300px'; cursorBlob.style.height = '300px'; // Simulate server delay setTimeout(() => { if (password.length === 0) { // ERROR STATE document.body.classList.add('error-state'); loginCard.classList.add('shake'); cardTitle.style.color = 'var(--error)'; statusMsg.innerText = "ACCESS DENIED: MISSING PASSCODE"; statusMsg.classList.add('show'); submitBtn.innerText = "RETRY"; submitBtn.style.pointerEvents = 'auto'; cursorBlob.style.background = 'var(--error)'; } else { // SUCCESS STATE document.body.classList.add('success-state'); cardTitle.style.color = 'var(--success)'; cardTitle.innerText = "GRANTED"; statusMsg.innerText = `SESSION INITIATED FOR ${username.toUpperCase()}`; statusMsg.classList.add('show'); // Fade out inputs for clean transition inputGroups.forEach(group => { group.style.opacity = '0'; group.style.transform = 'translateZ(0px) translateY(20px)'; group.style.pointerEvents = 'none'; }); submitBtn.innerText = "ENTER SYSTEM"; submitBtn.style.pointerEvents = 'auto'; btnContainer.classList.add('splatter'); cursorBlob.style.background = 'var(--success)'; } // Return cursor blob to normal ambient size setTimeout(() => { cursorBlob.style.width = '100px'; cursorBlob.style.height = '100px'; }, 400); }, 1200); }); // Focus & Keystroke interactions inputs.forEach(input => { input.addEventListener('input', () => { document.body.className = ''; // clear error/success on type cardTitle.style.color = '#fff'; statusMsg.classList.remove('show'); }); input.addEventListener('focus', () => { cursorBlob.style.width = '200px'; cursorBlob.style.height = '200px'; }); input.addEventListener('blur', () => { cursorBlob.style.width = '100px'; cursorBlob.style.height = '100px'; }); });
Live Preview