JavaScript Tutorial

JavaScript Project: Counter

Plus, minus, and reset buttons that update a number on the page.

What you will build

A counter with one displayed number and three buttons: plus one, minus one, and reset to zero. Each click updates the same value in memory and writes it onto the page.

The number lives in a JavaScript variable. The heading only shows a copy of that value. If you stored the count only in the heading, a stray space or a second element would break the math.

Open an example with Try it in JavaScript. That loads /javascript/try — a live page and a console.

Methods you will use

MethodJob on this page
clickIncreases, decreases, or resets the count
state (let count)Keeps the current number in one place
textContentDraws the number onto the page after every change
addEventListenerAttaches one handler per button
StringTurns the number into text for the heading

One render function is enough. Plus, minus, and reset all change count, then call the same draw. Do not copy the same textContent line into three handlers.

Build in slices

Markup first. The count needs an id. Each button needs an id and type="button" so it never submits a form.

Example

<p id="count">0</p>
<button id="plus" type="button">Plus</button>
<button id="minus" type="button">Minus</button>
<button id="reset" type="button">Reset</button>

Keep the number in a variable. Write a render that copies it to the page. Call that function once at start so the heading matches the variable even if you change the starting value later.

Example

let count = 0;
const display = document.getElementById("count");

function render() {
  display.textContent = String(count);
}

document.getElementById("plus").addEventListener("click", function () {
  count += 1;
  render();
});

document.getElementById("minus").addEventListener("click", function () {
  count -= 1;
  render();
});

document.getElementById("reset").addEventListener("click", function () {
  count = 0;
  render();
});

render();

Combine markup and script. Click plus twice, minus once, then reset. The heading should show 2, then 1, then 0.

Example

<p id="count">0</p>
<button id="plus" type="button">Plus</button>
<button id="minus" type="button">Minus</button>
<button id="reset" type="button">Reset</button>
<script>
  let count = 0;
  const display = document.getElementById("count");

  function render() {
    display.textContent = String(count);
  }

  document.getElementById("plus").addEventListener("click", function () {
    count += 1;
    render();
  });
  document.getElementById("minus").addEventListener("click", function () {
    count -= 1;
    render();
  });
  document.getElementById("reset").addEventListener("click", function () {
    count = 0;
    render();
  });
  render();
</script>

Run the slice at /javascript/try with Try it in JavaScript. Watch the heading, not the console. The console can stay empty.

Complete document

This file is the counter you would keep. The number is large so clicks are obvious. Buttons sit in a row. Minus is allowed to go below zero — that is the honest default. A later practice task can clamp it.

Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Counter</title>
  <style>
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      background: #fefce8;
      font-family: "Segoe UI", system-ui, sans-serif;
      color: #1c1917;
    }
    .card {
      width: min(20rem, 92vw);
      background: #fffbeb;
      border: 1px solid #fde68a;
      padding: 1.4rem 1.5rem 1.55rem;
      text-align: center;
    }
    h1 {
      margin: 0 0 0.25rem;
      font-size: 1.2rem;
    }
    #count {
      margin: 0.4rem 0 1rem;
      font-size: 3.2rem;
      font-weight: 800;
      letter-spacing: -0.04em;
    }
    .row {
      display: flex;
      gap: 0.5rem;
      justify-content: center;
    }
    button {
      min-width: 4.4rem;
      padding: 0.5rem 0.7rem;
      border: 0;
      background: #854d0e;
      color: #fffbeb;
      font: inherit;
      font-weight: 700;
      cursor: pointer;
    }
    #reset {
      background: #a8a29e;
      color: #1c1917;
    }
  </style>
</head>
<body>
  <article class="card">
    <h1>Counter</h1>
    <p id="count">0</p>
    <div class="row">
      <button id="minus" type="button">Minus</button>
      <button id="reset" type="button">Reset</button>
      <button id="plus" type="button">Plus</button>
    </div>
  </article>
  <script>
    let count = 0;
    const display = document.getElementById("count");

    function render() {
      display.textContent = String(count);
    }

    document.getElementById("plus").addEventListener("click", function () {
      count += 1;
      render();
    });
    document.getElementById("minus").addEventListener("click", function () {
      count -= 1;
      render();
    });
    document.getElementById("reset").addEventListener("click", function () {
      count = 0;
      render();
    });

    render();
  </script>
</body>
</html>

Why the number is a variable

textContent returns a string. "10" + 1 is "101". If you read the heading and add one, you concatenate instead of counting. A let number cannot make that mistake.

render is the only place that touches the DOM. That makes later rules cheap: a minimum of zero, a step of five, a color change when the count is negative. Change the variable, then draw.

Common mistakes

  • Using const count = 0. You cannot reassign a constant. The plus button would throw.
  • Writing count = count++. Postfix increment returns the old value. The count never moves.
  • Parsing the heading with Number(display.textContent) as the source of truth. Keep a variable.
  • Attaching one listener to the card and guessing which button was clicked, before you can do that cleanly.
  • Forgetting to call render after reset. The variable is zero. The page still shows the old number.

Practice tasks

  1. Stop the count from going below zero. Minus on 0 should leave the display at 0.
  2. Add a Step field. Plus and minus add or subtract that number instead of 1.
  3. Turn the count red when it is negative and amber when it is zero. Preview at /javascript/try.

FAQ: JavaScript Project: Counter

Common questions about this page.

What is the StudyGrid JavaScript tutorial?

The StudyGrid JavaScript tutorial is a full beginner track: variables, functions, arrays, if/else, the DOM, events, storage, and fetch. Each chapter has copy-and-run examples.

Should I run javascript counter project examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn javascript counter project in this JavaScript JavaScript lesson (JavaScript Project: Counter).

Is the JavaScript editor the same as Try Python?

No. Try JavaScript is a live page plus a console at /javascript/try. Try Python stays at /try. JavaScript lessons never open the Python editor.

Do I need to install anything to learn JavaScript?

No. Open a chapter, click Try it in JavaScript, and the page and console update in the browser.

Where should I start the JavaScript tutorial?

Start at JavaScript Intro, then Where To, Output, and Syntax. After variables and functions, continue to the DOM and events. Use Next at the bottom of each chapter.

Is the JavaScript tutorial free?

Yes. The JavaScript studio on StudyGrid (studygrid.in) is free: dashboard, chapters, and the live editor.