Skip to content

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

@twalichiewicz

Description

@twalichiewicz

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

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions