CSS :near Pseudo-class: Smarter UI Without JavaScript Hacks

The CSS Working Group recently received a proposal for the CSS :near pseudo-class, and honestly, it is one of those features that makes you wonder why we are still faking this with JavaScript in 2025. If you have ever tried to trigger a UI change before the user actually touches an element, you know the struggle. We usually end up calculating Euclidean distances in a pointermove listener, which is a performance bottleneck waiting to happen.

Thomas Walichiewicz proposed this new selector to allow elements to match when a pointer is within a specific range. Specifically, the syntax would look something like button:near(3rem). Consequently, this would trigger styles when the user is “close enough” but hasn’t committed to a hover or click yet.

The Performance Cost of the Current “Near” Logic

Currently, if a client asks for a “magnetic button” or a menu that reveals itself as the cursor approaches, we reach for JavaScript. We hook into the mouse position and run math on every frame. Furthermore, this often leads to layout thrashing if not handled with extreme care. Specifically, here is the kind of boilerplate we are currently forced to write:

// The expensive way to detect proximity
document.addEventListener('pointermove', (e) => {
  const rect = element.getBoundingClientRect();
  const x = e.clientX - (rect.left + rect.width / 2);
  const y = e.clientY - (rect.top + rect.height / 2);
  const distance = Math.sqrt(x * x + y * y);

  if (distance < 100) {
    element.classList.add('is-near');
  }
});

This approach is fragile. It doesn’t respect the browser’s paint cycles unless you wrap it in requestAnimationFrame, and it’s a nightmare for accessibility. If you’re interested in reducing JS overhead, you might also want to check out how to stop JS scroll bloat with CSS sibling-index().

Practical Use Cases for the CSS :near Pseudo-class

The most immediate benefit of the CSS :near pseudo-class is reducing visual clutter. Imagine a high-density dashboard where every button has an icon. Showing 50 icons at once is overwhelming. However, using :near(), we could fade those icons in only when the user’s intent is clear. This is much smoother than :hover, which feels abrupt because it only triggers at the last millisecond.

Another “war story” use case: the invisible hit area. We have all tried the trick of adding massive transparent padding to a button to make it easier to click. While effective, it ruins the layout flow. With the proposed selector, we can keep the button’s physical dimensions small while expanding its interactive “gravity” natively.

Hiding Elements Until They Are Needed

Hiding elements until a user is nearby is great for UX, but it usually breaks “find-in-page” (Cmd+F). To solve this, we can use a combination of hidden="until-found" and content-visibility. Specifically, when combined with contain-intrinsic-size, we can reserve space for an element before it even renders.

/* Proposed native approach */
button {
  content-visibility: hidden;
  contain-intrinsic-size: auto 40px; /* Reserve height */
}

button:near(3rem) {
  content-visibility: visible;
  opacity: 1;
}

This ensures the browser knows the element exists and takes up space, but doesn’t waste resources painting it until the pointer gets close. For more on modern accessibility patterns, see my guide on implementing CSS contrast color approximation.

Technical Concerns: Fingerprinting and Privacy

As a dev who has handled security audits, I have to point out the elephant in the room: privacy. A selector like :near() could theoretically be used for “heatmapping” without user consent. By nesting multiple :near() ranges, a malicious script could track cursor movement across the screen via CSS transitions alone. This is likely why the W3C proposal includes strict discussions on thwarting these abuses.

Look, if this CSS :near pseudo-class stuff is eating up your dev hours, let me handle it. I’ve been wrestling with WordPress since the 4.x days.

Native Proximity is the Future

Ultimately, shifting proximity logic from JavaScript to the browser’s C++ engine is a win for performance. It follows the trend of “Interest Invokers”—browser APIs designed to handle hover and focus intent with less code. While we wait for browser vendors to ship this, keep using the padding-container hack as a workaround, but keep your logic clean. We are moving toward a web where the “feel” of an interface is handled by the stylesheet, not a 50kb script.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.

Leave a Comment