WhatsApp us

Elevator System Tutorial in JavaScript – Simple HTML, CSS & JS Project for Beginners

  • Tech Area
  • Last updated on: January 8, 2026



Creating small JavaScript projects is one of the best ways to understand core concepts like event handling, DOM manipulation, timers, and smooth animation. In this tutorial, we will build a simple Elevator System using HTML, CSS, and JavaScript.
This project is perfect for beginners who want to learn how real-world logic can be applied in JavaScript.

Files used in this tutorial:

1- index.html (Contains the elevator’s user interface)

2- elevatorEngine.js (Contains the full elevator movement logic)

3- style.css (Styles the elevator and floors)

Below are the step-by-step processes to create an Elevator System project in JavaScript.

Step 1: Create the HTML Layout

Start by creating a new file named index.html.
This file contains the elevator structure, floor buttons, and display panel used in the tutorial.

This screenshot shows the elevator layout.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Elevator Demo</title>

    <!-- CSS -->
    <link rel="stylesheet" href="style.css">
</head>
<body>

<div class="container">
    <div class="gridWrapper">

        <!-- Floor 10 -->
        <div class="box firstChild">10</div>
        <div class="box elevatorBox" data-floor="10" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="10" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="10" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="10" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="10" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="10">CALL</a></div>

        <!-- Floor 9 -->
        <div class="box firstChild">9</div>
        <div class="box elevatorBox" data-floor="9" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="9" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="9" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="9" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="9" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="9">CALL</a></div>

        <!-- Floor 8 -->
        <div class="box firstChild">8</div>
        <div class="box elevatorBox" data-floor="8" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="8" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="8" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="8" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="8" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="8">CALL</a></div>

        <!-- Floor 7 -->
        <div class="box firstChild">7</div>
        <div class="box elevatorBox" data-floor="7" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="7" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="7" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="7" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="7" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="7">CALL</a></div>

        <!-- Floor 6 -->
        <div class="box firstChild">6</div>
        <div class="box elevatorBox" data-floor="6" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="6" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="6" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="6" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="6" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="6">CALL</a></div>

        <!-- Floor 5 -->
        <div class="box firstChild">5</div>
        <div class="box elevatorBox" data-floor="5" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="5" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="5" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="5" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="5" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="5">CALL</a></div>

        <!-- Floor 4 -->
        <div class="box firstChild">4</div>
        <div class="box elevatorBox" data-floor="4" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="4" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="4" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="4" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="4" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="4">CALL</a></div>

        <!-- Floor 3 -->
        <div class="box firstChild">3</div>
        <div class="box elevatorBox" data-floor="3" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="3" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="3" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="3" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="3" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="3">CALL</a></div>

        <!-- Floor 2 -->
        <div class="box firstChild">2</div>
        <div class="box elevatorBox" data-floor="2" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="2" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="2" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="2" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="2" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="2">CALL</a></div>

        <!-- Floor 1 -->
        <div class="box firstChild">1</div>
        <div class="box elevatorBox" data-floor="1" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="1" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="1" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="1" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="1" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="1">CALL</a></div>

        <!-- Floor 0 -->
        <div class="box firstChild">0</div>
        <div class="box elevatorBox" data-floor="0" data-elevator="1"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="0" data-elevator="2"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="0" data-elevator="3"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="0" data-elevator="4"><div class="wait-time"></div></div>
        <div class="box elevatorBox" data-floor="0" data-elevator="5"><div class="wait-time"></div></div>
        <div class="box lastChild"><a class="call-btn" href="#" data-floor="0">CALL</a></div>

    </div>
</div>

<!-- JavaScript -->
<script type="text/javascript" src="elevatorEngine.js"></script>

</body>
</html>

Step 2: Add the Elevator Logic Using JavaScript

Create a new file named elevatorEngine.js.
This file will handle the elevator movement logic, floor selection, button interactions, and animation updates.

elevatorEngine.js

