A Guide to Handling Browser Events

Sarah Chima on April 16, 2019

Cover Photo by Ambitious Creative Co. - Rick Barrett on Unsplash Most web pages are interactive and users can perform actions on the web page. ... [Read Full]
markdown guide

Thanks for the article, Sarah.
One question about the browser events bothers me for some time. You mentioned the third parameter useCapture when adding a listener to a DOM node. When readng fellow developers code sometimes I see boolean values true/false, sometimes objects {useCapture: true}. What's the difference between them? And what was the purpose to implement both options in browsers if there is no difference between them?


Sarah mentions it in the article. 😀

"The difference between bubbling and capturing is that in the bubbling phase, events propagate outwards. That is, the handler on the innermost element gets triggered first, then the parent all the way up.

In capturing, the reverse occurs. The handler on the outermost element is triggered first and then the child handler all the way down to the element where the event occurred. "


I mean there are two ways to add event listener in capture phase:

  1. node.addEventListener('click', e => console.log(e.eventPhase), true);
  2. node.addEventListener('click', e => console.log(e.eventPhase), {capture: true});

The result will be the same.
So my question was: is there any difference in these statements or they do exactly the same thing?

Hi Eugene.

They do exactly the same thing. true is a shorthand for {capture: true}.

Thanks for reading my article.

Ahh, sorry misunderstood what you were asking. 🙃 I believe Sarah just answered you.


Thanks for sharing.. Just want to add, using arrow function as eventListener callback will make the element lose the this context...

var span = document.querySelector('span');
span.addEventListener('click', (event) => {
   console.log(this); // Window Object

compared to this

var span = document.querySelector('span');
span.addEventListener('click', function(event) {
   console.log(this); // Element Object
   this.innerHTML = 'Hola';

Budy, sorry but I don't notice any difference in the two snippets ... maybe the latter should be a regular function declaration such as "function(event) {...}" ?
thank you, happy Easter!


Great explanation Sarah. Bubbling is so powerful because it allows you to reduce the potential number of events added to a page. Too many events can bog down a site.

I did a hello world in web components a couple of years ago, but haven't touched them since. Thanks for the refresher!

I'd just make one suggestion about adding event listeners. This is not web component specific, but for adding event listeners in general. In the case of the rainbow-text component, the number of <span />s increases for every additional letter in the text attribute, so the number of event listeners per instance of the component is n letters * 2 (mouse over + animation end events).

You can end up with a lot of events very quickly just for one instance of the component. What you can do is add an event listener for each event type on the parent <div /> you create in aspittel/rainbow-word-webcomponent and then the power of event bubbling is your friend.


class RainbowText extends HTMLElement {

  addEventListeners(div) {
    div.addEventListener("mouseover", e => {
      const { target } = e;

      if (target.tagName === "SPAN") {
        console.log(`mousing over ${target.tagName}`);

    div.addEventListener("animationend", e => {
      const { target } = e;

      if (target.tagName === "SPAN") {
        console.log(`mousing over ${target.tagName}`);


  render() {
    const div = document.createElement("div");

This is a great overview, thank you Sarah! Always love to see great vanilla JS resources.


thank you, Sarah. simple and clear. have nice days

code of conduct - report abuse