Screen Wake Lock Toggle — Free navigator.wakeLock Demo

Screen Wake Lock Toggle · Buttons · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Real wakeLock.request call
Genuinely prevents display sleep, not a decorative switch.
WakeLockSentinel tracking
Holds and releases the actual lock handle correctly.
Visibility auto-reacquire
Handles the API's real auto-release-on-hide quirk.
Release event listener
Detects unexpected releases, not just user-initiated ones.
Disabled, not fake, when unsupported
No silent no-op toggle on unsupported browsers.
Named failure reasons
Surfaces the actual DOMException name on refusal.
Live status dot
A glanceable indicator separate from the longer status text.
Accessible switch semantics
role="switch" and aria-checked stay in sync with real state.

About this UI Snippet

Screen Wake Lock Toggle — Real Wake Lock With the Visibility Quirk Handled

Screenshot of the Screen Wake Lock Toggle snippet rendered live

This toggle calls the genuine Screen Wake Lock API — navigator.wakeLock.request('screen') — to actually prevent a device's display from sleeping while the toggle is on, the kind of control a recipe app or workout timer needs so the screen doesn't dim mid-instruction. Unlike a purely decorative switch, this one either does the real thing or plainly says it can't, because a wake lock toggle that silently does nothing is worse than no toggle at all.

Requesting and holding the lock

acquireLock() calls navigator.wakeLock.request('screen'), which resolves with a WakeLockSentinel — a live handle representing the held lock — wrapped in a try/catch since the browser can refuse the request (commonly a NotAllowedError, and some browsers refuse outright on very low battery). Success flips the UI to its "on" state and updates the status text to confirm the lock is genuinely active, not just that a switch was clicked.

The auto-release quirk, handled honestly

The one behavior every real implementation of this feature has to account for: a wake lock automatically releases the instant its document becomes hidden — switching apps, locking the phone, or backgrounding the tab all silently drop it. This snippet listens for the sentinel's own release event to detect that, and separately listens for visibilitychange on the document to re-acquire the lock the moment the page becomes visible again, but only if the user still wants it on (tracked in userWantsLock). Skipping this step is the single most common bug in real wake-lock implementations — the toggle looks "on" but the screen sleeps anyway the next time the user glances away.

No supported, no fake toggle

If 'wakeLock' in navigator is false, the toggle is disabled outright with an explanatory status line, rather than left interactive and doing nothing when clicked — matching the honesty standard set by this library's canvas audio frequency bars snippet, which never leaves a capability-gated control pretending to work. A visually-active-looking toggle that silently fails to keep the screen awake would defeat the entire purpose of the control.

A visible status dot

Beyond the toggle itself, a small status dot and label track the sentinel's actual state, so at a glance — even without reading the longer status sentence — it's clear whether the lock is genuinely held right now. Pair this with an uptime status page or status pill for the same "live indicator" pattern applied elsewhere in a dashboard.

Customizing it

Auto-request the lock on page load for a kiosk-style display, add a countdown showing how long the lock has been held, or combine it with a dark mode toggle for a late-night reading mode.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain why the Wake Lock API automatically releases the lock whenever the document becomes hidden, and why that makes the visibilitychange re-acquisition logic essential rather than optional — walk through what would happen if that listener were removed. It's a good prompt for reasoning about the WakeLockSentinel object specifically: ask why the code listens for the sentinel's own release event in addition to tracking a separate userWantsLock boolean, and what real-world scenario (other than switching tabs) could cause an unexpected release. For extensions, ask it to add a running timer showing how long the lock has been continuously held, a battery-level check that proactively warns the user the browser may refuse the request, or a way to distinguish "released because you turned it off" from "released unexpectedly" in the UI. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "Screen Wake Lock Toggle" in plain HTML, CSS, and JavaScript — no libraries.

Requirements:
- A toggle switch with proper role="switch" and aria-checked semantics, plus a small status dot/label and a longer status sentence, all reflecting the real current wake lock state.
- On toggle-on, check 'wakeLock' in navigator before calling navigator.wakeLock.request('screen') inside a try/catch. On success, store the returned WakeLockSentinel and update the UI to an active state with a status message confirming the lock is genuinely held.
- CRITICAL: handle the Wake Lock API's real auto-release behavior. The lock automatically releases whenever the page's visibility state becomes hidden (switching tabs or apps, locking the device) — listen for the document's visibilitychange event and, if the user still wants the lock on and it isn't currently held, re-request it automatically when the page becomes visible again. Also listen for the sentinel's own "release" event to detect and reflect releases that weren't user-initiated.
- On toggle-off, call sentinel.release() if a sentinel is currently held, and update the UI back to an inactive state.
- On unsupported browsers (the API doesn't exist at all — a common case, since support is Chromium-focused) or a rejected request (e.g. a NotAllowedError from a low-battery refusal or a blocked permissions policy in a sandboxed iframe, a likely scenario for wherever this demo renders), do NOT leave the toggle interactive and silently non-functional — either disable it outright with a clear "not supported" message, or show a specific failure reason in the status text and reset the toggle to its off state.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSAn off-state toggle with a status dot renders.
  2. 2
    Click the toggle to turn it onnavigator.wakeLock.request('screen') is called live.
  3. 3
    Switch tabs or lock your phoneThe lock auto-releases — a real browser behavior.
  4. 4
    Return to the tabThe visibilitychange listener re-acquires the lock automatically.
  5. 5
    Click the toggle offThe sentinel is released and the screen can sleep again.
  6. 6
    Try it in an unsupported browserThe toggle disables itself with a clear explanation.

Real-world uses

Common Use Cases

Recipe and cooking apps
Keep the screen on through a multi-step recipe.
Workout and timer apps
Prevent sleep mid-set without the user touching the screen.
Presentation and kiosk modes
Pair with a status pill showing lock state.
Reading apps
Combine with a dark mode toggle for night reading.
Video call waiting rooms
Keep a lobby screen visible before a meeting starts.
Dashboard displays
Keep an always-on status dashboard screen awake.

Got questions?

Frequently Asked Questions

That shouldn't happen with this snippet — but it's the exact bug that occurs if a wake lock implementation doesn't handle the API's biggest quirk: the lock automatically releases the instant the document is hidden (switching tabs, locking the phone, backgrounding the app). This snippet listens for visibilitychange and re-acquires the lock automatically when the page becomes visible again, as long as the toggle is still meant to be on.

The Wake Lock API (navigator.wakeLock) isn't supported in every browser. This snippet checks 'wakeLock' in navigator before doing anything, and if it's missing, disables the toggle outright with an explanatory message rather than leaving it clickable and silently doing nothing — a toggle that looks functional but has no effect is worse than one that's honestly unavailable.

No — requesting a wake lock requires a real user action to trigger it in this snippet (clicking the toggle), and the browser itself will show some visible indication that a page is holding a wake lock in many implementations. The lock is also always scoped to that specific document and releases automatically the moment the tab is closed, navigated away from, or hidden.

Browsers can refuse a wake lock request for reasons like critically low battery, an explicit user or system power-saving policy, or (in an embedded context) a permissions policy blocking the wake-lock feature for that frame. This snippet catches that rejection and shows the actual error name in the status text, then leaves the toggle in a clearly labeled off state rather than pretending the lock is held.

Store the WakeLockSentinel and a "user wants lock" boolean in refs (not state, since the sentinel is a live object rather than serializable data), and mirror the same acquireLock/releaseLock functions as event handlers. Add the visibilitychange listener in a mount effect and remove it in cleanup, and make sure to release any held lock on unmount so a component teardown doesn't leave a phantom lock active.