Futuristic Vault Login with Fingerprint Scan using HTML CSS JS

Faraz

By Faraz -

Learn to create a futuristic vault login system with a dummy fingerprint scan and secure access portal using HTML, CSS, and JavaScript step by step.


futuristic-vault-login-fingerprint-scan-and-access-portal.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

Security is a key part of web design today. Many apps use biometrics like fingerprint or face recognition for real authentication. But in this tutorial, we will not create a real biometric system. Instead, we will design a dummy fingerprint scanner – a futuristic UI simulation of a vault login system using only HTML, CSS, and JavaScript.

Note: This fingerprint scanner is only a dummy for design purposes. It does not provide real biometric security.

By the end of this guide, you’ll have a sci-fi-inspired login portal that looks like a vault access screen with a glowing fingerprint effect and access granted animation.

Prerequisites

Before you start, make sure you have:

  • Basic knowledge of HTML, CSS, and JavaScript
  • A code editor (VS Code, Sublime Text, Atom, or Notepad++)
  • A browser (Chrome, Edge, or Firefox) to test the project
  • Basic idea of CSS animations and styling

Source Code

Step 1 (HTML Code):

To get started, we first need to create a basic HTML file. In this file, we will include the main structure for our vault login. Let's break down the HTML code:

1. Document Setup

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  • <!DOCTYPE html> → Defines HTML5 document.
  • lang="en" → Page language is English.
  • meta charset="UTF-8" → Supports all characters (English + special).
  • X-UA-Compatible → Ensures compatibility with old Internet Explorer.
  • viewport → Makes site mobile responsive.

2. External Fonts & Icons

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  • Loads Google Fonts (Inter).
  • Loads Font Awesome icons (lock, user-shield, cog, etc.).

3. Page Title & CSS

<title>Futuristic Vault Login - Fingerprint Scan & Access Portal</title>
<link rel="stylesheet" href="styles.css">
  • title → Shown on browser tab & SEO.
  • styles.css → External stylesheet for design.

4. Preloader (Vault + Fingerprint UI)

<div class="preloader">
  <div class="preloader-content">

A preloader screen that shows vault + fingerprint scanner before content loads.

a) Vault Door Assembly

<div class="vault-perspective-container">
  <div class="vault-door-assembly">
      <div class="vault-frame">
          <div class="vault-interior"></div>
          <div class="bolt-receptacle top"></div>
          <div class="bolt-receptacle right"></div>
          <div class="bolt-receptacle bottom"></div>
          <div class="bolt-receptacle left"></div>
      </div>
      <div class="vault-door">
          <div class="hinge top"></div>
          <div class="hinge bottom"></div>
  • Creates a 3D vault door effect with bolts, hinges, and frame.
  • Will later animate open when access is granted.

b) Vault Dial / Handle

<div class="vault-dial-container">
  <div class="vault-dial">
      <div class="vault-handle">
          <div class="handle-spoke"></div>
          <div class="handle-spoke"></div>
          <div class="handle-spoke"></div>
          <div class="handle-hub"></div>
      </div>
  </div>
</div>
  • Creates a vault handle/dial (like a bank safe).

5. Security Panel (Fingerprint Scanner)

<div class="security-panel">
    <div class="panel-header">
        <span>BIOMETRIC AUTHENTICATION</span>
    </div>
  • Side panel with Biometric Authentication title.

a) Fingerprint Scanner SVG

<div class="fingerprint-scanner">
    <svg class="fingerprint-svg" viewBox="0 0 24 24">
        <g class="fingerprint-lines">
            <path d="M17.81 4.47c..."/>
        </g>
        <g class="success-mark">
            <path d="M6 12 l4 4 l8 -8" />
        </g>
    </svg>
    <div class="scan-line"></div>
</div>
  • A fingerprint icon (SVG paths).
  • <g class="success-mark"> → Checkmark appears when scan succeeds.
  • .scan-line → Animated scanning line effect.

b) Status Text

<div class="status-display">
    <span class="status-text">Awaiting Scan</span>
</div>
  • Shows text like Awaiting Scan → Scanning → Access Granted.

6. Vault Instructions

<div class="vault-instructions">
  <p>Press and Hold to Scan</p>
</div>
  • Instructions for the user.

7. Main Website Content

<div class="main-content">
  <div class="content-container">
  • This is the real content that shows after access is granted.

