I was auditing a client’s WooCommerce site last week, standard stuff, or so I thought. They were complaining about inputs jumping around on mobile and a JavaScript bundle that seemed to exist only to manage form field heights. Under the hood I found a tangle of ResizeObserver logic whose entire job was making a textarea grow with its content. It was brittle, it felt slow, and nobody wanted to touch it.
My first move was to refactor their JS helper and tune the debounce logic. That cost me an hour of fighting race conditions before I accepted that I was solving a problem which no longer exists. The Modern CSS Features that landed in the last round of web platform updates handle these “complex” UI behaviors natively. I should have deleted the helper instead of tuning it, and it is a relief to see how much bloat goes out with it.
Ditching JavaScript for native solutions
The biggest win this year, for me, is field-sizing: content. We spent years loading libraries to make inputs auto-expand and now it is one line of CSS. Writing JS for it today only adds technical debt. Chizaram Ken wrote about reducing reliance on JavaScript recently and I think he is right. As the browser picks up more of this work, our code can get leaner.
Input fields are not the whole story. ::target-text lets you style the text fragment a reader arrived at from a search result or a shared URL. WebKit pointed out that it is supported across all the major browsers now. It is a small thing, and small native details like it are the difference between a site that feels “fast” and one that is merely “functional.”
Scoped styling with @scope
The one I keep coming back to is @scope, and I think it changes how we build WordPress themes. I have written before about how WordPress development can break your CSS when global styles collide. @scope gives you a native way to isolate styles to one DOM subtree, with none of the overhead of Shadow DOM and none of the specificity wars of BEM.
/* bbioon-theme scoped styling example */
@scope (.bbioon-product-card) {
:scope {
border: 1px solid #eee;
padding: 1rem;
}
img {
border-radius: 8px;
/* This only affects images inside the card */
}
}
In WordPress, where you are constantly mixing core blocks with custom components, that matters a lot. It removes the reason for the z-index and specificity hacks most of us have committed at 3 AM. If styles keep leaking into places they should not reach, this is the fix. I go further into it in modern CSS beyond JS bloat.
New browser toys: invoker commands
Invoker Commands (command and commandfor) also have baseline support now. You can toggle dialogs and popovers without attaching a single JS event listener, which helps both accessibility and performance. It is declarative and it ships with the browser. Read it alongside the HTMHell Advent Calendar and you start noticing how much plain HTML we skipped over in favor of frameworks.
I understand how we got here. We spent a decade solving everything with JavaScript because there was no other option. The platform has caught up since. If your site feels heavy, or your CSS is a 5,000-line pile of !important, you are probably fighting the platform instead of using it.
This gets complicated fast. If you are tired of debugging someone else’s mess and you want the site running on modern standards, drop me a line. I have probably seen your version of it, and I know what to delete.
The bottom line
- field-sizing: deletes the auto-growing input JS.
- @scope: ends the specificity wars inside custom blocks.
- Invoker Commands: native control over dialogs and popovers.
- ::target-text: a small improvement for anyone arriving from a shared link.
Greetings! I’ve been following your web site for a while now and finally got the bravery to go ahead and give you a shout out from Porter Texas! Just wanted to tell you keep up the excellent job!
Thank you, Johnny.
Happy to hear you like my writings 🎉