First-person games and 3D viewers need the mouse to keep moving even when the cursor would hit the edge of the screen. The Pointer Lock API hides the cursor and delivers continuous movementX / movementY deltas.
pointerlockchange is the Document signal that lock status already flipped. Update button labels, pause the game when the user presses Esc, or start reading movement events only while locked. MDN marks it Limited availability (not Baseline)—feature-detect and test.
💡
Beginner tip
Locking usually requires a user gesture (click on a canvas or “Play” button). Calling requestPointerLock() from a random timer often fails and may fire pointerlockerror instead.
Concept
Understanding pointerlockchange
A Document event that answers: “Did pointer lock just turn on or off?”
Fires when the pointer is locked or unlocked.
Does not encode lock vs unlock — read document.pointerLockElement.
Not cancelable and does not bubble (MDN).
Event type — a plain Event.
Handler — document.onpointerlockchange or document.addEventListener("pointerlockchange", ...).
Limited availability on MDN (not Baseline)—test carefully.
Foundation
📝 Syntax
Use the event name with addEventListener, or set the handler property on document:
Ask to lock the pointer (needs user gesture; returns a Promise in modern engines)
document.exitPointerLock()
Unlock the pointer (Document method)
document.pointerLockElement
Locked element, or null if unlocked / pending
pointerlockerror
Fires when a lock request fails
movementX / movementY
Mouse deltas while locked (on pointer/mouse events)
Detect
🔁 Locked vs Unlocked
By the time your handler runs, the mode has already changed. Use this MDN pattern:
JavaScript
document.addEventListener("pointerlockchange", (event) => {
if (document.pointerLockElement) {
console.log("The pointer is locked to: ", document.pointerLockElement);
} else {
console.log("The pointer is not locked");
}
});
document.pointerLockElement non-null → pointer is locked to that element.
null → unlocked (Esc, exitPointerLock(), or never locked).
Compare
⚖️ Pointer lock vs fullscreen
Topic
Pointer Lock
Fullscreen
Change event
pointerlockchange
fullscreenchange
State property
pointerLockElement
fullscreenElement
Enter
requestPointerLock()
requestFullscreen()
Exit
exitPointerLock() / Esc
exitFullscreen() / Esc
Main goal
Unlimited mouse deltas
Fill the display
Games often use both together: fullscreen for immersion, pointer lock for camera look.
Example 1 — addEventListener("pointerlockchange") (MDN)
Log whether the pointer is locked and to which element.
JavaScript
document.addEventListener("pointerlockchange", (event) => {
if (document.pointerLockElement) {
console.log("The pointer is locked to: ", document.pointerLockElement);
} else {
console.log("The pointer is not locked");
}
});
The pointer is locked to: [object HTMLCanvasElement]
The pointer is not locked
How It Works
Attach the listener on document before locking. Esc unlocks and still fires pointerlockchange, so your UI stays in sync.
Example 2 — document.onpointerlockchange
MDN’s alternate style using the handler property.
JavaScript
document.onpointerlockchange = (event) => {
if (document.pointerLockElement) {
console.log("The pointer is locked to: ", document.pointerLockElement);
} else {
console.log("The pointer is not locked");
}
};
Document pointerlockchange is marked Limited availability on MDN (not Baseline). Logos use the shared browser-image-sprite.png sprite from this project. Feature-detect requestPointerLock / exitPointerLock, and remember some environments deny pointer lock.
✓ Limited availability
Document pointerlockchange
Lock/unlock signal for the Pointer Lock API. Confirm support and user-gesture rules in your target browsers.
LimitedNot Baseline
Google ChromeSupported (check BCD / platform)
Supported
Mozilla FirefoxSupported in modern versions
Supported
Apple SafariSupported with platform quirks
Supported
Microsoft EdgeSupported · Chromium
Supported
OperaSupported · Modern versions
Supported
Internet ExplorerNo modern Pointer Lock API
No
pointerlockchangeLimited
Bottom line: Listen on document for pointerlockchange, check document.pointerLockElement, lock from a user gesture, and handle pointerlockerror for failures.
Wrap Up
Conclusion
pointerlockchange tells you pointer lock already flipped. Drive your UI from document.pointerLockElement, lock with requestPointerLock() after a user gesture, and unlock with Esc or document.exitPointerLock().
Check document.pointerLockElement inside the handler
Call requestPointerLock() from a user gesture
Guard movementX / movementY with a lock check
Feature-detect and handle pointerlockerror
❌ Don’t
Assume every browser allows pointer lock
Call lock from a random timer
Expect the event itself to say “locked” vs “unlocked”
Ignore Esc unlocks—they still fire pointerlockchange
Assume Baseline Widely available status
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about pointerlockchange
Lock/unlock signal — read pointerLockElement for state.
5
Core concepts
📄01
Lock toggled
on or off
Event
🔍02
Check element
null = unlocked
State
👋03
User gesture
for requestPointerLock
API
🚫04
No bubble
listen on document
DOM
⚠️05
Limited avail.
feature-detect
Compat
❓ Frequently Asked Questions
It fires when the pointer is locked or unlocked. In the handler, check document.pointerLockElement: if it is non-null the pointer is locked to that element; if null the pointer is not locked.
No. MDN does not mark it Deprecated, Experimental, or Non-standard. It has Limited availability (not Baseline), so feature-detect and test the browsers you care about.
No. MDN states the event is not cancelable and does not bubble. Listen on document.
Call element.requestPointerLock() from a user gesture to lock. Call document.exitPointerLock() or let the user press Esc to unlock. Update UI on pointerlockchange.
Listen for the pointerlockerror event on document. Failures often happen without a user gesture, in unsupported browsers, or when the browser denies permission.
Games and 3D viewers need unlimited mouse movement without hitting the screen edge. Locked input delivers movementX / movementY deltas instead of a visible cursor.
Did you know?
Pressing Esc is the standard unlock gesture. Browsers intentionally make leaving pointer lock easy—your pointerlockchange handler should treat unlock as a normal pause path, not an unexpected error.