a) Welcome Animation

<div class="welcome-animation">
  <i class="fas fa-lock-open success-icon"></i>
  <h1>ACCESS GRANTED</h1>
  <p>Secure vault system disengaged</p>
</div>
  • Lock icon + “ACCESS GRANTED” animation when fingerprint scan passes.

b) Content Card with Features

<div class="content-card">
  <h2>Premium Secure Portal</h2>
  <p>Your sensitive content is now accessible...</p>
  <div class="features-grid">
      <div class="feature">
          <i class="fas fa-user-shield"></i>
          <h3>Security</h3>
          <p>Manage your protection settings</p>
      </div>
      ...
  </div>
</div>
  • Features Grid → 4 features (Security, Documents, Settings, Logout).

8. External JS Libraries

<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.7.77/Tone.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
  • Tone.js → Sound effects (e.g., scan beep, vault unlock).
  • GSAP → Animations (vault door opening, scan line movement, etc.).

9. Custom JavaScript

<script src="script.js"></script>
  • Controls the fingerprint scan, animations, and access granted logic.

Step 2 (CSS Code):

Once the basic HTML structure of the vault login is in place, the next step is to add styling to the page using CSS. Let's break down the CSS code:

1. Global Reset

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
  • Removes default browser margins and paddings.
  • Uses box-sizing: border-box so padding & border are included in element width/height.

2. Body Styling

body {
  font-family: 'Inter', sans-serif;
  overflow-x: hidden;
  background-color: #f8fafc;
  color: #334155;
}
  • Sets font to Inter (fallback sans-serif).
  • Prevents horizontal scrolling (overflow-x: hidden).
  • Light gray background with dark gray text.

3. Preloader Screen

.preloader { ... }
.preloader-content { ... }
  • Full-screen loading screen before vault unlock.
  • Centered flexbox layout with smooth transitions.
  • z-index: 9999 ensures it stays on top.

4. Security Panel

.security-panel { ... }
.panel-header { ... }
.scanner-area { ... }
.status-display { ... }
  • Small card showing the fingerprint scanner + status.
  • Dark gradient with shadow for 3D effect.
  • .status-display shows “Success” or “Failed” messages.
  • .scanning.fail ~ .status-display → turns text red on failed scan.

5. Fingerprint Scanner

.fingerprint-scanner { ... }
.fingerprint-lines { ... }
.scan-line { ... }
.success-mark { ... }
  • Scanner is interactive (cursor: pointer).
  • Uses SVG for fingerprint lines.
  • .scan-line → blue glowing horizontal line that animates scanning.
  • .success-mark → green checkmark after successful scan.
  • .scanning.fail → fingerprint turns red & shakes (error).

6. Vault 3D Door

.vault-perspective-container { ... }
.vault-door-assembly { ... }
.vault-frame { ... }
.vault-interior { ... }
  • 3D vault door effect using perspective & transform-style: preserve-3d.
  • Circular metallic frame + interior gradient.
  • Bolt receptacles around edges (top, right, bottom, left).
  • .vault-door → rotates open when unlocked (.is-unlocked).
  • Uses pseudo-elements (::before, ::after) for the front/back face of the door.

7. Vault Hinges & Dial

.hinge { ... }
.vault-dial-container { ... }
.vault-dial { ... }
.vault-handle { ... }
.handle-spoke { ... }
.handle-hub { ... }
  • Hinges on the left side to make the door realistic.
  • Center dial with rotating handle (3 spokes + hub) like a safe.
  • .vault-handle.active → glowing pulse animation.

8. Main Content (After Unlock)

.main-content { ... }
.content-container { ... }
.welcome-animation { ... }
.content-card { ... }
.features-grid { ... }
  • Hidden initially (opacity: 0; transform: scale(0.95)).
  • Fades in (.visible) after unlocking.
  • Cards and features grid with hover effects.
  • Clean, modern design with subtle shadows and rounded corners.

9.Animations

@keyframes pulse-handle { ... }
@keyframes shake { ... }
  • pulse-handle → glowing golden handle effect.
  • shake → fingerprint shakes left-right when scan fails.
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: 'Inter', sans-serif;
  overflow-x: hidden;
  background-color: #f8fafc;
  color: #334155;
}

