[csswg-drafts] [selectors] Proposal: :near(<length>) pseudo-class for pointer proximity (“pre-hover” styling) (#13271)

twalichiewicz has just created a new issue for https://github.com/w3c/csswg-drafts:

== [selectors] Proposal: :near(<length>) pseudo-class for pointer proximity (“pre-hover” styling) ==
## Introduction
Designers often want “pre-hover” affordances: reveal controls, brighten icons, or show hints when a pointing device approaches an interactive target—common in physical UIs. On the web, doing this robustly typically requires JS (`pointermove`) and custom hit-testing/geometry, which is heavy for a simple threshold effect and hard to integrate with the cascade.

**Examples / use cases**
- Reveal a toolbar when the pointer approaches a container (without requiring the container to be hovered yet).
- Increase contrast/brightness of small icon buttons as the pointer nears them, improving discoverability.
- Display contextual hints (“Drag to reorder”) when approaching a handle.

## Proposal
Add a functional pseudo-class that matches elements when the active pointing device* is within a given distance of the element. On devices without hover-capable pointers, `:near()` never matches.

*_In this proposal, "active pointing device" is the UA’s primary hover-capable pointing device (if any)._

### Syntax
```css
button:near(200px) { outline: 1px solid; }
```

This is intended as a boolean threshold (“inside/outside”) rather than exposing continuous pointer coordinates.

**Open question:** Is the argument exactly `<length>` (including `calc()`), and are negative lengths invalid? What about `0`?

## Considerations
### Non-goals (to keep scope contained)

- Not a general “distance between two elements” selector.
- Not a replacement for `:hover` / `:focus` and should not imply activation.
- Not exposing pointer coordinates or requiring JS.

### Suggested initial semantics (strawman, for discussion)
An element matches `:near(<length>)` when:

- The UA has an active pointing device (see “Which pointer / modality” below).
- The distance between the pointer hotspot and the element’s “proximity shape” is ≤ `<length>`.
- The “proximity shape” is intentionally left to define (see questions below), but likely should align with existing UA hit-testing / painted geometry rather than author-defined shapes.

### Key semantics questions to resolve

**1. Distance & geometry**
- Distance from pointer hotspot to the nearest point on what geometry?
   - border box / padding box / visual border edge
   - UA hit-test region
   - post-transform painted geometry (transforms, border-radius)
- How should `overflow: clip/hidden`, masks, and `clip-path` affect the geometry?

**2. Which pointer / modality**
- Should this instead use `any-pointer` semantics (match if any hover-capable pointer is within range), rather than primary-only?
- What about pen hover (where supported) vs mouse?

**3. Update model**
- When does matching update?
   - pointer movement
   - scroll
   - layout/transform changes
- Can UAs throttle updates for performance (similar to how they handle other high-frequency input-driven effects)?
- What happens when the pointer is outside the viewport, or in a different browsing context (iframes)? How should this interact with Shadow DOM (closed trees, retargeting)?

**4. Hit-testing & stacking context**
- Should `:near()` consider the element even if it is not the topmost hit-test target at that point (covered by another element)?
- Interaction with `pointer-events: none`: should such elements ever match?

**5. Opt-in / performance gating**
- Should `:near()` itself be the opt-in gate (UA only needs to track proximity for elements that participate in selectors containing :near())?
- Are additional restrictions needed to prevent “global proximity listeners” (e.g., `*:near(999999px)`) from forcing continuous evaluation?
   - UAs may impose implementation-defined throttling and may clamp extremely large radii for performance/privacy.

### Privacy / fingerprinting considerations
This introduces a new CSS-driven state that can change styling based on pointer approach earlier than `:hover`. Even without JS, that can potentially be observed via conditional resource loads (e.g., `background-image` changes) and timing.

**Potential mitigations to discuss:**
- Consider restricting evaluation to the document/viewport (no cross-document or OS-level proximity semantics).
- Document and/or constrain observable side effects (if the group considers it necessary).

### Why a boolean proximity selector (vs pointer coordinates)
A threshold pseudo-class supports common “approach” affordances while keeping the feature smaller than exposing continuous coordinates. It may be easier to constrain for privacy and performance and provides a CSS-native alternative to JS `pointermove` patterns.

## Prior art / related CSSWG discussions
- w3c/csswg-drafts#6733 
- w3c/csswg-drafts#10574 

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13271 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Friday, 26 December 2025 23:19:32 UTC