Skip to Content
Make a Button Do Something With addEventListener
Beginner
0 likes
Tutorials

Make a Button Do Something With addEventListener

Find the button, attach a listener, change something on the page when it's clicked. Three steps, and two mistakes that make it silently do nothing.

You want a button that does something when it's clicked. It takes three steps: find the button, attach a listener, change something in the listener. Then there are two mistakes that make it silently do nothing, and you'll probably make one of them at least once. Let's do it properly.

Skip ahead: If your button already works and you're here because it doesn't, jump to "It does nothing: check these first".

The page

Save this as index.html, with a script.js next to it:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Counter</title>
</head>
<body>
  <p>Cups of coffee today: <span id="count">0</span></p>
  <button id="add" type="button">Add a cup</button>
  <button id="reset" type="button">Reset</button>
  <script src="script.js"></script>
</body>
</html>

The script tag is at the end of <body>, so the buttons exist when the script runs. That one detail prevents the most common problem.

Step 1: Find the button

const addButton = document.querySelector("#add");
const resetButton = document.querySelector("#reset");
const countEl = document.querySelector("#count");

#add means "the element with id add". If you used a class, it would be .add.

Step 2: Attach a listener

let count = 0;

addButton.addEventListener("click", () => {
  count++;
  countEl.textContent = count;
});

addEventListener takes the event name and a function. The browser calls the function every time the button is clicked. Nothing inside runs until then.

Step 3: Change something on the page

That's the countEl.textContent = count; line. The page shows the new number. Add the reset button the same way:

resetButton.addEventListener("click", () => {
  count = 0;
  countEl.textContent = count;
});

Here's the whole script.js:

const addButton = document.querySelector("#add");
const resetButton = document.querySelector("#reset");
const countEl = document.querySelector("#count");

let count = 0;

function render() {
  countEl.textContent = count;
  resetButton.disabled = count === 0;
}

addButton.addEventListener("click", () => {
  count++;
  render();
});

resetButton.addEventListener("click", () => {
  count = 0;
  render();
});

render();

The render function keeps "what the page shows" in one place. Both buttons change count, then call it. As the page grows, that saves you from updating the same element from five places and forgetting one.

It does nothing: check these first

Open the console (F12) before anything else. Then go down this list.

1. Red error "Cannot read properties of null (reading 'addEventListener')". querySelector found nothing. The id is misspelled, you used . for an id or # for a class, or the script runs in the <head> before the button exists. Fix the selector, or move the script to the end of <body>, or add defer: <script src="script.js" defer></script>.

2. No error, and nothing happens. You probably called the function instead of passing it:

addButton.addEventListener("click", addCup()); // wrong: calls it now
addButton.addEventListener("click", addCup);   // right: passes it

The first line runs addCup once, immediately, while the page loads, and attaches whatever it returns (usually undefined). The second line is right: pass the function, don't call it.

⚠ Warning: A button inside a <form> is a submit button by default. Clicking it submits the form and reloads the page, so your change flashes and disappears. Add type="button" to buttons that aren't meant to submit, like in the HTML above. If it is a form, listen for submit on the form and call event.preventDefault().

3. It works, but runs twice (or more). You attached the listener more than once, often by putting addEventListener inside another listener or inside a function that runs repeatedly. Attach listeners once, when the page loads.

4. Wrong file. The console shows 404 for script.js, or your changes aren't showing. Check the file name and folder, save, and reload.

Using the event object

The function gets an event with details. event.target is the element that was clicked. That lets one listener handle many buttons:

<div id="sizes">
  <button type="button" data-size="S">Small</button>
  <button type="button" data-size="M">Medium</button>
  <button type="button" data-size="L">Large</button>
</div>
<p id="picked">No size picked</p>
document.querySelector("#sizes").addEventListener("click", (event) => {
  const size = event.target.dataset.size;
  if (!size) return;
  document.querySelector("#picked").textContent = `Size: ${size}`;
});

dataset.size reads the data-size attribute. The if (!size) return; ignores clicks on the gaps between buttons.

💡 Tip: Use a real <button> for things that do something, not a <div> with a click listener. A button can be reached with the Tab key, works with Enter and Space, and screen readers announce it. A clickable div does none of that unless you add it all yourself.

Common mistakes

  • addEventListener("click", fn()) instead of fn.
  • Script in the <head> without defer.
  • Forgetting type="button" inside forms.
  • "onclick" as the event name. The event is "click". onclick is the old attribute.

Now try it: add a "Remove a cup" button that never lets the count go below zero. Where does the check go?

About

Wire up a button with querySelector and addEventListener, update the page on click, and fix the usual reasons nothing happens. After this, your button actually does something.

Responsible
Mary Q
Last Update
08/28/2026
Reading Time
5 min
Was this helpful?
​ 0 ​ 0

Comments (0)

Sign in to comment

No comments yet.