.preloader {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #f8fafc;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 15px;
  z-index: 9999;
  transition: background-color 1s ease-out, opacity 0.5s ease-in-out;
  overflow: hidden;
}

.preloader-content {
  width: 100%;
  max-width: 600px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 1.5s ease-in, opacity 1s ease-in,
    justify-content 0.8s ease-in-out;
}

/* Security Panel */
.security-panel {
  width: 200px;
  background: linear-gradient(145deg, #374151, #1f2937);
  border-radius: 8px;
  border: 1px solid #cbd5e1;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  padding: 15px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
}

.panel-header {
  font-size: 9px;
  font-weight: 600;
  color: #9ca3af;
  letter-spacing: 1px;
}

.scanner-area {
  width: 100px;
  height: 100px;
  background: #111827;
  border-radius: 8px;
  padding: 10px;
  box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.5);
}

.status-display {
  width: 100%;
  background: #111827;
  color: #34d399;
  font-size: 14px;
  text-align: center;
  padding: 8px;
  border-radius: 4px;
  box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.5);
  transition: color 0.3s;
}

.scanning.fail ~ .status-display {
  color: #ef4444;
}

.vault-instructions {
  font-size: 10px;
  font-weight: 500;
  color: #111827;
  letter-spacing: 0.5px;
}

/* Fingerprint Scanner */
.fingerprint-scanner {
  width: 100%;
  height: 100%;
  cursor: pointer;
  position: relative;
  border-radius: 4px;
  overflow: hidden;
}

.fingerprint-svg {
  width: 100%;
  height: 100%;
}

.fingerprint-lines {
  fill: #2563eb;
  clip-path: polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%);
}

.scan-line {
  position: absolute;
  top: 0;
  left: -10%;
  width: 120%;
  height: 2px;
  background: #2563eb;
  box-shadow: 0 0 10px #2563eb;
  opacity: 0;
}

.success-mark {
  fill: none;
  stroke: #10b981;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
}

.scanning.fail .fingerprint-lines {
  fill: #ef4444;
  animation: shake 0.5s;
}

/* Vault Styles */
.vault-perspective-container {
  perspective: 1000px;
  display: none;
}

.vault-door-assembly {
  position: relative;
  width: 220px;
  height: 220px;
  transform-style: preserve-3d;
}

.vault-frame {
  width: 100%;
  height: 100%;
  background: #374151;
  border-radius: 50%;
  border: 1px solid #4b5563;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3), inset 0 0 10px rgba(0, 0, 0, 0.4);
  position: absolute;
}

.vault-interior {
  position: absolute;
  top: 10px;
  left: 10px;
  right: 10px;
  bottom: 10px;
  background: radial-gradient(circle, #222 0%, #000 100%);
  border-radius: 50%;
  box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.8);
}

.bolt-receptacle {
  position: absolute;
  background: #cbd5e1;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.2);
}

.bolt-receptacle.top {
  top: 5px;
  left: 50%;
  transform: translateX(-50%);
  width: 30px;
  height: 10px;
  border-radius: 5px;
}

.bolt-receptacle.right {
  right: 5px;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 30px;
  border-radius: 5px;
}

.bolt-receptacle.bottom {
  bottom: 5px;
  left: 50%;
  transform: translateX(-50%);
  width: 30px;
  height: 10px;
  border-radius: 5px;
}

.bolt-receptacle.left {
  left: 5px;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 30px;
  border-radius: 5px;
}

.vault-door {
  position: absolute;
  width: 100%;
  height: 100%;
  background: radial-gradient(circle, #4b5563 0%, #1f2937 100%);
  border-radius: 50%;
  transform-origin: left;
  transform-style: preserve-3d;
  box-shadow: 5px 0 15px rgba(0, 0, 0, 0.3);
  transition: transform 1.5s cubic-bezier(0.65, 0, 0.35, 1);
}

.vault-door::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle, #4b5563 0%, #1f2937 100%);
  backface-visibility: hidden;
}

.vault-door::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #111827;
  transform: rotateY(180deg);
  backface-visibility: hidden;
}

.vault-door.is-unlocked {
  transform: rotateY(-120deg);
  box-shadow: 25px 0 50px rgba(0, 0, 0, 0.2);
}

.hinge {
  position: absolute;
  width: 18px;
  height: 40px;
  background: #374151;
  border-radius: 4px 0 0 4px;
  border: 1px solid #4b5563;
  box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
}

