JavaScript Document pointerlockchange Event

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Document event
Limited availability

What You’ll Learn

The Document pointerlockchange event fires when the pointer is locked or unlocked. Learn how to read document.pointerLockElement, how to lock with requestPointerLock() and unlock with exitPointerLock(), and five try-it labs.

01

Kind

Document event

02

Type

Event

03

Cancelable

No

04

Bubbles

No

05

State check

pointerLockElement

06

Status

Limited availability

Introduction

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.

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.
  • Handlerdocument.onpointerlockchange or document.addEventListener("pointerlockchange", ...).
  • Limited availability on MDN (not Baseline)—test carefully.

📝 Syntax

Use the event name with addEventListener, or set the handler property on document:

JavaScript
addEventListener("pointerlockchange", (event) => { });

onpointerlockchange = (event) => { };

Event type

A generic Event. Not cancelable. Does not bubble.

Related Pointer Lock pieces

APIRole
element.requestPointerLock()Ask to lock the pointer (needs user gesture; returns a Promise in modern engines)
document.exitPointerLock()Unlock the pointer (Document method)
document.pointerLockElementLocked element, or null if unlocked / pending
pointerlockerrorFires when a lock request fails
movementX / movementYMouse deltas while locked (on pointer/mouse events)

🔁 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).

⚖️ Pointer lock vs fullscreen

TopicPointer LockFullscreen
Change eventpointerlockchangefullscreenchange
State propertypointerLockElementfullscreenElement
EnterrequestPointerLock()requestFullscreen()
ExitexitPointerLock() / EscexitFullscreen() / Esc
Main goalUnlimited mouse deltasFill the display

Games often use both together: fullscreen for immersion, pointer lock for camera look.

⚡ Quick Reference

GoalCode / note
Listendocument.addEventListener("pointerlockchange", fn)
Handler propertydocument.onpointerlockchange = fn
Lockel.requestPointerLock() (user gesture)
Unlockdocument.exitPointerLock() or Esc
Am I locked?Boolean(document.pointerLockElement)
Bubbles / cancelable?No / No
MDN statusLimited availability (not Baseline)

🔍 At a Glance

Four facts to remember about pointerlockchange.

Event type
Event

Plain Event

Means
lock toggled

On or off

State check
pointerLockElement

null = unlocked

Baseline
no

Limited availability

Examples Gallery

Examples follow MDN Document: pointerlockchange event. Try-it labs need a real browser click—some embedded previews block pointer lock.

📚 Getting Started

MDN-style Document listeners.

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");
  }
});
Try It Yourself

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");
  }
};
Try It Yourself

How It Works

Prefer addEventListener when you need multiple listeners or easy removal.

📈 Toggle, Detect & Move

Build a lock button, feature-detect, and read movement deltas.

Example 3 — Toggle Lock + Update UI

Click a canvas to lock; Esc or a button unlocks; status text follows the event.

JavaScript
const canvas = document.getElementById("game");
const status = document.getElementById("status");
const unlockBtn = document.getElementById("unlock");

function syncUi() {
  const locked = Boolean(document.pointerLockElement);
  status.textContent = locked ? "Pointer locked (Esc to exit)" : "Click canvas to lock";
  unlockBtn.disabled = !locked;
}

document.addEventListener("pointerlockchange", syncUi);

canvas.addEventListener("click", () => {
  if (!document.pointerLockElement) {
    canvas.requestPointerLock();
  }
});

unlockBtn.addEventListener("click", () => {
  document.exitPointerLock();
});

syncUi();
Try It Yourself

How It Works

exitPointerLock() lives on document, not the element. Drive all chrome from pointerlockchange so Esc exits stay consistent.

Example 4 — Feature-Detect Before Calling

Disable the lock control when Pointer Lock methods are missing.

JavaScript
const canvas = document.getElementById("game");
const note = document.getElementById("note");

const canLock =
  typeof canvas.requestPointerLock === "function" &&
  typeof document.exitPointerLock === "function";

if (!canLock) {
  note.textContent = "Pointer Lock API not available in this environment.";
} else {
  note.textContent = "Pointer Lock API looks available. Click the canvas.";
  document.addEventListener("pointerlockchange", () => {
    note.textContent = document.pointerLockElement
      ? "Locked"
      : "Unlocked";
  });
  canvas.addEventListener("click", () => {
    canvas.requestPointerLock();
  });
}
Try It Yourself

How It Works

Limited availability means some engines or embedded frames may deny lock even when methods exist—also listen for pointerlockerror.

Example 5 — Read movementX / movementY While Locked

Only accumulate look deltas while pointerLockElement is set.

JavaScript
const canvas = document.getElementById("game");
const out = document.getElementById("out");
let yaw = 0;
let pitch = 0;

document.addEventListener("pointerlockchange", () => {
  out.textContent = document.pointerLockElement
    ? "Locked — move the mouse"
    : "Unlocked — click canvas to lock";
});

canvas.addEventListener("click", () => {
  canvas.requestPointerLock();
});

document.addEventListener("mousemove", (event) => {
  if (!document.pointerLockElement) return;
  yaw += event.movementX;
  pitch += event.movementY;
  out.textContent = `yaw: ${yaw}, pitch: ${pitch}`;
});
Try It Yourself

How It Works

Guard movement handlers with pointerLockElement so unlocked mouse moves do not spin the camera. That pairs naturally with pointerlockchange UI.

🚀 Common Use Cases

  • FPS / third-person camera look controls.
  • 3D model viewers that need continuous drag without leaving the viewport.
  • Pausing a game loop when the user presses Esc to unlock.
  • Updating “Click to play” overlays based on lock state.
  • Pairing with fullscreen for immersive play modes.

🔧 How It Works

1

User gesture

Click calls requestPointerLock() on a canvas or game surface.

Gesture
2

Browser locks pointer

Cursor hides; pointerLockElement points at the target.

Lock
3

pointerlockchange

Document fires the event; UI and game loop react.

Notify
4

Unlock via Esc or exitPointerLock

Another pointerlockchange fires; pointerLockElement becomes null.

📝 Notes

  • MDN: Limited availability (not Baseline)—test the browsers you support.
  • Not Deprecated, Experimental, or Non-standard—no status banner required.
  • Not cancelable and does not bubble—listen on document.
  • Check document.pointerLockElement for locked vs unlocked.
  • Related learning: pointerLockElement, exitPointerLock(), requestPointerLock(), JavaScript hub.

Limited Availability Support

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.

Limited Not Baseline
Google Chrome Supported (check BCD / platform)
Supported
Mozilla Firefox Supported in modern versions
Supported
Apple Safari Supported with platform quirks
Supported
Microsoft Edge Supported · Chromium
Supported
Opera Supported · Modern versions
Supported
Internet Explorer No modern Pointer Lock API
No
pointerlockchange Limited

Bottom line: Listen on document for pointerlockchange, check document.pointerLockElement, lock from a user gesture, and handle pointerlockerror for failures.

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().

Continue with pointerLockElement, exitPointerLock(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Listen on document for lock/unlock UI updates
  • 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

Key Takeaways

Knowledge Unlocked

Five things to remember about pointerlockchange

Lock/unlock signal — read pointerLockElement for state.

5
Core concepts
🔍 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.

Next: Document pointerlockerror

Learn the Document event that fires when locking the pointer fails.

pointerlockerror →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful