FRM001

Apple Liquid Glass Form

A stunning liquid glass form with seamless login/register transitions and interactive effects

UI Components
Chrome Only: This snippet is fully supported only in Google Chrome. Other browsers will display a simplified version.
Font Awesome Included: This snippet uses Font Awesome icons. The required stylesheet is automatically included at the top of the code block. If you are going to use this snippet in your project, add the stylesheet to your <head>.

Live Preview

Register

Already have an account?

Code

HTML
<!-- Font Awesome Icons; Make sure to add it in the <head> tag -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  
<!-- SVG Filter for Glass Distortion -->
<svg style="display: none">
  <filter id="glass-distortion">
    <feTurbulence type="turbulence" baseFrequency="0.008" numOctaves="2" result="noise" />
    <feDisplacementMap in="SourceGraphic" in2="noise" scale="77" />
  </filter>
</svg>

<div class="glass-form">
  <div class="glass-filter"></div>
  <div class="glass-overlay"></div>
  <div class="glass-specular"></div>
  <div class="glass-content">
    <div class="form-container login active">
      <h3>Login</h3>
      <form>
        <div class="form-group">
          <i class="fas fa-envelope"></i>
          <input type="email" placeholder="Email" required>
        </div>
        <div class="form-group">
          <i class="fas fa-lock"></i>
          <input type="password" placeholder="Password" required>
        </div>
        <button type="submit">Sign In</button>
      </form>
      <p class="form-switch">Don't have an account? <a href="#" class="switch-to-register">Register</a></p>
    </div>
    
    <div class="form-container register">
      <h3>Register</h3>
      <form>
        <div class="form-group">
          <i class="fas fa-user"></i>
          <input type="text" placeholder="Username" required>
        </div>
        <div class="form-group">
          <i class="fas fa-envelope"></i>
          <input type="email" placeholder="Email" required>
        </div>
        <div class="form-group">
          <i class="fas fa-lock"></i>
          <input type="password" placeholder="Password" required>
        </div>
        <div class="form-group">
          <i class="fas fa-lock"></i>
          <input type="password" placeholder="Confirm Password" required>
        </div>
        <button type="submit">Sign Up</button>
      </form>
      <p class="form-switch">Already have an account? <a href="#" class="switch-to-login">Login</a></p>
    </div>
  </div>
</div>
CSS
.glass-form {
  --bg-color: rgba(255, 255, 255, 0.25);
  --highlight: rgba(255, 255, 255, 0.75);
  --text: #ffffff;
  --input-bg: rgba(255, 255, 255, 0.1);
  --input-border: rgba(255, 255, 255, 0.2);
  --input-focus: rgba(255, 255, 255, 0.3);
  
  position: relative;
  width: 400px;
  min-height: 450px;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2);
}

