I love writing philosophical essays — thoughts about code, work, all that stuff. I also love deep technical dives. But I know you love my lists of cool features that not everyone has heard about yet 😄
What’s up with me? This week I’m preparing for a conference, fighting performance issues, and trying to get at least somewhat ready for the upcoming holidays 😉
Something nice happened too. I enjoy writing — not just technical articles, but in general. Last summer my life changed quite a bit, and to keep my sanity I started writing a sci-fi story, which I submitted to a Polish science fiction foundation competition. I didn’t win, but my story made it pretty far — around 13th place out of 179 submissions. Considering it was my first attempt at this kind of writing… it could have gone worse 😄
And speaking of sci-fi — the kind happening right in front of us 😉 Today I’ve prepared a batch of things the browser can already do, which honestly didn’t fit in my head not that long ago. A lot of these are still not that widely known, and yet many of them are already supported across modern browsers. Have fun!
1. “Let me just run this later” → requestIdleCallback
At first I thought this API was pointless. It basically lets you run some code when nothing interesting is happening. Ok… cool… but why would I care?
Turns out — there are tons of use cases. For example, collecting data about how the user behaves on your page — definitely not something you want to do while your 200 components are rendering 😅 Or loading less important data, preprocessing something, generating images in the background.
Honestly, there are probably as many use cases as there are developers.
function trackUserScrolling() {
console.log("User scrolled. This changes everything.");
}
if ("requestIdleCallback" in window) {
requestIdleCallback(trackUserScrolling);
} else {
setTimeout(trackUserScrolling, 0);
}
Support: modern browsers (historically missing in Safari, so fallback is still a good idea)
2. “Why is my input not highlighting???” → :focus-within
It’s easy to style an element that has focus. But what if you want to style the parent div? For example, make it pink, add some flowers 😉 You can write 40 lines of JavaScript… or just use :focus-within.
Works. No listeners. No bugs. No suffering.
.form-field {
border: 1px solid #ccc;
padding: 12px;
}
.form-field:focus-within {
border-color: hotpink;
}
<div class="form-field">
<input placeholder="Type something meaningful..." />
</div>
Support: basically everywhere that matters
3. “Let’s show offline mode” → navigator.onLine
Have you ever built a PWA? Because I have, and the eternal problem is what to do when the user loses connection (e.g. they’re in the wilderness or just walked into an elevator 😄). You can write a bunch of complicated ifs, or just listen to offline and online. On offline you can store data in IndexedDB, and when the user is back online, send it to the server.
window.addEventListener("offline", () => {
alert("You are offline. Time to panic.");
});
window.addEventListener("online", () => {
alert("You're back. Panic cancelled.");
});
Support: widely supported (but “online” ≠ “your backend works” 😅)
4. “Smooth animation, but make it cursed” → requestAnimationFrame
We’ve all seen this:
setInterval(() => {
element.style.left = Math.random() * 100 + "px";
}, 16);
You can feel this is not the best idea 😉 It just lags. Luckily we have requestAnimationFrame, which is synced with the browser repaint cycle, so things are actually smooth.
function animate() {
element.style.transform = `translateX(${Date.now() % 300}px)`;
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
Support: everywhere
5. “This card should adapt… but only here” → container queries
This feature feels almost unfair. I’m at a point in my career where I barely write CSS anymore (well, except for occasional moments like the one I described here: Is learning CSS a waste of time in 2026?).
But there was a time when I wrote a lot of it. And wow — how much I would have given to apply media queries to a specific element instead of the whole viewport. Now we finally can. The component becomes self-aware, and we can go grab a coffee.
.card-wrapper {
container-type: inline-size;
}
.card {
display: grid;
}
@container (min-width: 400px) {
.card {
grid-template-columns: 1fr 2fr;
}
}
Support: modern browsers (add fallback if needed)
6. “Random ID, what could go wrong?” → crypto.getRandomValues
const id = Math.random().toString(36).slice(2);
This is how bugs are born. It looks like “good enough” crypto from AliExpress and works… until it doesn’t. First of all, it depends on the engine implementation — we don’t really know what’s happening under the hood. Some patterns are absolutely possible, and with enough IDs you’re basically asking for duplicates.
Luckily, we now have a simple native solution. It’s not a silver bullet, but crypto.getRandomValues is pretty solid — much better entropy, no weird patterns, dramatically reduces the chance of collisions. The browser just does it properly.
const bytes = new Uint8Array(8);
crypto.getRandomValues(bytes);
const id = Array.from(bytes)
.map(b => b.toString(16).padStart(2, "0"))
.join("");
console.log("Secure-ish ID:", id);
Support: widely supported
7. “We need a modal” → <dialog>
It’s honestly nice that browsers finally stepped up and said: fine, here’s your modal 😄 No more installing 12KB libraries just to open a dialog that users love so much. This one is also accessible by default, so win-win.
<dialog id="modal">
<p>Are you sure you want to deploy on Friday?</p>
<button onclick="modal.close()">Cancel</button>
<button onclick="alert('Good luck 😬')">Deploy</button>
</dialog>
<button onclick="modal.showModal()">Open modal</button>
Support: modern browsers
8. “Voice input would be cool…” → Speech API
Are you already installing transformers.js because you need speech recognition? Relax — turns out the browser has something for that too. Well… at least Chromium does 😄 So if you can “encourage” users to use Chrome, Edge, or something similar, you’re good. Personally, I’d still be careful with production use, but for demos? Why not.
const SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
if (SpeechRecognition) {
const recognition = new SpeechRecognition();
recognition.onresult = e => {
console.log("You said:", e.results[0][0].transcript);
};
recognition.start();
}
Support: mostly Chromium
9. “Will this CSS explode?” → @supports
Here’s a modern solution to the classic “it works on my machine” — at least in CSS 😉 You don’t have to guess whether something will break your layout. Just wrap it in @supports. There is a small catch — while support is very good, it’s not literally everywhere, so ironically… we could use @supports for @supports.
.card {
background: white;
}
@supports (backdrop-filter: blur(10px)) {
.card {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.6);
}
}
Support: very good
⚠️ But don’t get me wrong
Libraries are great. Sometimes you absolutely need them. But sometimes… you’re installing a dependency for something the browser solved years ago. Before installing anything, just ask yourself (or Google): “Is the browser already smarter than me here?” Sometimes the answer is yes. And that’s… perfectly fine 😄
Top comments (99)
Casually mentioning that you almost won a national sci-fi competition right before diving into native browser APIs is an incredible flex. I am genuinely impressed by that combination of skills. 🥳
The technical list is spot on. The amount of heavy dependencies I have seen installed just to replicate that exact native dialog behavior is depressing. Also, your offline mode panic alert logic is exactly the kind of architecture the web needs more of.
Good luck with the conference this week. Try not to let the performance issues keep you up writing code all night. We both know exactly where that leads. Get some actual rest before the holidays, and let me know how the presentation goes. 😃
Haha, of course my first reaction was: “well… that’s a failure” because it wasn’t one of the top spots 😄 But after a moment I was like… hmm, maybe that’s actually not bad at all 😄
And thank you! The conference is exactly a week from now, so it’s the final stretch now!
Only a developer could beat out over a hundred and sixty other writers on their very first attempt and instinctively classify it as a failure. That exact brand of relentless perfectionism is probably why your technical work is so solid, but you have to admit it is a completely ridiculous standard to hold yourself to. You should absolutely just own that success. 😄
Good luck with the final stretch of preparations this week. Just try to resist the urge to rewrite your entire presentation the night before. By the way, is the conference going to be streamed anywhere? Let me know if there is a link. I would really like to tune in and watch you present.😊
Haha, you’re probably right about that 😄
As for the conference, it most likely won’t be streamed live, but it should be uploaded to YouTube afterward, so I’ll definitely share the link once it’s out! 😊
Wow the times os going ower my head, I don't know about voice input is aviable in browser.
( my Mac is know that by douple press fn by default)
Haha yeah, it’s one of those features that feels a bit like sci-fi creeping into everyday life 😄
You’re right though, the support is still a bit limited and not something you’d rely on everywhere in production yet. But things like what you mentioned on macOS show exactly where this is heading.
Feels like we’re slowly moving toward voice being just another normal input method in apps 👀
Cool article, but this is only the tip of the iceberg - the native browser/web APIs have become so extensive, most devs know only a tiny bit of what's available (to a large extent because they use frameworks like React to program the frontend) ...
What do you think of the idea (and feasibility) to not use React or other frameworks to build a frontend, but only "custom elements" (the preferred contemporary name for "web components", I've learned) and native browser APIs - is it a realistic alternative?
That’s a great question!
If I had to answer quickly, I’d say: probably not as a full replacement in most cases. Frameworks solve a lot of problems for us, they come with mature ecosystems, component libraries, state management patterns, routing, etc. So they’re not bad at all. The real issue is more that developers tend to overdo it with additional libraries on top of them.
That said… I’ve actually been thinking about this more recently, and I’m not so sure anymore, especially for simpler apps. With custom elements and modern browser APIs, you can go surprisingly far without a framework. So maybe it’s not about replacing frameworks entirely, but being more intentional about when we actually need them.
Great take, excellent - this:
"Maybe it’s not about replacing frameworks entirely, but being more intentional about when we actually need them"
That's exactly the gist of this article which I just came across:
blog.logrocket.com/anti-frameworki...
So yeah, native web APIs and 'custom elements' are not the holy grail, neither are frameworks - each has its place ...
And this one:
"The real issue is more that developers tend to overdo it with additional libraries on top of them"
Yes, we're way too 'easy'/lazy pulling in tons of dependencies even when we don't really need them, also for trivial things - which has drawbacks, and risks:
a16z.news/p/et-tu-agent-did-you-in...
But, if you rely on AI coding tools/agents - they tend to favor ... React:
dev.to/krunal_groovy/vue-vs-react-...
So you need to make a conscious choice, and maybe you need to put in a little bit more effort ...
Wow, that’s a lot of great content, saved! 🙌
As for preferring React, that doesn’t surprise me at all. It’s simply the most popular, so AI was probably trained on it the most. And of course, it’s often a good choice — I like React too, but not always.
At work, for my large enterprise project, we use Angular — and I really appreciate it. It’s stable, a lot of things work out of the box, and I’ve been blissfully avoiding vulnerability dramas for years 😄
That said, I do worry a bit that with AI we’ll see less actual thinking and more defaulting to whatever is suggested. I’m a bit afraid we’ll end up with very “cemented” tech choices. I’ve actually been meaning to write a post about this for a month now… but haven’t found the time yet 😅
Thanks! Yes that's my fear as well, that everything will a bit more "canned" and run-of-the-mill !
I am seriously of the opinion, among all the AI "hype", that it wouldn't be a bad thing if some development is still done "the old-fashioned way", if only as an antidote, or no, let me make that more specific:
These are really great ideas 🙌 I especially like the angle of keeping the “craft” alive — not everything has to be automated, some things are just genuinely fun to build.
And your last point actually reminded me of something a friend of mine does. She noticed that AI can sometimes go in completely the wrong direction, so now she always asks it to provide not just one solution, but also 2–3 alternatives. It’s surprisingly effective.
I’ve had similar situations myself — the LLM would suggest adding 10 files and building some complex structure, and when I asked “can this be simpler?”, it suddenly turned out that… yes, it can, and it’s just one extra line 😄
"now she always asks it to provide not just one solution, but also 2–3 alternatives" - nice one, need to remember that!
The
<dialog>one hits hard. I recently audited a site where the modal library alone added 14KB gzipped to the bundle — for something the browser does natively with better accessibility out of the box.The
loading="lazy"point is especially relevant for anyone running image-heavy pages at scale. I manage a site with thousands of pages across 12 languages and switching from a JS lazy-loading library to nativeloading="lazy"shaved ~200ms off LCP on mobile. That's the kind of win that directly impacts Core Web Vitals scores.Would love to see a follow-up on native CSS features that replace JS too —
scroll-snap,container queries, and@layerhave quietly eliminated a lot of JS-heavy patterns.Thanks a lot! 🙌 And that CSS-focused follow-up is a great idea, there’s definitely a lot to explore there 😄
Right? The CSS side is where most of the hidden bloat lives. I've seen projects pulling in entire utility frameworks just for a handful of layout patterns that
gridandhas()handle natively now. Would love to see someone benchmark the real-world performance delta between CSS-native approaches and popular UI kits.Haha true, that would be super interesting to see 😄 I’d love to see real numbers comparing CSS-native approaches vs full UI kits in real-world apps.
Would be a fascinating benchmark! On one of my projects I went Tailwind-only (no component library) for a data-heavy site with 100K+ pages — the CSS output is surprisingly small because utility classes deduplicate naturally at scale. The entire site ships under 30KB of CSS gzipped.
The hidden cost with full UI kits isn't just bundle size though — it's the cascade of JavaScript that comes with interactive components you probably don't need. A datepicker here, a modal there, and suddenly you're shipping 200KB of JS for what's essentially a static content site.
Would love to see someone do a Lighthouse comparison: same layout built with Tailwind vs MUI vs Chakra. My bet is the Tailwind version wins on CLS and LCP by a noticeable margin on mobile.
The
requestIdleCallbackexample is a good opener — it's one of those APIs that solves a real problem (deferring non-critical work without blocking the main thread) that most developers reach for a setTimeout hack to approximate.A few others worth adding to the "browser already solved it" list: the Intersection Observer API (replaces hand-rolled scroll listeners for lazy loading and animation triggers), the View Transitions API for page transition animations that most people build with JavaScript frameworks, ResizeObserver for element-level resize detection (no more polling or window resize hacks), and
dialogelement withshowModal()for accessible modals without a single line of focus-trap JavaScript.The pattern across all of these is the same: they exist because the browser vendors watched what developers were hacking together repeatedly and standardized the good version. The bottleneck is usually awareness — most developers don't audit their dependencies against the platform periodically. Worth doing annually.
Exactly this 🙌 I’ve actually written about some of these in my previous articles — things like Intersection Observer or ResizeObserver are such good examples of “the browser already solved it.”
I also really like the idea of doing a yearly audit. That’s honestly something more teams should consider. The problem is, we’re often tied to a specific UI library, and then it’s up to them whether they keep up with modern browser capabilities or not.
And I’ve definitely seen some “genius” cases where datepickers still use Moment.js… even though the Moment docs themselves say not to use it anymore 😄
again awesome article, Sylwia. thanks
How was your conference, i hope all was as you expected.
Thanks a lot! 😊 The conference is actually this Thursday, so it’s still ahead of me — a mix of excitement and mild terror at this point 😄
I am sure it will be fine, I would like to read your observations and experience afterwards, if you like.
Good luck and have fun.
requestAnimationFrameis great. You probably can skip theDate.now()part. The callback receives a timestamp as the first argument: developer.mozilla.org/en-US/docs/W...Good catch, you’re right! Thanks for the clarification 🙂
Honestly, I'm still wrapping my head around the idea of container queries - it sounds like a total game changer for layout management. Saving this!
Exactly! 😄 It really is a game changer. Such a shame I barely write CSS anymore these days 😅
The
requestIdleCallbackpoint really resonated. I run a static site with 100K+ pages built on Astro, and one of the biggest performance wins was deferring analytics and non-critical JS to idle time instead of loading it eagerly. Shaved nearly 200ms off LCP on mobile.The
:focus-withinone is also underrated — I used to write custom JS for that exact pattern on form containers. Replacing it with a single CSS pseudo-class was one of those "why didn't I know this earlier" moments.Curious if you've looked into the
Speculation Rules APIfor prerendering? That's another browser-native feature that replaces a lot of custom prefetching logic and has massive implications for perceived navigation speed.That’s a really nice win — shaving ~200ms off LCP just by deferring non-critical work is exactly the kind of improvement that actually matters in real apps 🙌
And yes, :focus-within is one of those “why did I ever write JS for this” moments 😄 I had the same reaction.
As for the Speculation Rules API — I’ve looked into it a bit, but haven’t used it in a real project yet. It definitely feels like another one of those features that can replace a lot of custom logic once it matures. The whole idea of letting the browser handle prerendering heuristics is super interesting. Have you used it in production already?
Haven't deployed it in production yet either, but it's high on my list. For a static site with predictable navigation patterns (stock page → sector page → related stocks), the prerender hints would map really cleanly to user intent. The part I'm most interested in is replacing the prefetch-on-hover JS I currently use — letting the browser handle that natively with better resource management feels like the right direction. Definitely one to watch as browser support expands.
I like
requestIdleCallback. I read about a pattern you can implement with it: idle-until-urgent:There are some expensive calculations required for some function the user is likely to invoke. Instead of doing it once it is required, you can do it once you have time for it. Basically pre-caching.
But: when the result is required before the work was done, you cancel the callback and do it just-in-time.
Exactly this! It’s such a beautiful pattern. Idle-until-urgent really changes how you think about work scheduling in the browser. Instead of “do everything immediately”, it becomes “do it when it makes sense… unless the user needs it now”.
Feels like a small thing, but it actually shifts your whole mental model of what the browser can handle for you today.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.