Overview & What You Will Learn

What We Are Building

In this project, we are building a high-precision digital stopwatch application with lap timer split functionality. The app allows users to start, pause, resume, and reset the timer, as well as record lap times which are displayed dynamically in a scrollable split history list.

How We Are Building It

We structure the app using an HTML container with a digital LCD display screen, control buttons, and an un-ordered list for lap splits. We style the display with high-contrast dark theme colors and monospace typography. Using JavaScript, we measure elapsed time accurately with Date.now() timestamps, run a 10ms timer interval loop, format time units (minutes, seconds, hundredths of a second), and prepend new lap split records onto the DOM dynamically.

Key Skills & Concepts You Will Learn:

  • Accurate time tracking using JavaScript Date.now() timestamp arithmetic
  • Managing interval loops with setInterval() and clearInterval()
  • Formatting raw milliseconds into human-readable time strings (00:00.00)
  • Dynamic DOM element creation and insertion using insertBefore()
  • Toggling element states (disabled/enabled, Start/Pause) based on application status

Interactive Live Demo

Digital Stopwatch & Lap Timer Preview

Step-by-Step Tutorial

Step 1HTML Structure: Display Screen & Control Buttons

We construct a centered stopwatch container using <div> elements. Inside, we place a title, a primary timer display screen for minutes, seconds, and hundredths of a second, followed by three control keys using <button> tags (Start/Pause, Lap, and Reset).

<div class="stopwatch-container">
  <div class="stopwatch-title">Digital Stopwatch</div>

  <div class="timer-display" id="display">
    00:00<span class="milliseconds">.00</span>
  </div>

  <div class="controls">
    <button id="start-btn" class="btn btn-start">Start</button>
    <button id="lap-btn" class="btn btn-lap" disabled>Lap</button>
    <button id="reset-btn" class="btn btn-reset">Reset</button>
  </div>
</div>
💡 Key Concepts & Tips:
  • disabled attribute on the Lap button prevents recording split times before the timer has started.
Step 2HTML Lap History List Container

Below the control buttons, we add an unordered list (<ul>) to serve as a container for dynamically generated split lap records.

<ul id="laps-list" class="laps-list">
  <!-- Lap items dynamically inserted via JS -->
</ul>
💡 Key Concepts & Tips:
  • Use semantic <ul> elements for accessible list structures.
Step 3CSS Styling: Digital LCD Screen & Monospace Fonts

We style the stopwatch display to resemble a dark digital LCD screen using dark background colors, high-contrast neon text, and a monospace font stack using CSS font-family. Controls use CSS Flexbox Layout for centered alignment.

.timer-display {
  font-family: monospace;
  background-color: #1e1e2e;
  color: #50fa7b;
  font-size: 2.2rem;
  padding: 20px;
  border-radius: 12px;
  text-align: center;
  margin-bottom: 20px;
}

.controls {
  display: flex;
  gap: 12px;
  justify-content: center;
}
💡 Key Concepts & Tips:
  • Using a monospace font stack ensures numbers maintain identical character widths as digits update rapidly.
Step 4JavaScript Timestamp Precision & Interval Timer Loop

We use Date.now() timestamps to measure elapsed time accurately instead of relying solely on tick counts. Clicking Start launches a setInterval() timer loop that recalculates elapsed time every 10 milliseconds and formats time units onto the screen using DOM manipulation.

function startTimer() {
  if (!isRunning) {
    isRunning = true;
    startTime = Date.now() - elapsedTime;
    timerInterval = setInterval(() => {
      elapsedTime = Date.now() - startTime;
      display.innerHTML = formatTime(elapsedTime);
    }, 10);
  }
}
💡 Key Concepts & Tips:
  • Calculating time using Date.now() - startTime guarantees precise elapsed time even when browser tabs are backgrounded.
  • Always clear active timer handles with clearInterval() when pausing or resetting.
Step 5JavaScript Dynamic Lap Split Time Insertion

Each time the user clicks "Lap", we subtract the previous total elapsed time from current elapsed time to compute the split lap duration, dynamically create a new <li> element, and insert it at the top of the list using JavaScript.

function recordLap() {
  const currentLapTime = elapsedTime - lastLapTime;
  lastLapTime = elapsedTime;
  const li = document.createElement('li');
  li.innerHTML = `<span>Lap #${lapCounter}</span><span>${formatTime(currentLapTime)}</span>`;
  lapsList.insertBefore(li, lapsList.firstChild);
}
💡 Key Concepts & Tips:
  • Inserting laps using insertBefore(li, lapsList.firstChild) keeps the newest split time right at the top for instant visibility.

Complete Project Source Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="stopwatch-container">
  <div class="stopwatch-title">Digital Stopwatch</div>
  
  <div class="timer-display" id="display">
    00:00<span class="milliseconds">.00</span>
  </div>
  
  <div class="controls">
    <button id="start-btn" class="btn btn-start">Start</button>
    <button id="lap-btn" class="btn btn-lap" disabled>Lap</button>
    <button id="reset-btn" class="btn btn-reset">Reset</button>
  </div>
  
  <div class="laps-section">
    <div class="laps-header">
      <span>Lap #</span>
      <span>Lap Time</span>
      <span>Total Time</span>
    </div>
    <ul id="laps-list" class="laps-list">
      <li class="empty-laps">No laps recorded yet.</li>
    </ul>
  </div>
</div>
File: index.html (24 lines)HTML

Explore Other Web Projects