I recently inherited a WooCommerce project, a high-end fashion boutique, where the mobile experience was frankly awful. The previous dev had built a “bespoke” product variation selector and three separate sliders out of heavy JavaScript libraries plus some shaky IntersectionObserver logic. Every scroll felt like the page was dragging a ball and chain, and choosing a size choked the main thread for 200ms while a custom dropdown re-rendered.
My first instinct was to optimize the JavaScript that was already there. Debounce the scroll events, push some of the heavy lifting into requestIdleCallback, that sort of thing. It was the wrong call. The problem was structural and I was taping over it, while the actual fix sat in the recent Chrome releases. Modern CSS logic now handles state and interaction natively, which means a lot of that JavaScript is work the browser will do for you.
Native selects you can actually style
For years we reached for Select2 or Choices.js because a native <select> element could not be styled. The “CSS Wrapped 2025” report confirms that appearance: base-select has landed. You can style the button, the picker and the rich content inside options without breaking accessibility or shipping 50kb of JavaScript to get there.
/* bbioon native select styling */
select {
@supports (appearance: base-select) {
&, &::picker(select) {
appearance: base-select;
background-color: var(--bbioon-bg);
border-radius: 8px;
}
}
}
On that boutique project, switching to a native customizable select cut nearly a full second off Time to Interactive on product pages, and a second is the difference between a bounce and a sale. Being able to use <selectedcontent> to clone rich icons straight into the button keeps the UI consistent too.
Native carousels without a slider library
Clients love carousels and developers mostly resent the technical debt that comes with them. ::scroll-marker and ::scroll-button() change that. Navigation dots and arrows can be built in CSS alone, wired natively to the scroll container, and they keep their built-in keyboard behavior. You no longer have to work through the Slick or Swiper.js API just to change the color of a dot.
Smashing Magazine went through all of this recently and it is worth reading. A CSS slider is more efficient for a fairly boring reason: the browser handles the scroll-linking on the compositor thread, which leaves the main thread free for the logic that actually matters, like your checkout flow.
Asking CSS whether an element is stuck
You can now query whether an element is stuck or snapped without writing a line of JavaScript. Anyone who has tried to add a shadow to a header only while it is stuck to the top remembers how awkward the old IntersectionObserver workarounds were. With container-type: scroll-state, the browser tells you directly.
.bbioon-sticky-header {
container-type: scroll-state;
position: sticky;
top: 0;
header {
transition: box-shadow 0.3s ease;
@container scroll-state(stuck: top) {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
}
}
There are also if() statements and tree-counting functions such as sibling-index(), which let you stagger animations or do layout math inside the stylesheet. Calling that visual sugar undersells it, because the logic ends up somewhere far easier to maintain.
What this changes in practice
Moving logic out of JavaScript and into CSS leaves fewer moving parts, so less of the site breaks when a browser updates or two plugins disagree. If your current build feels slow, the likely reason is that it is still doing work in JavaScript that the browser now does for free.
- Native features run on threads the browser has already optimized.
- Less code to debug means fewer billable hours spent nursing an old slider.
- Keyboard navigation for selects and sliders comes built in.
Mixing modern CSS with legacy WooCommerce templates is where this gets fiddly fast. If you would rather someone else untangle that instead of spending your own week on it, drop my team a line.
If your UI states still run through JavaScript, it is worth checking how much of that CSS can take over now.