// Elevator SVG 
const elevatorSVG = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<path d="M 15.875 0 C 15.617188 0.0351563 15.378906 0.167969 15.21875 0.375 L 10.21875 6.375 C 9.976563 6.675781 9.929688 7.085938 10.097656 7.433594 C 10.265625 7.78125 10.617188 8 11 8 L 21 8 C 21.382813 8 21.734375 7.78125 21.902344 7.433594 C 22.070313 7.085938 22.023438 6.675781 21.78125 6.375 L 16.78125 0.375 C 16.566406 0.101563 16.222656 -0.0429688 15.875 0 Z M 29.8125 0 C 29.460938 0.0625 29.171875 0.308594 29.046875 0.640625 C 28.925781 0.976563 28.992188 1.351563 29.21875 1.625 L 34.21875 7.625 C 34.410156 7.863281 34.695313 8 35 8 C 35.304688 8 35.589844 7.863281 35.78125 7.625 L 40.78125 1.625 C 41.023438 1.324219 41.070313 0.914063 40.902344 0.566406 C 40.734375 0.21875 40.382813 0 40 0 L 30 0 C 29.96875 0 29.9375 0 29.90625 0 C 29.875 0 29.84375 0 29.8125 0 Z M 32.125 2 L 37.875 2 L 35 5.4375 Z M 16 2.5625 L 18.875 6 L 13.125 6 Z M 3 10 C 1.355469 10 0 11.355469 0 13 L 0 47 C 0 48.644531 1.355469 50 3 50 L 47 50 C 48.644531 50 50 48.644531 50 47 L 50 13 C 50 11.355469 48.644531 10 47 10 Z M 3 12 L 47 12 C 47.554688 12 48 12.445313 48 13 L 48 47 C 48 47.554688 47.554688 48 47 48 L 3 48 C 2.445313 48 2 47.554688 2 47 L 2 13 C 2 12.445313 2.445313 12 3 12 Z M 11 14 C 8.800781 14 7 15.800781 7 18 C 7 20.199219 8.800781 22 11 22 C 13.199219 22 15 20.199219 15 18 C 15 15.800781 13.199219 14 11 14 Z M 11 22 C 7.675781 22 5 24.675781 5 28 L 5 35 C 4.996094 35.386719 5.214844 35.738281 5.5625 35.90625 L 7 36.625 L 7 45 C 7 45.550781 7.449219 46 8 46 L 14 46 C 14.550781 46 15 45.550781 15 45 L 15 36.625 L 16.4375 35.90625 C 16.785156 35.738281 17.003906 35.386719 17 35 L 17 28 C 17 24.675781 14.324219 22 11 22 Z M 25 14 C 22.800781 14 21 15.800781 21 18 C 21 20.199219 22.800781 22 25 22 C 27.199219 22 29 20.199219 29 18 C 29 15.800781 27.199219 14 25 14 Z M 25 22 C 21.675781 22 19 24.675781 19 28 L 19 35 C 18.996094 35.386719 19.214844 35.738281 19.5625 35.90625 L 21 36.625 L 21 45 C 21 45.550781 21.449219 46 22 46 L 28 46 C 28.550781 46 29 45.550781 29 45 L 29 36.625 L 30.4375 35.90625 C 30.785156 35.738281 31.003906 35.386719 31 35 L 31 28 C 31 24.675781 28.324219 22 25 22 Z M 39 14 C 36.800781 14 35 15.800781 35 18 C 35 20.199219 36.800781 22 39 22 C 41.199219 22 43 20.199219 43 18 C 43 15.800781 41.199219 14 39 14 Z M 39 22 C 35.675781 22 33 24.675781 33 28 L 33 35 C 32.996094 35.386719 33.214844 35.738281 33.5625 35.90625 L 35 36.625 L 35 45 C 35 45.550781 35.449219 46 36 46 L 42 46 C 42.550781 46 43 45.550781 43 45 L 43 36.625 L 44.4375 35.90625 C 44.785156 35.738281 45.003906 35.386719 45 35 L 45 28 C 45 24.675781 42.324219 22 39 22 Z"
fill="#000000"/></svg>
`;

// Red elevator SVG
const elevatorSVGRed = elevatorSVG.replace(`fill="#000000"`, `fill="red"`);

// Elevator image mapping
const elevatorsImg = {
    1: `<div id="elevator-1">${elevatorSVG}</div>`,
    2: `<div id="elevator-2">${elevatorSVG}</div>`,
    3: `<div id="elevator-3">${elevatorSVGRed}</div>`,
    4: `<div id="elevator-4">${elevatorSVG}</div>`,
    5: `<div id="elevator-5">${elevatorSVGRed}</div>`
};

// Create elevator on a random floor
let elevators = Array.from({ length: 5 }, (_, i) => {
    let floor = Math.floor(Math.random() * 10);
    return {
        id: i + 1,
        currentFloor: floor,
        busy: false
    };
});

// Display elevator inside correct slot
function displayElevators(elevatorArray) {
    elevatorArray.forEach(elevator => {
        let floor = (elevator.id === 3 || elevator.id === 5)
            ? 0
            : elevator.currentFloor;

        let selector = `.elevatorBox[data-floor="${floor}"][data-elevator="${elevator.id}"]`;
        let box = document.querySelector(selector);

        if (box) {
            box.innerHTML = elevatorsImg[elevator.id];
        }
    });
}

// On page load
document.addEventListener("DOMContentLoaded", function () {
    displayElevators(elevators);

    document.querySelectorAll(".call-btn").forEach(button => {
        button.addEventListener("click", function (event) {
            event.preventDefault();

            const floorId = parseInt(this.getAttribute("data-floor"));

            const elevatorOnThisFloor = elevators.some(
                elevator =>
                    elevator.currentFloor === floorId &&
                    elevator.id !== 3 &&
                    elevator.id !== 5
            );

            if (elevatorOnThisFloor) {
                this.disabled = true;
                return;
            }

            this.disabled = true;
            this.style.backgroundColor = "red";
            this.textContent = "WAITING";

            requestElevator(floorId, this);
        });
    });
});

// Request elevator
function requestElevator(requestedFloor, button) {
    let availableElevators = elevators.filter(
        elevator => !elevator.busy && elevator.id !== 3 && elevator.id !== 5
    );

    if (availableElevators.length > 0) {
        let nearestElevator = availableElevators.reduce((nearest, elevator) => {
            const nearestDist = Math.abs(nearest.currentFloor - requestedFloor);
            const elevatorDist = Math.abs(elevator.currentFloor - requestedFloor);

            return elevatorDist < nearestDist ? elevator : nearest;
        }, availableElevators[0]);

        moveElevator(nearestElevator, requestedFloor, button);
    } else {
        queueRequest(requestedFloor, button);
    }
}

// Move elevator with animation
function moveElevator(elevator, targetFloor, button) {
    elevator.busy = true;

    const elevatorImg = document.getElementById(`elevator-${elevator.id}`);
    const floorHeight = 50;
    const totalFloors = 11;

    const floorsToMove = Math.abs(targetFloor - elevator.currentFloor);
    const speedPerFloor = 1; 
    const totalDuration = floorsToMove * speedPerFloor;

    const minutes = Math.floor(totalDuration / 60);
    const seconds = Math.floor(totalDuration % 60);

    let formattedTime =
        minutes > 0
            ? `${minutes} Min${minutes > 1 ? "s" : ""}${seconds > 0 ? `, ${seconds} Second${seconds > 1 ? "s" : ""}` : ""}`
            : `${seconds} Second${seconds > 1 ? "s" : ""}`;

    const selector = `.elevatorBox[data-floor="${targetFloor}"][data-elevator="${elevator.id}"]`;
    const box = document.querySelector(selector);

    let etaDiv = box ? box.querySelector(".wait-time") : null;
    if (etaDiv) {
        etaDiv.textContent = formattedTime;
    }

    const currentY = (totalFloors - 1 - elevator.currentFloor) * floorHeight;
    const targetY = (totalFloors - 1 - targetFloor) * floorHeight;
    const translateY = targetY - currentY;

    if (!elevator.cumulativeY) elevator.cumulativeY = 0;
    elevator.cumulativeY += translateY;

    if (elevatorImg) {
        elevatorImg.querySelector("path").setAttribute("fill", "green");
        elevatorImg.style.transition = `transform ${totalDuration}s linear`;
        elevatorImg.style.transform = `translateY(${elevator.cumulativeY}px)`;
    }

    setTimeout(() => {
        elevator.currentFloor = targetFloor;
        elevator.busy = false;

        button.style.backgroundColor = "#5bcd88";
        button.textContent = "ARRIVED";

        if (etaDiv) etaDiv.textContent = "";

        setTimeout(() => {
            elevatorImg.querySelector("path").setAttribute("fill", "black");
            button.textContent = "CALL";
            button.style.backgroundColor = "";
            button.disabled = false;
        }, 2000);

        processQueue();
    }, totalDuration * 1000);
}

// Queue System
let requestQueue = [];

function queueRequest(floor, button) {
    requestQueue.push({ floor, button });
}

function processQueue() {
    if (requestQueue.length > 0) {
        const nextRequest = requestQueue.shift();
        requestElevator(nextRequest.floor, nextRequest.button);
    }
}

Step 3: Add the Styling for the Elevator UI

Create a new file named style.css.
This file will style the elevator cabin, floor buttons, indicators, and overall layout to make the interface clean and user-friendly.

style.css

.container {
    max-width: 1200px;
    margin: 0 auto;
}

.gridWrapper {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    align-items: center;
}

.box {
    height: 50px;
    border: 1px solid grey;
    background-color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Floor number column */
.firstChild {
    border: 0;
    justify-content: end;
    padding-right: 10px;
}

/* Elevator SVG styling */
.elevatorBox svg {
    width: 32px;
}

/* CALL button column */
.lastChild {
    background-color: transparent;
    border: 0;
}

/* CALL button style */
.box .call-btn {
    background-color: #5d7b69;
    padding: 10px 25px;
    border-radius: 4px;
    color: #fff;
    text-decoration: none;
}

Download Source Code


Subscribe us via Email

Join 20,000+ subscriber

Subscribe on YouTube

PHP Projects
Matrimonial Portal Project in PHP & MySQL Last Updated: December 22, 2025
Event Management System Project in PHP & MySQL Last Updated: December 6, 2025
Online Shopping System Project in PHP MySQL Last Updated: November 26, 2025
Hostel management system project in PHP and MySQL Last Updated: February 14, 2024
Online Pizza Delivery project in PHP Last Updated: February 4, 2024
Parking Management System project in PHP Last Updated: November 5, 2023
Visitors Management System project in PHP Last Updated: August 28, 2023
SNIPE – IT Asset management system v6.1.0 Last Updated: April 21, 2023
Employee Management System project in PHP Last Updated: January 21, 2023