.glass-filter,
.glass-overlay,
.glass-specular {
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.glass-filter {
  z-index: 1;
  backdrop-filter: blur(4px);
  filter: url(#glass-distortion) saturate(120%) brightness(1.15);
}

.glass-overlay {
  z-index: 2;
  background: var(--bg-color);
}

.glass-specular {
  z-index: 3;
  box-shadow: inset 1px 1px 1px var(--highlight);
}

.glass-content {
  position: relative;
  z-index: 4;
  padding: 30px;
  color: var(--text);
  height: 100%;
}

.form-container {
  display: none;
  opacity: 0;
  transform: translateX(20px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.form-container.active {
  display: block;
  opacity: 1;
  transform: translateX(0);
}

.form-container h3 {
  margin: 0 0 20px 0;
  font-size: 28px;
  font-weight: 600;
  text-align: center;
}

.form-group {
  position: relative;
  margin-bottom: 20px;
}

.form-group i {
  position: absolute;
  left: 15px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text);
  opacity: 0.8;
}

.form-group input {
  width: 100%;
  padding: 12px 15px 12px 45px;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: 10px;
  color: var(--text);
  font-size: 16px;
  transition: border-color 0.3s ease, background 0.3s ease;
}

.form-group input:focus {
  outline: none;
  background: var(--input-focus);
  border-color: var(--highlight);
}

.form-group input::placeholder {
  color: rgba(255, 255, 255, 0.6);
}

button[type="submit"] {
  width: 100%;
  padding: 12px;
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 10px;
  color: var(--text);
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  margin-top: 10px;
}

button[type="submit"]:hover {
  background: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.4);
}

.form-switch {
  text-align: center;
  margin-top: 20px;
  font-size: 14px;
  opacity: 0.8;
}

.form-switch a {
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
  opacity: 1;
}

.form-switch a:hover {
  text-decoration: underline;
}

/* Dark mode styles */
@media (prefers-color-scheme: dark) {
  .glass-form {
    --bg-color: rgba(0, 0, 0, 0.25);
    --highlight: rgba(255, 255, 255, 0.15);
    --input-bg: rgba(0, 0, 0, 0.2);
    --input-border: rgba(255, 255, 255, 0.1);
    --input-focus: rgba(0, 0, 0, 0.3);
  }
}
JavaScript
document.addEventListener('DOMContentLoaded', function() {
  // Get all glass form elements
  const glassElements = document.querySelectorAll('.glass-form');
  const switchToRegister = document.querySelector('.switch-to-register');
  const switchToLogin = document.querySelector('.switch-to-login');
  const loginForm = document.querySelector('.form-container.login');
  const registerForm = document.querySelector('.form-container.register');
  
  // Add mousemove effect for each glass element
  glassElements.forEach(element => {
    element.addEventListener('mousemove', handleMouseMove);
    element.addEventListener('mouseleave', handleMouseLeave);
  });
  
  // Form switch event listeners
  if (switchToRegister && switchToLogin && loginForm && registerForm) {
    switchToRegister.addEventListener('click', (e) => {
      e.preventDefault();
      loginForm.style.opacity = '0';
      loginForm.style.transform = 'translateX(-20px)';
      
      setTimeout(() => {
        loginForm.classList.remove('active');
        registerForm.classList.add('active');
        
        setTimeout(() => {
          registerForm.style.opacity = '1';
          registerForm.style.transform = 'translateX(0)';
        }, 50);
      }, 300);
    });
    
    switchToLogin.addEventListener('click', (e) => {
      e.preventDefault();
      registerForm.style.opacity = '0';
      registerForm.style.transform = 'translateX(-20px)';
      
      setTimeout(() => {
        registerForm.classList.remove('active');
        loginForm.classList.add('active');
        
        setTimeout(() => {
          loginForm.style.opacity = '1';
          loginForm.style.transform = 'translateX(0)';
        }, 50);
      }, 300);
    });
  }
  
  // Handle mouse movement over glass elements
  function handleMouseMove(e) {
    const rect = this.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    
    // Add highlight effect
    const specular = this.querySelector('.glass-specular');
    if (specular) {
      specular.style.background = `radial-gradient(
        circle at ${x}px ${y}px,
        rgba(255,255,255,0.15) 0%,
        rgba(255,255,255,0.05) 30%,
        rgba(255,255,255,0) 60%
      )`;
    }
  }
  
  // Reset effects when mouse leaves
  function handleMouseLeave() {
    const filter = document.querySelector('#glass-distortion feDisplacementMap');
    if (filter) {
      filter.setAttribute('scale', '77');
    }
    
    const specular = this.querySelector('.glass-specular');
    if (specular) {
      specular.style.background = 'none';
    }
  }
  
  // Form validation and submission handling
  const forms = document.querySelectorAll('.glass-form form');
  forms.forEach(form => {
    const inputs = form.querySelectorAll('input');
    
    // Add input validation styles
    inputs.forEach(input => {
      input.addEventListener('invalid', function() {
        this.classList.add('error');
      });
      
      input.addEventListener('input', function() {
        if (this.validity.valid) {
          this.classList.remove('error');
        }
      });
    });
    
    // Handle form submission
    form.addEventListener('submit', (e) => {
      e.preventDefault();
      
      // Get form data
      const formData = new FormData(form);
      const data = Object.fromEntries(formData.entries());
      
      // Simple validation for password match in register form
      if (form.closest('.register')) {
        const password = data.password;
        const confirmPassword = data['confirm-password'];
        
        if (password !== confirmPassword) {
          alert('Passwords do not match!');
          return;
        }
      }
      
      // Here you would typically send the data to your server
      console.log('Form submitted:', data);
      
      // Show success state
      const submitBtn = form.querySelector('button[type="submit"]');
      const originalText = submitBtn.textContent;
      submitBtn.textContent = 'Success!';
      submitBtn.classList.add('success');
      
      setTimeout(() => {
        submitBtn.textContent = originalText;
        submitBtn.classList.remove('success');
        form.reset();
      }, 2000);
    });
  });

  // Initialize code blocks for the snippet preview
  initializeCodeBlocks();
});

// Function to initialize code blocks
function initializeCodeBlocks() {
  const htmlCode = document.getElementById('html-code');
  const cssCode = document.getElementById('css-code');
  const jsCode = document.getElementById('js-code');

  // Add copy functionality to code blocks
  document.querySelectorAll('.copy-button').forEach(button => {
    button.addEventListener('click', () => {
      const targetId = button.getAttribute('data-target');
      const codeBlock = document.getElementById(targetId);
      if (codeBlock) {
        navigator.clipboard.writeText(codeBlock.textContent).then(() => {
          button.innerHTML = ' Copied!';
          setTimeout(() => {
            button.innerHTML = ' Copy';
          }, 2000);
        });
      }
    });
  });
}