More Forms Snippets
Glassmorphism Login Form HTML CSS JS — Frosted Glass
Glassmorphism Login Form · Forms · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Glassmorphism Login Form — How to Build a Frosted Glass Login UI with CSS backdrop-filter, Animated Blobs, and 3D Flip Card

Glassmorphism is the UI trend that gives elements the appearance of frosted glass — a translucent surface with blurred content visible behind it. It became the defining aesthetic of macOS Big Sur and has since spread across web dashboards, authentication screens, and marketing pages. Achieving the effect correctly requires three specific CSS properties working in concert, plus a carefully designed background scene to blur.
This snippet builds a complete glassmorphism login form with animated background blobs, real-time form validation, a password strength-aware eye toggle, social login buttons, and a 3D card flip animation that reveals a success state on submit.
The Glassmorphism Effect
Three CSS properties produce the frosted glass appearance:
`backdrop-filter: blur(16px)` blurs all content rendered behind the element. This is the core glassmorphism technique. The blur radius (16px here) controls how frosted the glass looks — higher values are more opaque-feeling, lower values more transparent.
`background: rgba(255, 255, 255, 0.12)` applies a semi-transparent white tint over the blurred background. Without this, the element would be invisible. The alpha value (0.12) controls transparency — lower = more see-through, higher = more opaque.
`border: 1px solid rgba(255, 255, 255, 0.25)` adds a bright edge that simulates the light catching the glass edge. This border is what makes glassmorphism look three-dimensional rather than flat.
Critically, these three properties only produce the intended effect when there is rich, colorful content behind the element to blur. That is why glassmorphism UIs always pair the glass card with a vibrant gradient background or animated elements.
Animated Background Blobs
The animated color blobs behind the login card are <div class="blob"> elements positioned with position: absolute in a full-screen scene container. Each blob uses a CSS @keyframes animation that morphs its border-radius between different asymmetric values and translates it along a looping path.
The blob shapes use border-radius values like 60% 40% 30% 70% / 60% 30% 70% 40% — the slash syntax sets per-corner radii independently for horizontal and vertical radii, producing organic blob shapes rather than circles or pills. The animation uses 8-second and 12-second durations with alternate direction to create non-repeating blob movements that never feel mechanical.
Form Validation
Validation fires on blur (when the user leaves a field) and on submit. For the email field: /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) — a minimal but effective email regex that checks for at-sign and dot without complex backtracking. For the password field: value.length >= 8 — a minimum length check only, appropriate for a login form (password strength is for registration, not login).
Errors display as red text in a <span class="field-error"> element beneath each field. On error: the field wrapper gets a has-error class (red border and background tint), the error span becomes visible, and the field shakes via a CSS keyframe animation (translateX oscillating ±4px, 300ms). On correction: the has-error class is removed and the error span clears.
Password Eye Toggle
The eye button toggles passInput.type between password and text. The icon swaps between two SVG paths: the open eye (circle with surrounding arc) and the eye-off (same paths with a diagonal slash line). SVG path data is stored in two constants (SVG_EYE, SVG_EYE_OFF) and swapped via eyeIcon.innerHTML. This avoids external icon fonts and keeps the toggle entirely self-contained.
3D Card Flip on Success
On successful form submission, the login card performs a 3D flip animation to reveal a success state. This uses transform-style: preserve-3d on the card container, with the login panel at rotateY(0deg) (front face) and the success panel at rotateY(180deg) (back face, visible only when flipped). Both panels have backface-visibility: hidden — each becomes invisible when rotated more than 90° away from the viewer.
The flip is triggered by adding a flipped class to the card element: .card.flipped { transform: rotateY(180deg); } with transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1). The transition produces a smooth, physics-feel rotation. The CSS perspective: 1000px on the parent scene element creates the 3D depth that makes the rotation look three-dimensional rather than flat.
Loading State During Submission
The submit button has three states: idle (Sign In), loading (spinner + Signing in…), and success (handled by the flip). The loading state is triggered by calling setLoading(true) — which adds loading class, disables the button, and sets aria-busy="true". A CSS keyframe rotates a spinner SVG. setTimeout simulates the API response delay before triggering the success flip. In production, replace the timeout with your actual authentication API call.
Social Login Buttons
Google, GitHub, and email buttons are cosmetic in the demo — they fire click events that in production would redirect to OAuth provider URLs or trigger window.location.href redirects. Each button has the provider's brand icon as an inline SVG and a text label. The divider between social and email login uses the classic "OR" text with CSS borders: ::before and ::after pseudo-elements with flex: 1; height: 1px; background: rgba(255,255,255,0.2).
Build with AI
Build, Understand, Optimize, and Extend It With AI
Rather than tracing the flip and validation logic yourself, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain precisely how the card-front and card-success panels use transform-style: preserve-3d with backface-visibility: hidden to stay a single flat card until the flipped class rotates the whole thing 180 degrees on rotateY, and why the shake animation needs the void card.offsetWidth reflow trick to restart reliably on repeated failed submits. It's also worth asking it to optimize the form, for example whether the three floating blob animations are worth pausing when the tab is backgrounded, or whether the email regex is too permissive for production. For extending it, ask for a real fetch-based auth call replacing the setTimeout, a "remember me" checkbox, or a password-strength meter reused from the sign-up variant. Treat the code less like a finished artifact and more like a starting point for a conversation.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build a glassmorphism login form in plain HTML, CSS, and JavaScript using CSS 3D transforms for a flip-on-success card, with no external libraries.
Requirements:
- An animated background of at least three large blurred circular blobs, each positioned absolutely and animated independently with CSS keyframes moving translate and scale values on staggered, differing durations so their motion never synchronizes.
- A login card using backdrop-filter: blur with a semi-transparent white background and a translucent border for a genuine frosted-glass look, including the -webkit-backdrop-filter prefix.
- Two stacked panels inside the card, a front login panel and a back success panel, both with backface-visibility: hidden, inside a card container with transform-style: preserve-3d; toggling a single flipped class on the card must rotate it 180 degrees on the Y axis to reveal the success panel, driven purely by a CSS transition, with a perspective value set on the parent so the rotation reads as genuinely three-dimensional.
- Email and password fields using the floating-label pattern purely in CSS, where the label sits over the placeholder text and animates to a small label above the field when the input is focused or has a value, using the :not(:placeholder-shown) and :focus pseudo-classes with no JavaScript needed for the label motion.
- A password visibility toggle button that switches the input's type attribute between password and text and swaps between two inline SVG icon states.
- Client-side validation on submit that checks for a valid email pattern and a minimum password length, applying an error class and message per invalid field, and shaking the whole card via a CSS keyframe animation when validation fails, restarting the animation correctly even on consecutive failures.
- A loading state on submit that disables the button, swaps its label for a spinner, and after a simulated delay flips the card to the success panel.Step by step
How to Use
- 1See the glassmorphism cardThe login card renders over three animated color blobs. The frosted glass effect is visible — the blobs show through the card as blurred color.
- 2Try form validationClick in the email field and leave it empty, then tab out. The field turns red with an error message and a shake animation. Enter an invalid email for the same effect.
- 3Toggle the passwordClick the eye icon in the password field to reveal or hide the password text. The icon swaps between the open and closed eye SVG.
- 4Submit the formEnter any email and a password of 8+ characters, then click Sign In. The button shows a loading spinner, then the card flips to reveal the success state.
- 5Connect to your auth backendIn the submit handler, replace the setTimeout simulation with a fetch() POST to your login endpoint. On success: call flipToSuccess(). On failure: set a general error message and re-enable the submit button.
- 6Adjust the glass effectModify backdrop-filter blur amount (16px), background alpha (0.12), and border alpha (0.25) in the CSS to tune the frosted glass appearance. Higher blur = more frosted, higher alpha = more opaque.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
backdrop-filter: blur() blurs the content rendered behind the element. On a plain solid-color background, blurring a flat color produces the same flat color — there is nothing to blur. Glassmorphism requires rich, colorful, or varied content behind the card: a gradient, a photo, the animated color blobs in this snippet, or other UI elements showing through. The effect is only visible when there are visible color variations behind the card.
The card container has transform-style: preserve-3d and transition: transform 0.7s. The front panel has no transform. The back panel has transform: rotateY(180deg) applied permanently — it starts already flipped. Both panels have backface-visibility: hidden, which makes each panel invisible when rotated more than 90° from the viewer. Adding class="flipped" to the card applies transform: rotateY(180deg), bringing the back face forward and hiding the front face. The parent has perspective: 1000px for the 3D depth effect.
In the form submit handler, replace the setTimeout with: try { const res = await fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }) }); if (res.ok) { flipToSuccess(); } else { const err = await res.json(); showError(err.message); } } catch { showError("Network error. Try again."); }. The flipToSuccess() function adds the .flipped class to the card element. The showError() function sets a general error message and re-enables the submit button.
Add a strength meter div below the password field. In the password input's input event handler, run four regex tests: minimum 8 chars, uppercase letter, digit, special character. Score 0–4 based on how many pass. Map the score to a width percentage and color: red (0–1), orange (2), yellow (3), green (4). Update the strength bar width and label text on each keystroke. This is the same technique used in the password strength snippet.
Each blob has a CSS animation with a duration and keyframe path. Increase the animation duration (e.g., from 8s to 16s) for slower, more subtle movement. Decrease for faster. Change the translateX and translateY values in the @keyframes to control the movement range. Change border-radius values in the keyframes for different blob shape morphing. Each blob has its own animation-delay so they move independently — stagger the delays for less synchronization.
Yes. Click JSX for React, Vue for a Vue 3 SFC, Angular for a standalone component, or Tailwind for utility classes — backdrop-blur, bg-white/15, and border-white/30 map directly to Tailwind. Wire the form submit to your auth API and keep input values in controlled state.