Note: Geolocation requires HTTPS (or localhost for development). User must grant permission - request shows browser prompt. Accuracy varies by device (GPS, WiFi, IP). enableHighAccuracy uses GPS on mobile (slower, more battery). Desktop typically uses IP/WiFi regardless.
Warning:watchPosition can drain battery - always clearWatch() when done. Don't rely on optional fields (altitude, speed, heading) - may be null. Location can be spoofed - don't trust for security. Privacy concern - explain why you need location to users.
Note: iOS 13+ requires user permission and user gesture to access orientation/motion. Request permission with DeviceOrientationEvent.requestPermission(). Events fire frequently (30-60 times/second) - throttle expensive operations. Desktop browsers may not support these events.
Warning: Sensor data can be noisy - apply smoothing/filtering for better results. Battery drain with continuous monitoring - remove listeners when not needed. Privacy concern - can be used for fingerprinting. Not all devices have all sensors (gyroscope, magnetometer).
3. Battery Status API (deprecated but legacy)
Property
Type
Description
Status
navigator.getBattery()
Promise<BatteryManager>
Returns Promise with battery status object.
DEPRECATED
level
number
Battery level 0.0 to 1.0 (0% to 100%).
Read-only
charging
boolean
true if device is charging.
Read-only
chargingTime
number
Seconds until fully charged. Infinity if not charging or unknown.
Read-only
dischargingTime
number
Seconds until battery empty. Infinity if charging or unknown.
Read-only
Event
When Fired
levelchange
Battery level changed
chargingchange
Charging status changed (plugged/unplugged)
chargingtimechange
Charging time estimate changed
dischargingtimechange
Discharging time estimate changed
Example: Battery status monitoring
// Check if API is availableif ("getBattery" in navigator) { navigator.getBattery().then((battery) => { // Initial state console.log(`Battery level: ${battery.level * 100}%`); console.log(`Charging: ${battery.charging}`); console.log(`Charging time: ${battery.chargingTime} seconds`); console.log(`Discharging time: ${battery.dischargingTime} seconds`); // Listen for level changes battery.addEventListener("levelchange", () => { console.log(`Battery level: ${battery.level * 100}%`); // Warn if low battery if (battery.level < 0.2 && !battery.charging) { console.warn("Low battery!"); } }); // Listen for charging state changes battery.addEventListener("chargingchange", () => { if (battery.charging) { console.log("Device is charging"); } else { console.log("Device is not charging"); } }); // Charging time updates battery.addEventListener("chargingtimechange", () => { if (battery.chargingTime !== Infinity) { const minutes = Math.floor(battery.chargingTime / 60); console.log(`Fully charged in ${minutes} minutes`); } }); // Discharging time updates battery.addEventListener("dischargingtimechange", () => { if (battery.dischargingTime !== Infinity) { const minutes = Math.floor(battery.dischargingTime / 60); console.log(`Battery empty in ${minutes} minutes`); } }); });} else { console.log("Battery Status API not supported");}
Warning: Battery Status API is DEPRECATED due to privacy concerns (fingerprinting). Removed from most browsers. Firefox disabled by default. Chrome plans removal. Don't rely on this API for new projects. Use feature detection before accessing.
4. Vibration API for Haptic Feedback
Method
Syntax
Description
Browser Support
vibrate
navigator.vibrate(pattern)
Vibrates device with pattern. Pattern is number (ms) or array [vibrate, pause, ...].
Note: Vibration only works on mobile devices with vibration hardware. Desktop browsers ignore vibrate() calls. Maximum vibration time limited by browsers (few seconds). User can disable vibration in system settings. Requires user gesture on some browsers.
Warning: Don't overuse vibration - annoying and drains battery. Respect user preferences - provide option to disable. Some users rely on vibration for accessibility - use meaningfully. Vibration patterns limited to prevent abuse (max length, max duration).
5. Screen Orientation API and Lock
Property/Method
Description
Browser Support
screen.orientation.type
Current orientation: "portrait-primary", "portrait-secondary", "landscape-primary", "landscape-secondary".
Modern Browsers
screen.orientation.angle
Orientation angle: 0, 90, 180, or 270 degrees.
Modern Browsers
screen.orientation.lock(orientation)
Locks to specific orientation. Returns Promise. Requires fullscreen on most browsers.
Modern Mobile
screen.orientation.unlock()
Unlocks orientation, allowing device rotation.
Modern Mobile
orientationchange event
Fires when screen orientation changes.
Modern Browsers
Orientation Value
Description
portrait-primary
Normal portrait (0° or 180°)
portrait-secondary
Upside-down portrait (180° or 0°)
landscape-primary
Normal landscape (90° or 270°)
landscape-secondary
Reverse landscape (270° or 90°)
portrait
Any portrait orientation
landscape
Any landscape orientation
any
Allow all orientations (default)
Example: Detect and lock orientation
// Check current orientationif (screen.orientation) { console.log(`Type: ${screen.orientation.type}`); console.log(`Angle: ${screen.orientation.angle}°`);} else { console.log("Screen Orientation API not supported");}// Listen for orientation changesscreen.orientation?.addEventListener("change", () => { console.log(`Orientation changed to: ${screen.orientation.type}`); console.log(`Angle: ${screen.orientation.angle}°`); // Adjust layout based on orientation if (screen.orientation.type.startsWith("landscape")) { document.body.classList.add("landscape"); document.body.classList.remove("portrait"); } else { document.body.classList.add("portrait"); document.body.classList.remove("landscape"); }});// Lock orientation (requires fullscreen)async function lockLandscape() { try { // Enter fullscreen first await document.documentElement.requestFullscreen(); // Lock to landscape await screen.orientation.lock("landscape"); console.log("Locked to landscape"); } catch (error) { console.error("Failed to lock orientation:", error); }}// Lock to specific orientationasync function lockOrientation(orientation) { try { await screen.orientation.lock(orientation); console.log(`Locked to ${orientation}`); } catch (error) { if (error.name === "NotSupportedError") { console.error("Orientation lock not supported"); } else if (error.name === "SecurityError") { console.error("Must be in fullscreen to lock orientation"); } else { console.error("Lock failed:", error); } }}// Unlock orientationfunction unlockOrientation() { screen.orientation?.unlock(); console.log("Orientation unlocked");}// Game example: lock to landscape when playingasync function startGame() { await document.documentElement.requestFullscreen(); await screen.orientation.lock("landscape"); // Start game}function exitGame() { screen.orientation.unlock(); document.exitFullscreen();}
Note: Orientation lock typically requires fullscreen mode. Desktop browsers may not support orientation lock. Use CSS media queries for responsive design alongside API. Some browsers use window.orientation (deprecated) - use screen.orientation instead.
Warning: Don't lock orientation unless necessary (games, video). Respect user preference - they rotated device intentionally. Unlock orientation when leaving fullscreen. May not work in iframes or certain contexts.
6. Generic Sensor API and Accelerometer
Sensor
Description
Browser Support
Accelerometer
Measures acceleration in m/s² along X, Y, Z axes.
Limited (Chrome)
LinearAccelerationSensor
Acceleration excluding gravity.
Limited (Chrome)
GravitySensor
Gravity component of acceleration.
Limited (Chrome)
Gyroscope
Measures angular velocity (rotation rate) in rad/s.
Limited (Chrome)
Magnetometer
Measures magnetic field in µT (microtesla).
Limited (Chrome)
AbsoluteOrientationSensor
Device orientation relative to Earth's coordinate system.
Limited (Chrome)
RelativeOrientationSensor
Device orientation relative to arbitrary reference.
Limited (Chrome)
AmbientLightSensor
Measures ambient light in lux.
Limited (Chrome)
Sensor Method/Property
Description
start()
Starts sensor. Fires reading event when data available.
// Gyroscope (rotation rate)try { const gyroscope = new Gyroscope({ "frequency": 60 }); gyroscope.addEventListener("reading", () => { console.log(`Rotation rate: x=${gyroscope.x}, y=${gyroscope.y}, z=${gyroscope.z} rad/s`); // Convert to degrees per second const degPerSec = { "x": gyroscope.x * 180 / Math.PI, "y": gyroscope.y * 180 / Math.PI, "z": gyroscope.z * 180 / Math.PI }; console.log(`Rotation (deg/s): x=${degPerSec.x.toFixed(2)}, y=${degPerSec.y.toFixed(2)}, z=${degPerSec.z.toFixed(2)}`); }); gyroscope.start();} catch (error) { console.error("Gyroscope not supported:", error);}// Absolute orientation (quaternion)try { const orientation = new AbsoluteOrientationSensor({ "frequency": 60 }); orientation.addEventListener("reading", () => { // Quaternion representation const [x, y, z, w] = orientation.quaternion; console.log(`Quaternion: [${x}, ${y}, ${z}, ${w}]`); // Convert to Euler angles const angles = quaternionToEuler(x, y, z, w); console.log(`Euler angles: ${JSON.stringify(angles)}`); }); orientation.start();} catch (error) { console.error("AbsoluteOrientationSensor not supported:", error);}// Helper: Convert quaternion to Euler anglesfunction quaternionToEuler(x, y, z, w) { const roll = Math.atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y)); const pitch = Math.asin(2 * (w * y - z * x)); const yaw = Math.atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z)); return { "roll": roll * 180 / Math.PI, "pitch": pitch * 180 / Math.PI, "yaw": yaw * 180 / Math.PI };}// Ambient light sensortry { const lightSensor = new AmbientLightSensor({ "frequency": 1 }); lightSensor.addEventListener("reading", () => { console.log(`Illuminance: ${lightSensor.illuminance} lux`); // Adjust UI based on ambient light if (lightSensor.illuminance < 50) { document.body.classList.add("dark-mode"); } else { document.body.classList.remove("dark-mode"); } }); lightSensor.start();} catch (error) { console.error("AmbientLightSensor not supported:", error);}
Note: Generic Sensor API has limited browser support (mainly Chrome). Requires HTTPS and user permission. Sensors may not be available on all devices. Use frequency option to control sampling rate (affects battery and CPU). Always wrap in try/catch for feature detection.
Warning: Sensor APIs can drain battery with high frequency - use lowest frequency needed. Always stop() sensors when not in use. Privacy concern - sensor data can be used for fingerprinting or side-channel attacks. Check browser compatibility before using - very limited support.
Device and Sensor API Best Practices
Always check feature availability with if ("geolocation" in navigator) before using APIs
Request location/sensor permissions with clear explanation why you need them
Use enableHighAccuracy: false for geolocation unless GPS precision is critical
Always clearWatch() geolocation watches when done to save battery
Throttle or debounce orientation/motion event handlers - they fire very frequently
Request DeviceOrientation/Motion permissions on iOS 13+ with user gesture
Don't rely on Battery Status API - deprecated and removed from most browsers
Use vibration sparingly - annoying when overused and drains battery
Orientation lock requires fullscreen mode - unlock when exiting fullscreen
Generic Sensor API has limited support - use DeviceOrientation/Motion for broader compatibility
Always stop sensors when not needed to conserve battery and CPU
Handle permission denials gracefully - provide fallback UX