๐Ÿ–ฅ๏ธ Chapter 54: The Fullscreen API

Fullscreen Lifecycle Events & State

Master `fullscreenchange`, `fullscreenerror`, tracking `document.fullscreenElement`, and synchronizing reactive application state.

LEARNING OBJECTIVES โŒต
  • Implement robust event listeners for fullscreenchange and fullscreenerror.
  • Accurately query document.fullscreenElement to synchronize UI controls, icons, and themes.
  • Understand the event dispatch chain and bubbling behavior across elements and the Document.
  • Diagnose and log permission rejections and runtime failures captured by fullscreenerror.
  • Architect a resilient state machine to track fullscreen sessions and analytics telemetry.
๐ŸŽฌ INTERACTIVE VISUAL PIPELINE Core Architecture Simulation
๐ŸŒ
1. Input
Directives & Tags
โš™๏ธ
2. Parse
Tokenizer & AST
๐ŸŒณ
3. Layout
Box Model & Flow
๐ŸŽจ
4. Render
GPU Paint & Composite
PHASE 1: INPUT & DIRECTIVES
Browser receives declarative markup stream, parsing tag tokens and initializing component state.

๐Ÿ“– The Mental Model & Story (Intuitive Foundation)

Imagine an airport air traffic control tower.

Aircraft are constantly taxiing, taking off, climbing, and landing. The air traffic controller doesn't just push a button to grant clearance and then look away; the radar screen continuously tracks which aircraft is currently occupying the active runway.

Whenever an aircraft crosses the runway threshold or clears the landing zone, an automated radar transponder ping sounds across the tower, updating the master status board.

FULLSCREEN EVENT DISPATCH LIFECYCLE
+-------------------------------------------------------------------------------+
| USER ACTION: Clicks "Play Fullscreen" OR Presses [ESC] Key                    |
+-------------------------------------------------------------------------------+
                                       |
                                       v
+-------------------------------------------------------------------------------+
| BROWSER COMPOSITOR TRANSITION                                                 |
|  1. Evaluates user activation & permissions                                   |
|  2. If DENIED  ---> Dispatches 'fullscreenerror' (on Element & Document)      |
|  3. If GRANTED ---> Reconfigures display & updates document.fullscreenElement |
+-------------------------------------------------------------------------------+
                                       |
                                       v
