How to Create a Simple Web Stopwatch with HTML and JavaScript

A lightweight front-end project easily portable to an Android APK application.

Hello, all programming enthusiasts! This time, I want to share a simple but very useful project: a web stopwatch built with clean HTML, CSS, and optimized JavaScript. Additionally, you will learn how this base can be seamlessly adapted into a standalone mobile application (APK) using Android Studio.

What are we going to build?

We are going to develop a digital stopwatch designed to feature precise control through three primary behaviors:

  • Start: Fires the timer interval to track time incrementally.
  • Stop: Pauses the current progression without losing track of the elapsed metrics.
  • Reset: Tears down the interval loops and clears all tracking components back to absolute zero.
Live Interactive Demo
00:00.00

HTML and CSS: The Structure and Presentation

HTML delivers the semantics and content nodes of the page, while CSS ensures clean proportions, crisp typography, and responsive buttons. Below is the optimized code block combining structure and look-and-feel variables:

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Stopwatch</title>
    <style>
        body {
            background-color: #f0f9ff;
            text-align: center;
            font-family: sans-serif;
            padding-top: 50px;
        }
        .display {
            font-size: 60px;
            font-family: monospace;
            color: #1e3a8a;
            margin-bottom: 20px;
        }
        .boton {
            display: inline-block;
            padding: 12px 24px;
            font-size: 18px;
            font-weight: bold;
            color: white;
            background-color: #0284c7;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            margin: 0 5px;
            transition: background-color 0.2s ease;
        }
        .boton:hover {
            background-color: #0369a1;
        }
    </style>
</head>
<body>

    <div id="cronometro" class="display">00:00.00</div>

    <div>
        <button onclick="iniciar()" class="boton">Start</button>
        <button onclick="detener()" class="boton">Stop</button>
        <button onclick="reiniciar()" class="boton">Reset</button>
    </div>

</body>
</html>

JavaScript: The Refactored Logic

The logic relies on a timing interval wrapper. This refactored version resolves a typical race condition bug: it blocks duplicate loops if multiple clicks trigger the "Start" state concurrently.

app.js
let centisegundos = 0;
let segundos = 0;
let minutos = 0;
let intervalo = null; // Inicializado en null para control de flujo

function iniciar() {
    // Si ya existe un intervalo corriendo, ignoramos la llamada para evitar aceleraciones bursátiles
    if (intervalo !== null) return;

    intervalo = setInterval(() => {
        centisegundos++;
        if (centisegundos === 100) { // Corrección técnica: 100 centisegundos forman 1 segundo real
            centisegundos = 0;
            segundos++;
        }
        if (segundos === 60) {
            segundos = 0;
            minutos++;
        }
        
        // Renderizado con formateo padStart de dos posiciones fijas
        const minStr = minutos.toString().padStart(2, '0');
        const segStr = segundos.toString().padStart(2, '0');
        const cenStr = centisegundos.toString().padStart(2, '0');
        
        document.getElementById('cronometro').textContent = `${minStr}:${segStr}.${cenStr}`;
    }, 10); // Intervalo ajustado a 10ms para precisión milimétrica real
}

function detener() {
    clearInterval(intervalo);
    intervalo = null; // Forzar restauración de flag lógica
}

function reiniciar() {
    detener();
    centisegundos = 0;
    segundos = 0;
    minutos = 0;
    document.getElementById('cronometro').textContent = '00:00.00';
}

How the Code Works Under the Hood

The HTML Framework

  • <meta name="viewport">: Essential for mobile responsiveness, adjusting scale profiles automatically across devices.
  • id="cronometro": Provides an explicit element target for the DOM to update text strings directly.
  • onclick="...": Event handler bridges execution from structural interaction nodes into JS engine executions.

The Functional Logic

  • Control Flag Check (if (intervalo !== null)): Crucial optimization ensuring safety constraints. It prevents subsequent keystrokes from orphaning older timers in background execution heaps.
  • Dynamic Padding (padStart(2, '0')): Guarantees that single digits preserve structured placeholders (e.g., transforming integers like 7 into string representations like "07").

Creating the Android APK with Android Studio

Once your web application operates flawlessly inside mobile browsers, wrapping it up inside a native Android execution wrapper takes only a few architectural adjustments:

  1. Install Android Studio: Down and set up the IDE environments using standard configuration variables.
  2. Spin up an Empty Activity Project: Initialize a new repository using Java or Kotlin profiles.
  3. Inject your Assets: Move your index.html (along with your styles and script bundles) straight into the project's src/main/assets/ physical assets subfolder.
  4. Implement a Native WebView Component: Update your core layout activity view configuration (activity_main.xml) to hook a full-screen mobile renderer component:
    activity_main.xml
    <WebView
        android:id="@+id/myWebView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  5. Bind execution and enable scripting inside Main Activity: Locate your runtime controller component class and update logic to toggle browser features inside the View container:
    MainActivity.java
    WebView webView = findViewById(R.id.myWebView);
    webView.getSettings().setJavaScriptEnabled(true); // Requerido para procesar app.js
    webView.loadUrl("file:///android_asset/index.html");
  6. Compile your Deployment Binaries: Go to Build > Build Bundle(s) / APK(s) > Build APK(s). Android Studio will bundle the assets into an isolated, distributable .apk package file.

Conclusion

Building a lightweight web stopwatch highlights the power of separating structure (HTML), style (CSS), and robust operational lifecycles (JavaScript). By keeping core runtimes efficient, transforming your web assets into cross-platform android apps becomes a fast, streamlined integration process. Take this clean project template, append split lap records features, or custom design configurations to make it your own!

Free Tools

Explore free web applications developed by Ufumbuzi.

About Ufumbuzi

Ufumbuzi develops free web applications and publishes articles about technology, programming, artificial intelligence and software development.

Our goal is to create useful, privacy-friendly software accessible from any device.

Explore Free Apps →
Link copied to clipboard