visionOS Spatial Web Research

visionOSWebXRspatial

1. visionOS Safari Capabilities

What visionOS Safari Supports That’s Unique

HTML <model> Element (visionOS 26+, Safari 26+): A new native HTML element that renders USDZ 3D models stereoscopically — the user perceives real depth, not a flat rendering. This is the single most differentiated feature for spatial web content.

Spatial Audio via Web Audio API: The PannerNode in Web Audio lets you position audio sources in 3D space around the user. On Vision Pro, audio is actually spatialized through the device’s speakers.

Immersive Media Playback (visionOS 26): Spatial videos, Apple Immersive Video, and 180/360-degree videos can be embedded on web pages and played back immersively on a curved surface in 3D space via HLS.

WebXR (visionOS 2.0+, enabled by default): Full immersive VR sessions with natural gaze-and-pinch input. As of Safari 26.2, WebXR also supports WebGPU for high-performance rendering.

Web Speech API: Both recognition and synthesis are supported, with on-device processing (no server round-trip). Useful for hands-free interaction.

System-Managed Hover Effects: Safari applies its own gaze-based highlights to interactive elements. The system renders these outside the app process for privacy — your site never knows where the user is looking.

Default Safari Window

The default Safari window on visionOS is 1280x720 points (roughly 0.94m x 0.53m in the user’s physical space). Users can resize this window freely.


2. Spatial Web Design: Apple Guidelines

Key recommendations from Apple’s WWDC23/24/25 sessions and WebKit documentation:

Semantic HTML is Critical: Safari determines “interactive regions” (what gets a gaze highlight) by analyzing your markup. Native <button>, <a>, <input>, and elements with equivalent ARIA roles are automatically recognized. Elements with cursor: pointer CSS are also detected.

Large Tap Targets with Padding: Add generous padding to interactive elements. Even without visible backgrounds, the padding expands the hit region for gaze-and-pinch. Apple recommends this explicitly.

border-radius on Interactive Elements: This is the only developer-controllable aspect of visionOS gaze highlights. The system respects your border-radius when drawing its highlight overlay.

Use SVG for UI Elements: Vector graphics render cleanly at any scale and any distance from the user in the spatial environment.

Viewport Units (vw, vh): Use these for layout to adapt naturally when the Safari window is resized in space.

Prefer rem over px: Resolution-agnostic units scale properly in the spatial environment.

prefers-reduced-motion Respect: Mandatory. Many Vision Pro users may be motion-sensitive.


3. @media Queries for visionOS Detection

There is no dedicated @media query for visionOS. The visionOS Safari user agent is frozen and indistinguishable from iPad Safari.

The best you can do is detect input characteristics:

/* Applies to visionOS, iOS, iPadOS (all coarse-pointer, no-hover devices) */
@media (pointer: coarse) and (hover: none) {
  .sticky { padding: 1.2rem; }  /* larger tap targets */
}

For JavaScript feature detection:

// Detect <model> element support (visionOS 26+ Safari)
const supportsModelElement = 'HTMLModelElement' in window;

// Detect AR Quick Look support
const link = document.createElement('a');
const supportsAR = link.relList && link.relList.supports('ar');

// Detect WebXR support
const supportsWebXR = 'xr' in navigator;

You cannot reliably distinguish visionOS from iPadOS via CSS or user agent. Apple intentionally prevents this for privacy. The recommended approach is progressive enhancement: detect capabilities, not platforms.


4. 3D Model / AR Content on Websites

HTML <model> Element (visionOS 26+)

This is the premier spatial web feature. It renders USDZ files stereoscopically inline in the page:

<model stagemode="orbit" style="width: 300px; height: 300px;">
  <source src="/models/pushpin.usdz" type="model/vnd.usdz+zip">
  <img alt="A 3D pushpin" src="/images/pushpin-fallback.png">
</model>

JavaScript API:

const model = document.querySelector('model');
await model.ready;

model.entityTransform = new DOMMatrix()
  .rotate(0, 45, 0)
  .scale(1.5);

model.play();
model.pause();
model.currentTime = 0;
model.loop = true;

console.log(model.boundingBoxCenter);
console.log(model.boundingBoxExtents);

Attributes: stagemode="orbit" (pinch-and-drag rotation), environmentmap="custom.exr" (custom HDR lighting), autoplay, loop.