+-------------------------------------------------------------------------------+
| EVENT BROADCAST: 'fullscreenchange'                                           |
|                                                                               |
|  Target Element (#player)  ========> Dispatches 'fullscreenchange'            |
|                                      (Bubbles up to Document & Window)        |
|                                                                               |
|  document.fullscreenElement === #player (or null if exiting)                  |
+-------------------------------------------------------------------------------+

In the Fullscreen API, fullscreenchange is that transponder ping. Because users can exit fullscreen at any time using the keyboard (Escape key), trackpad gestures, or OS controls, your UI state must never assume success based solely on a click. You must observe the lifecycle events to keep your play/pause buttons, icons, and analytics in sync.


Technical Deep Dive & Specifications

The fullscreenchange Event

The browser dispatches a fullscreenchange event whenever:

  1. An element successfully transitions into the Top Layer.
  2. An element is popped off the Top Layer (transitioning to a previous nested fullscreen element).
  3. The last element in the stack exits, returning to normal windowed mode.
// Listening at the document level (Recommended)
document.addEventListener('fullscreenchange', (event: Event) => {
  if (document.fullscreenElement) {
    console.log('Entered fullscreen on:', document.fullscreenElement);
  } else {
    console.log('Exited fullscreen mode completely.');
  }
});

The fullscreenerror Event

If a call to requestFullscreen() fails (or if exitFullscreen() encounters a fatal error), the browser fires the fullscreenerror event:

document.addEventListener('fullscreenerror', (event: Event) => {
  console.error('Fullscreen request was rejected by browser policy.', event);
});

Common Causes of fullscreenerror:

  • Missing User Activation: Attempting programmatic invocation without an active user gesture.
  • Iframe Sandboxing: The element resides inside an <iframe> missing allow="fullscreen".
  • Detached DOM Node: The element was removed or detached from the DOM immediately after calling requestFullscreen().
  • Conflicting Window State: The window is minimized or inactive.

Querying document.fullscreenElement

document.fullscreenElement is the single source of truth for fullscreen status:

+-------------------------------------------------------------------------------+
|                         `document.fullscreenElement`                          |
+----------------------+--------------------------------------------------------+
| Return Value         | State Description                                      |
+----------------------+--------------------------------------------------------+
| `null`               | The document is currently in normal windowed mode.     |
|                      |                                                        |
| `HTMLElement`        | Reference to the specific DOM node currently promoted  |
| (e.g. `<video id>`)  | into the active Top Layer slot.                        |
+----------------------+--------------------------------------------------------+

Comparison: Event Listener vs Promise Handling

Modern browsers support both Promises on requestFullscreen() and the fullscreenchange event. How do they compare?

Feature requestFullscreen().then() / await document.addEventListener('fullscreenchange')
Scope Captures only the specific initiating call Captures ALL transitions (entry, nested, and Escape key exits)
Handles Keyboard Esc โŒ No (Only catches the entry promise) โœ… Yes (Guaranteed to fire on Esc)
Error Handling catch (err) captures the specific TypeError Fires global fullscreenerror
Best Practice Usage Immediate async flow control Global UI synchronization & analytics

๐Ÿ’ป Interactive Code Playground

Starter Code

Line-by-Line Code Breakdown

  • Line 164โ€“187 (document.addEventListener('fullscreenchange')): Centralizes all UI updates into a single event handler. When the user exits using Escape, this handler fires automatically and restores all labels and button icons.
  • Line 172โ€“176 (sessionStartTime): Captures high-precision timestamps (performance.now()) to compute exact user viewing duration metrics.
  • Line 149โ€“157 (triggerErrorBtn): Deliberately executes requestFullscreen() after a setTimeout to trigger the fullscreenerror event for diagnostic testing.
  • Line 189โ€“192 (document.addEventListener('fullscreenerror')): Catches systemic browser rejections and security failures.

Expected Browser Render Output

  1. The page renders with a grey badge: STATE: WINDOWED and document.fullscreenElement: null.
  2. Clicking "Enter Fullscreen" promotes the player and triggers fullscreenchange. The telemetry log records the exact event and changes the badge to green: STATE: FULLSCREEN ACTIVE.
  3. Pressing Escape triggers fullscreenchange again, calculating the total viewing session duration (e.g. Session duration: 4.82s) and restoring the icon.

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
HTML STARSHIP CODE TERMINAL playground.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45ยฐC
INSPECTING DOM: VALID
TAGS: SCANNING...

๐Ÿ‹๏ธ Hands-On Exercise

๐ŸŽฏ The Challenge: Create a Resilient Fullscreen Telemetry & Error Monitor

Instructions:

  1. Create a media container (#gameViewport) with an "Enter Fullscreen Game" button.
  2. Build an analytics tracker that logs:
    • When fullscreen was entered.
    • The screen resolution at the time of entry (window.innerWidth x window.innerHeight).
    • How many times the user entered and exited during the session.
  3. Add a warning banner if the user stays in fullscreen for more than 10 seconds.
  4. Listen for fullscreenerror and display a user-friendly modal warning explaining that user gestures are required.

๐Ÿ Starter Code Sandbox

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
STARTER CODE SANDBOX exercise.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45ยฐC
INSPECTING DOM: VALID
TAGS: SCANNING...

โš ๏ธ Common Pitfalls

  1. Updating UI State Only in Click Handlers: Updating your button label to "Exit" inside button.addEventListener('click') causes a desynchronization bug when the user exits using the Escape key. Always update state inside the fullscreenchange listener.
  2. Attaching fullscreenchange Only to Target Elements on Legacy Browsers: While modern browsers bubble fullscreenchange, some older WebKit engines dispatched it only to the Document. Listening on document is the most reliable cross-browser approach.
  3. Assuming event.target is Always the Fullscreen Element: On exit, document.fullscreenElement is null. Always verify whether document.fullscreenElement is truthy before reading element properties.

๐Ÿ’ก Pro Tips

  1. Integrate with Visibility API: Combine fullscreenchange with visibilitychange (document.hidden) to automatically pause full-screen games or video playback if the user switches virtual desktops (e.g. via Alt+Tab or Mission Control).
  2. Dispatch Framework-Level Custom Events: In large web apps, wrap fullscreenchange in an application-wide event bus or reactive store (e.g., Zustand, Pinia, Redux) to notify decoupled navigation bars and modals.

๐Ÿ“Œ Key Takeaways

  • fullscreenchange is dispatched whenever entering or exiting any layer of fullscreen mode.
  • fullscreenerror fires when a fullscreen request is denied by permissions or security gating.
  • document.fullscreenElement is the canonical source of truth for the currently promoted DOM node.
  • Always synchronize UI buttons, icons, and timers inside fullscreenchange to account for Escape key exits.
  • Listening on document ensures 100% capture of all transitions across parent and child components.
  • --
โญ LEARN: HTML ๐ŸŒŸ โš”๏ธ QUIZ BATTLE ARENA // ACTIVE
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 1 / 3

Why is listening to the fullscreenchange event preferred over relying exclusively on the Promise returned by requestFullscreen() for updating UI buttons?

Question 1 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 2 / 3

What is the value of document.fullscreenElement when the browser is in standard windowed mode?

Question 2 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 3 / 3

Which event is dispatched if a script attempts to invoke requestFullscreen() without a valid transient user gesture?

Question 3 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP