DEV Community

Cover image for Beyond Custom Events: 9 Native Browser APIs Every Web Developer Should Know
Aamir saleem lone
Aamir saleem lone

Posted on

Beyond Custom Events: 9 Native Browser APIs Every Web Developer Should Know

So you just discovered CustomEvent in JavaScript and feel like a wizard? Get ready — the browser has a whole toolbox of magic you haven’t explored yet.

In my last post, we explored how CustomEvent and dispatchEvent let you build decoupled, modular web apps using your own events like user:loggedIn or pdf:uploaded.

But Custom Events are just the beginning.

The browser gives us built-in powers for observing, reacting, communicating, and scheduling — without any external libraries or frameworks.

Here are 9 other native APIs and patterns that’ll seriously level up your frontend game.


🔍 1. MutationObserverWatch the DOM like a spy

Want to react when someone adds a new element to the DOM? Or modifies attributes on the fly?

const observer = new MutationObserver((mutations) => {
  mutations.forEach((m) => console.log('DOM changed:', m));
});

observer.observe(document.body, { childList: true, subtree: true });
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Auto-refresh, syncing UI, building extensions, or watching 3rd party libraries change the DOM.


👁 2. IntersectionObserver

Know when elements enter the viewport

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      console.log('Visible:', entry.target);
    }
  });
});

observer.observe(document.querySelector('.lazy-image'));
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Lazy loading, infinite scroll, animations on scroll, analytics triggers.


🛰 3. BroadcastChannel

Communicate between tabs in real-time

const channel = new BroadcastChannel('notifications');
channel.postMessage({ type: 'LOGOUT' });

channel.onmessage = (e) => {
  console.log('Received in another tab:', e.data);
};
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Syncing logout/login, dark mode toggles, or notifications across browser tabs.


💡 4. Event Delegation

Efficiently handle dynamic elements

Instead of attaching listeners to every button:

document.body.addEventListener('click', (e) => {
  if (e.target.matches('.btn-delete')) {
    console.log('Delete clicked!');
  }
});
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Dynamic UIs (React-like), modals, dropdowns, or anything created via JS.


🧱 5. Web Components + Custom Elements

Create your own HTML tags

class MyAlert extends HTMLElement {
  connectedCallback() {
    this.innerHTML = `<div style="color:red">⚠️ ${this.getAttribute('text')}</div>`;
  }
}

customElements.define('my-alert', MyAlert);
Enter fullscreen mode Exit fullscreen mode
<my-alert text="This is a custom alert!"></my-alert>
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Design systems, reusable UI components, widget libraries.


⏱ 6. RequestIdleCallback

Schedule tasks when the browser is free

requestIdleCallback(() => {
  console.log('Non-critical task running');
});
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Preloading content, background caching, analytics pings — all without slowing the user down.


👀 7. Page Visibility API

Know when users leave or return to your tab

document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    console.log('User left the tab');
  } else {
    console.log('User is back!');
  }
});
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Pausing videos, deferring tasks, tracking engagement time.


📦 8. History API (pushState)

Navigate without reloading the page

history.pushState({ page: 2 }, 'Page 2', '/page2');

window.addEventListener('popstate', (event) => {
  console.log('User hit back/forward:', event.state);
});
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Single Page Apps, modals with URLs, breadcrumb-based navigation.


🧩 9. Subclassing EventTarget

Build your own event bus

class Emitter extends EventTarget {}
const bus = new Emitter();

bus.addEventListener('app:shutdown', () => console.log('Goodbye...'));

bus.dispatchEvent(new Event('app:shutdown'));
Enter fullscreen mode Exit fullscreen mode

🔧 Great for: Pub/Sub patterns, internal messaging systems, or micro frontends.


💥 Bonus: Combine These for Crazy Power

Imagine this:

  • A Web Component that lazy-loads images using IntersectionObserver
  • It fires a image:loaded CustomEvent
  • Other components react via an EventTarget-based bus
  • A MutationObserver updates layout when images appear

And it’s all vanilla JS. No React, no Vue, no jQuery.


🎯 Conclusion

These aren’t just random APIs — they’re tools that help you think like a system architect, not just a coder.

Whether you’re building small widgets or full-blown SPAs, these features let you:

  • React to change
  • Communicate cleanly
  • Schedule smartly
  • Stay lightweight

🧠 TL;DR – 9 Native Powers to Explore

Feature Use Case
MutationObserver Watch DOM for changes
IntersectionObserver Track element visibility
BroadcastChannel Cross-tab communication
Event Delegation Efficient event handling
Web Components Reusable custom elements
requestIdleCallback Background tasks
Page Visibility API Engagement tracking
pushState + popstate SPA routing
EventTarget subclass Custom event bus

✍️ You?

Have you used any of these in your project? Want a CodeSandbox showing them all together?

Let’s talk in the comments 💬

Top comments (0)