-
Notifications
You must be signed in to change notification settings - Fork 764
Description
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/:focusand 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, andclip-pathaffect the geometry?
2. Which pointer / modality
- Should this instead use
any-pointersemantics (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.