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. MutationObserver – Watch 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 });
🔧 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'));
🔧 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);
};
🔧 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!');
}
});
🔧 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);
<my-alert text="This is a custom alert!"></my-alert>
🔧 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');
});
🔧 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!');
}
});
🔧 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);
});
🔧 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'));
🔧 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)