.hinge.top {
  top: 50px;
}

.hinge.bottom {
  bottom: 50px;
}

.vault-dial-container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 150px;
  height: 150px;
  background: radial-gradient(circle, #1f2937, #111827);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.1);
}

.vault-dial {
  width: 120px;
  height: 120px;
  background: linear-gradient(145deg, #4b5563, #1f2937);
  border-radius: 50%;
  border: 1px solid #6b7280;
  display: flex;
  justify-content: center;
  align-items: center;
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
  position: relative;
}

.vault-handle {
  width: 100%;
  height: 100%;
  position: absolute;
  cursor: pointer;
  transition: transform 0.5s ease-in-out;
}

.vault-handle.active {
  animation: pulse-handle 1.5s infinite;
}

.handle-spoke {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 60px;
  height: 10px;
  background: linear-gradient(to right, #fcd34d, #fbbf24);
  border-radius: 5px;
  border: 1px solid #f59e0b;
  transform-origin: 5px 5px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

.handle-spoke:nth-child(1) {
  transform: translate(-5px, -5px) rotate(0deg);
}

.handle-spoke:nth-child(2) {
  transform: translate(-5px, -5px) rotate(120deg);
}

.handle-spoke:nth-child(3) {
  transform: translate(-5px, -5px) rotate(240deg);
}

.handle-hub {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 25px;
  height: 25px;
  background: radial-gradient(circle, #fbbf24, #f59e0b);
  border-radius: 50%;
  border: 1px solid #d97706;
  transform: translate(-50%, -50%);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}

/* Main content */
.main-content {
  text-align: center;
  padding: 30px;
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 0.8s ease-out 0.5s, transform 0.8s ease-out 0.5s;
  max-width: 800px;
  margin: 0 auto;
}

.main-content.visible {
  opacity: 1;
  transform: scale(1);
}

.content-container {
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.welcome-animation {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 20px;
}

.success-icon {
  font-size: 48px;
  color: #10b981;
  margin-bottom: 10px;
}

.welcome-animation h1 {
  font-size: 28px;
  font-weight: 600;
  color: #1e293b;
}

.welcome-animation p {
  color: #64748b;
  font-size: 16px;
}

.content-card {
  background: white;
  border-radius: 12px;
  padding: 30px;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  text-align: center;
  border: 1px solid #e2e8f0;
}

.content-card h2 {
  font-size: 24px;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 15px;
}

.content-card p {
  color: #64748b;
  font-size: 16px;
  margin-bottom: 30px;
}

.features-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.feature {
  background: #f8fafc;
  border-radius: 8px;
  padding: 20px;
  transition: all 0.3s ease;
  border: 1px solid #e2e8f0;
}

.feature:hover {
  transform: translateY(-3px);
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  border-color: #cbd5e1;
}

.feature i {
  font-size: 24px;
  color: #3b82f6;
  margin-bottom: 15px;
}

.feature h3 {
  font-size: 18px;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 8px;
}

.feature p {
  color: #64748b;
  font-size: 14px;
  margin-bottom: 0;
}

/* Animations */
@keyframes pulse-handle {
  0% {
    filter: brightness(1);
  }

  50% {
    filter: brightness(1.2) drop-shadow(0 0 8px #fcd34d);
  }

  100% {
    filter: brightness(1);
  }
}

@keyframes shake {
  10%,
  90% {
    transform: translate3d(-1px, 0, 0);
  }

  20%,
  80% {
    transform: translate3d(2px, 0, 0);
  }

  30%,
  50%,
  70% {
    transform: translate3d(-4px, 0, 0);
  }

  40%,
  60% {
    transform: translate3d(4px, 0, 0);
  }
} 

Step 3 (JavaScript Code):

Finally, we need to create a function in JavaScript. Let's break down the JavaScript code:

1. Wait until DOM is Ready

document.addEventListener('DOMContentLoaded', () => {
  • Ensures the code runs only after HTML is fully loaded.
  • All DOM elements are available to query safely.

2. Grab Important DOM Elements

const preloader = document.querySelector('.preloader');
const vaultDoor = document.querySelector('.vault-door');
const scanner = document.querySelector('.fingerprint-scanner');
const handle = document.querySelector('.vault-handle');
const mainContent = document.querySelector('.main-content');
...
  • Selects UI parts:
    • Preloader screen
    • Vault door & handle
    • Fingerprint scanner
    • Status text
    • Success mark (checkmark)
    • Main content (hidden until unlock)

3. State Variables

let scanComplete = false;
let isUnlocked = false;
let scanTimeline;
  • scanComplete → becomes true once scanning succeeds.
  • isUnlocked → becomes true once the vault is open.
  • scanTimeline → GSAP animation reference (so it can be stopped).

4. Audio Synths (Dummy Sound Effects)

Using Tone.js to create futuristic sounds:

const successSynth = new Tone.PolySynth(...);   // Success chime
const boltSynth = new Tone.MetalSynth(...);     // Lock bolt sound
const doorSynth = new Tone.NoiseSynth(...);     // Door opening sound
const scannerSynth = new Tone.AMSynth(...);     // Scanning sound
const failSynth = new Tone.Synth(...);          // Failure beep
  • Each plays different sounds during interactions.

5. Event Listeners

scanner.addEventListener('mousedown', startScan);
scanner.addEventListener('mouseup', cancelScan);
handle.addEventListener('click', handleHandleTurn);
  • Fingerprint scanner → starts scanning on press, cancels on release.
  • Vault handle → clickable after scan success to open vault.

6. Start Scan

function startScan(e) {
  if (scanComplete || isUnlocked) return;

  scannerSynth.triggerAttack('C2'); // Start scan sound
  statusText.textContent = 'Scanning...';
  scanner.classList.add('scanning');

  // GSAP timeline: animate scan line + fingerprint highlight
  scanTimeline = gsap.timeline({ onComplete: () => { scanSuccess(); } });

  scanTimeline
    .to(scanLine, { opacity: 1, duration: 0.2 })
    .set(fingerprintLines, { filter: 'brightness(1.5)' })
    .to(fingerprintLines, { clipPath: 'polygon(...)', duration: 2.0 })
    .to(scanLine, { y: '80px', duration: 2.0 }, '<');
}
  • Plays a scanning sound.
  • Animates fingerprint glowing + scan line moving down.
  • If animation completes → calls scanSuccess().

7. Cancel Scan

function cancelScan() {
  if (scanTimeline && scanTimeline.isActive()) {
    scannerSynth.triggerRelease();  // Stop scan sound
    failSynth.triggerAttackRelease('A2', '0.1'); // Error beep

    scanTimeline.kill(); // Stop animation
    gsap.to([fingerprintLines, scanLine], { clearProps: 'all', duration: 0.3 });

    scanner.classList.add('fail');
    statusText.textContent = 'Scan Failed';

    // Reset to idle after 1s
    setTimeout(() => {
      scanner.classList.remove('scanning');
      scanner.classList.remove('fail');
      statusText.textContent = 'Awaiting Scan';
    }, 1000);
  }
}
  • If the user releases the finger too early, the scan fails.
  • Plays failure beep, resets UI, shows "Scan Failed".

8. Successful Scan

function scanSuccess() {
  scanComplete = true;
  scanner.style.cursor = 'default';
  scannerSynth.triggerRelease(); // Stop scanning sound

  const tl = gsap.timeline({ onComplete: activateHandle });

  tl.to(fingerprintLines, { filter: 'brightness(1)' })
    .to(scanLine, { opacity: 0 })
    .set(statusText, { textContent: 'Verified' })
    .fromTo(successMark, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1 })
    .to(securityPanel, { opacity: 0, scale: 0.9, onComplete: () => { securityPanel.style.display = 'none'; } })
    .fromTo(vaultContainer, { display: 'none', opacity: 0 }, { display: 'block', opacity: 1 });
}
  • Marks scan as complete.
  • Shows "Verified" + green checkmark.
  • Hides scanner panel → reveals vault door.
  • Calls activateHandle() afterward.

9. Activate Handle

function activateHandle() {
  successSynth.triggerAttackRelease(['C4', 'E4', 'G4'], '0.5'); // Success sound
  instructions.textContent = 'Click Handle to Open';
  handle.classList.add('active'); // Glow effect
}
  • Plays success chime.
  • Update instructions.
  • Makes the handle glow (ready to be clicked).

10. Handle Turn

function handleHandleTurn() {
  if (!scanComplete || isUnlocked) return;
  isUnlocked = true;

  const tl = gsap.timeline();
  tl.to(handle, { rotation: 120, duration: 0.5 }) // Rotate handle
    .call(() => boltSynth.triggerAttackRelease('C2', '0.2')) // Lock bolt sound
    .call(openDoor); // Then open vault
}
  • Rotates the handle animation.
  • Plays metallic bolt unlocking sound.
  • Calls openDoor().

11. Open Vault Door

function openDoor() {
  doorSynth.triggerAttack(); // Door opening sound

  vaultDoor.classList.add('is-unlocked'); // Rotate open

  setTimeout(() => {
    mainContent.style.display = 'block';
    const revealTl = gsap.timeline({
      onComplete: () => { setTimeout(() => preloader.remove(), 500); },
    });

    revealTl
      .to(preloaderContent, { scale: 15, duration: 1.0 }) // Explosion effect
      .to(mainContent, { opacity: 1, duration: 1.0 })    // Show content
      .to(preloader, { opacity: 0, duration: 0.5 }, '<');
  }, 600);
}
  • Vault door rotates open.
  • Plays whoosh door sound.
  • Expands preloader content (cool zoom-out effect).
  • Reveals hidden main page content.
  • Removes preloader entirely.
document.addEventListener('DOMContentLoaded', () => {
  // --- DOM Elements ---
  const preloader = document.querySelector('.preloader');
  const preloaderContent = document.querySelector('.preloader-content');
  const vaultContainer = document.querySelector('.vault-perspective-container');
  const vaultDoor = document.querySelector('.vault-door');
  const mainContent = document.querySelector('.main-content');
  const handle = document.querySelector('.vault-handle');
  const scanner = document.querySelector('.fingerprint-scanner');
  const securityPanel = document.querySelector('.security-panel');
  const statusText = document.querySelector('.status-text');
  const instructions = document.querySelector('.vault-instructions p');
  const fingerprintLines = document.querySelector('.fingerprint-lines');
  const scanLine = document.querySelector('.scan-line');
  const successMark = document.querySelector('.success-mark');

  // --- State Variables ---
  let scanComplete = false;
  let isUnlocked = false;
  let scanTimeline; // To hold the GSAP timeline

  // --- Audio Synthesis ---
  const successSynth = new Tone.PolySynth(Tone.Synth, {
    volume: -8,
    oscillator: { type: 'sine' },
    envelope: { attack: 0.005, decay: 0.1, sustain: 0.3, release: 1 },
  }).toDestination();
  const boltSynth = new Tone.MetalSynth({
    frequency: 80,
    envelope: { attack: 0.001, decay: 0.1, release: 0.05 },
    harmonicity: 3.1,
    modulationIndex: 40,
    resonance: 3000,
    octaves: 1.5,
  }).toDestination();
  const doorSynth = new Tone.NoiseSynth({
    noise: { type: 'brown' },
    envelope: { attack: 0.1, decay: 1.4, sustain: 0, release: 0.1 },
  }).toDestination();
  const scannerSynth = new Tone.AMSynth({
    harmonicity: 1.5,
    envelope: { attack: 0.01, decay: 0.2, sustain: 0.1, release: 0.1 },
    modulationEnvelope: { attack: 0.1, decay: 0.1, sustain: 0.2, release: 0.1 },
  }).toDestination();
  const failSynth = new Tone.Synth({
    oscillator: { type: 'square' },
    envelope: { attack: 0.01, decay: 0.2, sustain: 0, release: 0.1 },
  }).toDestination();

  // --- Event Listeners ---
  scanner.addEventListener('mousedown', startScan);
  scanner.addEventListener('touchstart', startScan);
  scanner.addEventListener('mouseup', cancelScan);
  scanner.addEventListener('mouseleave', cancelScan);
  scanner.addEventListener('touchend', cancelScan);
  handle.addEventListener('click', handleHandleTurn);

  function startScan(e) {
    e.preventDefault();
    if (scanComplete || isUnlocked) return;

    scannerSynth.triggerAttack('C2');
    statusText.textContent = 'Scanning...';
    scanner.classList.add('scanning');

    // Create and play the GSAP timeline
    scanTimeline = gsap.timeline({
      onComplete: () => {
        scanSuccess();
      },
    });

    scanTimeline
      .to(scanLine, { opacity: 1, duration: 0.2 })
      .set(fingerprintLines, { filter: 'brightness(1.5)' })
      .to(
        fingerprintLines,
        {
          clipPath: 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)',
          duration: 2.0, // Slower scan for hold effect
          ease: 'power1.inOut',
        },
        '-=0.2'
      )
      .to(scanLine, { y: '80px', duration: 2.0, ease: 'power1.inOut' }, '<');
  }

  function cancelScan() {
    if (scanComplete || isUnlocked) return;
    if (scanTimeline && scanTimeline.isActive()) {
      scannerSynth.triggerRelease();
      failSynth.triggerAttackRelease('A2', '0.1', '+0.05');

      scanTimeline.kill();
      gsap.to([fingerprintLines, scanLine], {
        clearProps: 'all',
        duration: 0.3,
      });

      scanner.classList.add('fail');
      statusText.textContent = 'Scan Failed';

      setTimeout(() => {
        scanner.classList.remove('scanning');
        scanner.classList.remove('fail');
        statusText.textContent = 'Awaiting Scan';
      }, 1000);
    }
  }

  function scanSuccess() {
    if (scanComplete) return;
    scanComplete = true;
    scanner.style.cursor = 'default';
    scannerSynth.triggerRelease();

    const tl = gsap.timeline({ onComplete: activateHandle });

    tl.to(fingerprintLines, { filter: 'brightness(1)', duration: 0.3 })
      .to(scanLine, { opacity: 0, duration: 0.3 })
      .set(statusText, { textContent: 'Verified' })
      .fromTo(
        successMark,
        { scale: 0, opacity: 0 },
        { scale: 1, opacity: 1, duration: 0.5, ease: 'back.out(1.7)' }
      )
      .to(securityPanel, {
        opacity: 0,
        scale: 0.9,
        duration: 0.5,
        ease: 'power2.in',
        onComplete: () => {
          securityPanel.style.display = 'none';
        },
      })
      .fromTo(
        vaultContainer,
        { display: 'none', opacity: 0, scale: 0.9 },
        {
          display: 'block',
          opacity: 1,
          scale: 1,
          duration: 0.6,
          ease: 'power2.out',
        }
      );
  }

  function activateHandle() {
    successSynth.triggerAttackRelease(['C4', 'E4', 'G4'], '0.5', Tone.now());
    instructions.textContent = 'Click Handle to Open';
    handle.classList.add('active');
  }

  function handleHandleTurn() {
    if (!scanComplete || isUnlocked) return;
    isUnlocked = true;

    handle.classList.remove('active');

    const tl = gsap.timeline();
    tl.to(
      handle,
      {
        rotation: 120,
        duration: 0.5,
        ease: 'power2.inOut',
      },
      '-=0.2'
    )
      .call(() => boltSynth.triggerAttackRelease('C2', '0.2', Tone.now()))
      .call(openDoor);

    securityPanel.style.display = 'none';
  }

  function openDoor() {
    doorSynth.triggerAttack(Tone.now());

    vaultDoor.classList.add('is-unlocked');
    setTimeout(() => {
      mainContent.style.display = 'block';

      const revealTl = gsap.timeline({
        onComplete: () => {
          setTimeout(() => preloader.remove(), 500);
        },
      });

      revealTl
        .to(preloaderContent, {
          scale: 15,
          duration: 1.0,
          ease: 'power3.in',
        })
        .to(mainContent, {
          opacity: 1,
          duration: 1.0,
          ease: 'power1.out',
        })
        .to(
          preloader,
          {
            opacity: 0,
            duration: 0.5,
          },
          '<'
        );
    }, 600);
  }
});

Final Output:

futuristic-vault-login-fingerprint-scan-and-access-portal.gif

Conclusion:

You’ve successfully created a Futuristic Vault Login with Dummy Fingerprint Scan using HTML, CSS, and JavaScript.

Remember: This is a dummy scanner only for UI and design. It does not provide real biometric security.

This project is great for:

  • Practice in front-end development
  • Portfolio design ideas
  • Sci-fi or futuristic themed projects

With a little creativity, you can extend it with animations, neon effects, or background music to make it look like a real sci-fi vault access system.

That’s a wrap!

I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.

Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee

And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!

Thanks!
Faraz 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Components

Please allow ads on our site🥺