AR Quick Look (All Apple platforms)

<a rel="ar" href="/models/sticky-note.usdz">
  <img src="/images/sticky-preview.png" alt="View 3D sticky note">
</a>

On visionOS, the USDZ model opens in a Quick Look window alongside Safari, and users can place it anywhere in their physical space.


5. Unique Interaction Patterns

Gaze-and-Pinch (Primary Input)

  • pointerdown: Fires when a pinch begins. Target determined by where the user’s eyes were looking.
  • pointermove: Tracks hand movement while fingers are pinched together.
  • pointerup: Fires when the pinch releases.

Key Differences from Touch/Mouse

  • No mouseover/mouseenter events (no way to detect gaze without pinch)
  • No long-press differentiation
  • pointerdown target is determined by eye gaze, not finger position
  • Movement after pinch follows the hand, not the eyes

SVG Path-Based Interaction Regions (visionOS 2+)

For complex shapes (non-rectangular hit areas), SVG paths can define fine-grained interaction regions.


6. CSS :hover on visionOS

Safari completely ignores your CSS :hover rules on visionOS. This is by design for privacy — if the browser applied your hover styles based on eye position, websites could infer where the user is looking.

Instead, the system applies its own subtle highlight effect. This highlight:

  • Respects your element’s border-radius
  • Uses a gentle, semi-transparent overlay
  • Fades after a few seconds on large media elements
  • Is rendered outside the app process

Implications for bythewei.dev: Any visual effects built with :hover (sticky note lift, shadow changes) will not appear on visionOS. Options:

/* This WILL NOT work on visionOS */
.sticky:hover { transform: scale(1.05); }

/* This WILL work -- triggers on pinch */
.sticky:active { transform: scale(1.05); }

When a Bluetooth mouse/keyboard is connected, :hover rules are restored.


7. Window Resizing / Immersive Web

Safari Window Behavior

  • Default: 1280x720pt, freely resizable by the user
  • The window floats in space; users can reposition it anywhere
  • Standard responsive CSS (media queries, viewport units, flexbox/grid) all work
  • The window is flat — there is no z-depth to the Safari window itself

WebXR for Full Immersion

WebXR is the only way to break out of the flat Safari window into true 3D space:

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  if (supported) {
    const session = await navigator.xr.requestSession('immersive-vr');
  }
}

Important limitation: WebXR is a full-screen takeover. There is no “partially immersive” mode. It’s either the flat Safari window or full WebXR immersion.


8. Practical Ideas for bythewei.dev

Tier 1: Low Effort, High Impact

Glassmorphism / Frosted Glass Stickies

@media (pointer: coarse) and (hover: none) {
  .sticky {
    background: rgba(255, 253, 208, 0.7);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }
}

Generous border-radius for polished gaze highlights.

Move :hover Effects to :active

@media (hover: hover) {
  .sticky:hover { transform: translateY(-3px) rotate(0deg); }
}
@media (hover: none) {
  .sticky:active { transform: scale(0.97); }
}

Tier 2: Medium Effort

Spatial Audio Easter EggsPannerNode to position sounds at the sticky’s screen position.

CSS perspective + translateZ — Depth layers for visual parallax.

3D Pushpin via <model> — Replace .pin elements with stereoscopic USDZ models on supported devices.

Tier 3: High Effort, Showcase

WebXR “Step Into the Board” Mode — Full spatial session where stickies surround the user in 3D space.


Priority Table

#FeatureEffortImpact
1border-radius on interactive elements5 minPolished gaze highlights
2Move :hover to :active15 minPinch feedback works
3Larger tap targets @media (pointer: coarse)15 minComfortable gaze-and-pinch
4CSS perspective + translateZ30 minHead-tracking parallax
5backdrop-filter glassmorphism15 minNative visionOS aesthetic
6Spatial audio on interactions1 hrDirectional sound
73D pushpin <model>2 hrStereoscopic depth (needs USDZ)
8Voice commands via Web Speech2 hrHands-free navigation
9WebXR immersive board mode20+ hrFull spatial experience

Key Constraint: There is no way to make elements literally “float out” of the Safari window without WebXR. The <model> element is the only thing that renders with true stereoscopic depth while staying within the page.


Sources