1. Project Overview & Features
The Light Switch & Lamp Turn On Login Form is an essential frontend project designed to help you bridge the gap between learning JavaScript syntax and building interactive, responsive web applications.
Key Features Implemented:
- Interactive hanging lamp with clickable pull-cord switch and realistic click audio
- Turns room from pitch darkness to glowing warm / neon illuminated spotlight beam
- Theme light mood selector (Warm Amber, Cyberpunk Neon Cyan, Emerald Glow)
- Working illuminated glassmorphism login form with password toggle and inputs
2. Step-by-Step Code Walkthrough
A Step 1: Semantic HTML Structure
We structure the interface using clean, semantic HTML elements. This ensures maximum accessibility and provides intuitive hooks for CSS classes and JavaScript query selectors.
<div class="room-container" id="room">
<!-- Interactive Hanging Lamp with Pull Cord -->
<div class="lamp-system">
<div class="ceiling-wire"></div>
<div class="lamp-shade"></div>
<div class="lamp-bulb" id="lamp-bulb"></div>
<!-- Pull Cord -->
<div class="pull-cord" id="pull-cord" title="Click or Pull to Turn Light On/Off">
<div class="cord-string"></div>
<div class="cord-handle"><i class="fas fa-power-off"></i></div>
</div>
</div>
<!-- Spotlight Cone Beam -->
<div class="spotlight-cone" id="spotlight"></div>
<!-- Room Floating Switch & Mood Controls -->
<div class="light-controls-bar">
<span class="light-status" id="light-status-text">Light is OFF</span>
<div class="mood-swatches">
<button class="swatch active" data-color="amber" title="Warm Amber" style="background:#f59e0b"></button>
<button class="swatch" data-color="cyan" title="Neon Cyan" style="background:#06b6d4"></button>
<button class="swatch" data-color="emerald" title="Emerald Glow" style="background:#10b981"></button>
</div>
</div>
<!-- Illuminated Login Card -->
<div class="lamp-login-card" id="lamp-login-card">
<div class="card-glow-badge"><i class="fas fa-sun"></i> Illuminated Form</div>
<h2>Night Login</h2>
<p class="lamp-sub">Pull the lamp cord above to illuminate the screen</p>
<form id="lamp-form">
<div class="lamp-input-group">
<label>Username / Email</label>
<div class="input-inner">
<i class="fas fa-user"></i>
<input type="text" id="lamp-user" placeholder="alex@example.com" required>
</div>
</div>
<div class="lamp-input-group">
<label>Password</label>
<div class="input-inner">
<i class="fas fa-key"></i>
<input type="password" id="lamp-pass" placeholder="β’β’β’β’β’β’β’β’" required>
<button type="button" id="lamp-toggle-pass" class="btn-pwd-eye"><i class="far fa-eye"></i></button>
</div>
</div>
<button type="submit" class="btn-lamp-submit">
<i class="fas fa-sign-in-alt"></i> Enter Portal
</button>
</form>
</div>
</div>B Step 2: Styling & Responsive CSS
Modern CSS flexbox and grid layouts are used to make the UI look polished, centered, and responsive across desktop, tablet, and mobile screens.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #020617;
color: #f8fafc;
overflow-x: hidden;
padding: 20px;
}
.room-container {
width: 100%;
max-width: 460px;
min-height: 580px;
background: #020617;
border-radius: 24px;
border: 1px solid #1e293b;
position: relative;
overflow: hidden;
padding: 30px 24px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
box-shadow: 0 25px 60px rgba(0, 0, 0, 0.7);
transition: background 0.4s ease;
}
/* Light ON / OFF States */
.room-container.light-on {
background: #090e1a;
}
/* Hanging Lamp Assembly */
.lamp-system {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
z-index: 10;
}
.ceiling-wire {
width: 3px;
height: 45px;
background: #64748b;
}
.lamp-shade {
width: 80px;
height: 35px;
background: #1e293b;
border: 2px solid #475569;
border-radius: 40px 40px 0 0;
position: relative;
box-shadow: 0 4px 10px rgba(0,0,0,0.5);
}
.lamp-bulb {
width: 24px;
height: 24px;
background: #334155;
border-radius: 50%;
margin-top: -8px;
transition: all 0.3s ease;
}
/* Light ON Bulb Glow */
.room-container.light-on .lamp-bulb {
background: #ffedd5;
box-shadow: 0 0 30px 10px #f59e0b, 0 0 60px 20px rgba(245, 158, 11, 0.4);
}
.room-container.light-on.cyan-theme .lamp-bulb {
background: #cffafe;
box-shadow: 0 0 30px 10px #06b6d4, 0 0 60px 20px rgba(6, 182, 212, 0.4);
}
.room-container.light-on.emerald-theme .lamp-bulb {
background: #d1fae5;
box-shadow: 0 0 30px 10px #10b981, 0 0 60px 20px rgba(16, 185, 129, 0.4);
}
/* Pull Cord Assembly */
.pull-cord {
position: absolute;
top: 70px;
right: -25px;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
user-select: none;
transition: transform 0.15s ease;
}
.pull-cord:active {
transform: translateY(12px);
}
.cord-string {
width: 2px;
height: 65px;
background: #94a3b8;
}
.cord-handle {
width: 24px;
height: 24px;
background: #f59e0b;
color: #0f172a;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
box-shadow: 0 2px 8px rgba(0,0,0,0.4);
animation: pulseCord 2s infinite ease-in-out;
}
@keyframes pulseCord {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
/* Spotlight Cone Beam */
.spotlight-cone {
position: absolute;
top: 75px;
left: 50%;
transform: translateX(-50%);
width: 440px;
height: 500px;
background: radial-gradient(ellipse at top, rgba(245, 158, 11, 0.25) 0%, rgba(245, 158, 11, 0.08) 45%, rgba(0, 0, 0, 0) 75%);
clip-path: polygon(42% 0%, 58% 0%, 100% 100%, 0% 100%);
pointer-events: none;
opacity: 0;
transition: opacity 0.4s ease;
z-index: 2;
}
.room-container.light-on .spotlight-cone {
opacity: 1;
}
.room-container.light-on.cyan-theme .spotlight-cone {
background: radial-gradient(ellipse at top, rgba(6, 182, 212, 0.25) 0%, rgba(6, 182, 212, 0.08) 45%, rgba(0, 0, 0, 0) 75%);
}
.room-container.light-on.emerald-theme .spotlight-cone {
background: radial-gradient(ellipse at top, rgba(16, 185, 129, 0.25) 0%, rgba(16, 185, 129, 0.08) 45%, rgba(0, 0, 0, 0) 75%);
}
/* Controls Bar */
.light-controls-bar {
position: absolute;
top: 18px;
left: 20px;
right: 20px;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 20;
}
.light-status {
font-size: 0.8rem;
font-weight: 700;
color: #64748b;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.room-container.light-on .light-status { color: #f59e0b; }
.room-container.light-on.cyan-theme .light-status { color: #06b6d4; }
.room-container.light-on.emerald-theme .light-status { color: #10b981; }
.mood-swatches {
display: flex;
gap: 6px;
}
.swatch {
width: 18px;
height: 18px;
border-radius: 50%;
border: 2px solid transparent;
cursor: pointer;
transition: transform 0.2s;
}
.swatch.active {
border-color: #ffffff;
transform: scale(1.2);
}
/* Illuminated Login Card */
.lamp-login-card {
background: rgba(15, 23, 42, 0.88);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20px;
padding: 24px;
width: 100%;
position: relative;
z-index: 5;
transition: all 0.4s ease;
filter: brightness(0.4) blur(1px);
}
.room-container.light-on .lamp-login-card {
filter: brightness(1) blur(0px);
border-color: rgba(245, 158, 11, 0.3);
box-shadow: 0 15px 35px -5px rgba(245, 158, 11, 0.2);
}
.room-container.light-on.cyan-theme .lamp-login-card {
border-color: rgba(6, 182, 212, 0.3);
box-shadow: 0 15px 35px -5px rgba(6, 182, 212, 0.2);
}
.room-container.light-on.emerald-theme .lamp-login-card {
border-color: rgba(16, 185, 129, 0.3);
box-shadow: 0 15px 35px -5px rgba(16, 185, 129, 0.2);
}
.card-glow-badge {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
color: #f59e0b;
margin-bottom: 6px;
}
.lamp-login-card h2 {
font-size: 1.4rem;
font-weight: 800;
margin-bottom: 4px;
}
.lamp-sub {
font-size: 0.82rem;
color: #94a3b8;
margin-bottom: 18px;
}
.lamp-input-group {
margin-bottom: 14px;
}
.lamp-input-group label {
display: block;
font-size: 0.8rem;
color: #94a3b8;
margin-bottom: 6px;
}
.input-inner {
position: relative;
display: flex;
align-items: center;
}
.input-inner i {
position: absolute;
left: 12px;
color: #64748b;
font-size: 0.9rem;
}
.input-inner input {
width: 100%;
background: #020617;
border: 1px solid #334155;
border-radius: 10px;
padding: 10px 38px 10px 34px;
color: #f8fafc;
font-size: 0.9rem;
outline: none;
transition: border-color 0.2s;
}
.input-inner input:focus {
border-color: #f59e0b;
}
.btn-pwd-eye {
position: absolute;
right: 10px;
background: none;
border: none;
color: #64748b;
cursor: pointer;
}
.btn-lamp-submit {
width: 100%;
background: #f59e0b;
color: #0f172a;
border: none;
padding: 12px;
border-radius: 10px;
font-weight: 700;
font-size: 0.95rem;
cursor: pointer;
margin-top: 8px;
transition: opacity 0.2s;
}
.btn-lamp-submit:hover { opacity: 0.9; }C Step 3: JavaScript Logic & Event Handling
Here is the complete JavaScript code handling the state, event listeners, mathematical logic, and dynamic DOM rendering:
let isLightOn = false;
let currentMood = 'amber';
const room = document.getElementById('room');
const pullCord = document.getElementById('pull-cord');
const statusText = document.getElementById('light-status-text');
const swatches = document.querySelectorAll('.swatch');
const togglePassBtn = document.getElementById('lamp-toggle-pass');
const passInput = document.getElementById('lamp-pass');
const lampForm = document.getElementById('lamp-form');
// Sound synthesis for pull cord click
function playSwitchSound() {
try {
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = 'triangle';
osc.frequency.setValueAtTime(isLightOn ? 380 : 260, audioCtx.currentTime);
gain.gain.setValueAtTime(0.15, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.08);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + 0.08);
} catch(e) {}
}
// Toggle Light
function toggleLight() {
isLightOn = !isLightOn;
room.classList.toggle('light-on', isLightOn);
statusText.textContent = isLightOn ? `Light is ON (${currentMood.toUpperCase()})` : 'Light is OFF';
playSwitchSound();
}
pullCord.addEventListener('click', toggleLight);
// Mood Color Swatches
swatches.forEach(swatch => {
swatch.addEventListener('click', () => {
swatches.forEach(s => s.classList.remove('active'));
swatch.classList.add('active');
currentMood = swatch.dataset.color;
room.classList.remove('cyan-theme', 'emerald-theme');
if (currentMood === 'cyan') room.classList.add('cyan-theme');
if (currentMood === 'emerald') room.classList.add('emerald-theme');
if (isLightOn) {
statusText.textContent = `Light is ON (${currentMood.toUpperCase()})`;
}
});
});
// Toggle password visibility
togglePassBtn.addEventListener('click', () => {
const isPass = passInput.type === 'password';
passInput.type = isPass ? 'text' : 'password';
togglePassBtn.innerHTML = isPass ? '<i class="far fa-eye-slash"></i>' : '<i class="far fa-eye"></i>';
});
// Submit Form
lampForm.addEventListener('submit', (e) => {
e.preventDefault();
if (!isLightOn) {
toggleLight();
}
alert('Welcome! Authenticated via Illuminated Lamp Login.');
});
// Auto turn on after 600ms for delightful initial demo
setTimeout(toggleLight, 600);3. Core JavaScript Concepts You Learned
Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.
Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.
Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.
Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.
Crucial concept utilized to power the dynamic state, user interactions, and styling of this project.
4. How to Run Locally on Your Computer
- Download the project ZIP: Click the Download Project (.ZIP) button at the top or in the live runner to save
lamp-light-login-project.zip. - Extract the archive: Unzip the downloaded file. Inside you will find separate
index.html,style.css,script.js,index-standalone.html, and a comprehensiveREADME.md. - Open in any browser: Simply double-click
index.html(orindex-standalone.html) to open and test immediately in Chrome, Firefox, Safari, or Edge. - Edit in Visual Studio Code: Open the extracted folder in VS Code. Right-click
index.htmland select "Open with Live Server" to enjoy instant live reloading as you modify HTML, CSS, or JS!
Bonus Challenges for Learners
Ready to level up? Try adding these extra features on your own:
- Add sound effects or audio feedback for user button clicks.
- Add custom theme color customizer with CSS variables.
- Export the results to PDF or copy as a formatted text summary.