Skip to content

Click Events

The click event fires on any element when the user clicks or taps it. It is the most common event you will attach, and it is the foundation of the STO hamburger nav toggle.

const btn = document.querySelector('.hamburger-btn');
btn.addEventListener('click', (event) => {
console.log('clicked');
});

The browser passes an event object as the first argument to every handler. You can name it event, e, or anything — event is the clearest.

PropertyWhat it is
event.targetThe element that was actually clicked
event.currentTargetThe element the listener is attached to

These differ when clicks bubble up through nested elements:

const card = document.querySelector('.tour-card');
card.addEventListener('click', (event) => {
console.log(event.target); // could be the h3, p, or button inside the card
console.log(event.currentTarget); // always the .tour-card element
});

event.target tells you exactly what was clicked. event.currentTarget tells you where the listener lives. You will use this distinction in Module 06 event delegation.

Some elements have built-in browser behavior on click:

  • <a> navigates to its href
  • <button type="submit"> inside a form submits the form
  • Checkboxes toggle their checked state

event.preventDefault() stops that default behavior:

const link = document.querySelector('.tour-card a');
link.addEventListener('click', (event) => {
event.preventDefault(); // stops navigation
console.log('link clicked, navigation blocked');
});

Use preventDefault() when you want to handle the action yourself — most commonly on form submit events.

Events bubble up the DOM tree — a click on a button also fires on its parent, grandparent, and so on. stopPropagation() stops that bubble:

const btn = document.querySelector('.inner-btn');
btn.addEventListener('click', (event) => {
event.stopPropagation(); // click will not reach parent listeners
console.log('button click handled here only');
});

You rarely need stopPropagation() in straightforward code — event delegation (Module 06 L05) is usually the better approach. Reach for it only when a nested click is being incorrectly captured by a parent listener.

The most common click pattern: toggle a class on every click, letting CSS handle both states:

const nav = document.querySelector('.site-nav');
const btn = document.querySelector('.hamburger-btn');
btn.addEventListener('click', () => {
nav.classList.toggle('nav-open');
});

One handler, one line, handles open → closed → open automatically. The CSS for .nav-open defines what the open state looks like.

This is the first complete, shipped feature on the STO site. Wire the hamburger button to toggle the mobile navigation:

const hamburgerBtn = document.querySelector('.hamburger-btn');
const nav = document.querySelector('.site-nav');
if (hamburgerBtn && nav) {
hamburgerBtn.addEventListener('click', () => {
nav.classList.toggle('nav-open');
});
}

Add the code above to main.js, save, and reload index.html at a narrow viewport:

  1. Click the hamburger button — the nav should open
  2. Click again — the nav should close
  3. Repeat several times to confirm the toggle works in both directions

The CSS for .nav-open was written in CSS Foundations M08 L02, so the nav should visually show and hide on every click. Module 07 builds the production-ready version with accessibility and outside-click handling on top of this foundation.

  • element.addEventListener('click', handler) fires on click or tap.
  • event.target is the element actually clicked; event.currentTarget is the element with the listener — they differ when clicks bubble through nested elements.
  • event.preventDefault() stops built-in browser behavior (navigation, form submit).
  • event.stopPropagation() stops the event from bubbling to parent listeners — use sparingly.
  • The toggle pattern: classList.toggle('class') in a click handler handles both open and close in one call.
  • The STO hamburger nav uses classList.toggle('nav-open') on the nav element — the first complete interactive feature.