Fullscreen
Presents an element in fullscreen using the browser Fullscreen API.
View as MarkdownPreview
Live broadcastUsage guidelines
- User gesture required: Browsers only honor
requestFullscreen()while the window has transient activation — granted by a recent user interaction (click, tap, keypress) and valid for roughly five seconds. The bundled<Fullscreen.Trigger>always satisfies this. Flippingopenfrom any external handler triggered by a user gesture (including a deferredsetTimeoutthat still runs within the activation window) also works. Requests fired without a recent gesture are rejected. - Browser support: Fullscreen is unavailable on iOS Safari for iPhone (only iPad iOS 16.4+ supports
requestFullscreen()on arbitrary elements). When the API is unavailable for the container’s owner document,<Fullscreen.Trigger>is automatically disabled (data-disabled,aria-disabled="true"). Thesupportedstate is also exposed on Root, Trigger, Container, and Close so you can render fallback UI. - Inside iframes: The hosting
<iframe>must include theallowfullscreenattribute (orallow="fullscreen") and any Permissions Policy must permit thefullscreenfeature for the document. Without these, requests are rejected with aTypeError. - Mobile considerations: Some mobile browsers ignore
<meta name="viewport">settings and disable user pinch-zoom while a page is in fullscreen. - Exit affordance: Users can always exit fullscreen with Esc (or F11). The component listens to the browser’s
fullscreenchangeevent and reconciles state automatically —onOpenChangeis fired withreason: 'escape-key'in that case. - Esc inside popups: When a
<Dialog>,<Popover>,<Menu>, or any other popup is open inside fullscreen, pressing Esc dismisses the popup first instead of immediately exiting fullscreen. Base UI uses the Keyboard Lock API so the keypress reaches JavaScript handlers; popups (which callevent.preventDefault()on Esc) keep fullscreen alive, while a “bare” Esc still exits. Keyboard Lock is only implemented in Chromium today — Safari and Firefox keep their native behavior of always exiting fullscreen on Esc. - Portals inside fullscreen:
<Dialog.Portal>,<Popover.Portal>,<Menu.Portal>,<Tooltip.Portal>, and every other Base UI portal default todocument.body, which the browser hides while a child element is fullscreen. Base UI detects this and reroutes the portal into the active fullscreen element so popups, menus, and overlays stay visible. Portals with an explicitcontainerprop are respected as-is.
Anatomy
Import the component and assemble its parts:
The Container is the element passed to the browser’s requestFullscreen(). The Trigger toggles the fullscreen state, and the Close only ever exits fullscreen. Place the Close inside the Container so it remains visible while the page is in fullscreen.
Examples
Styling fullscreen state
<Fullscreen.Container>, <Fullscreen.Trigger>, and <Fullscreen.Close> all expose data-fullscreen and data-not-fullscreen attributes so you can show or hide controls based on the current state without managing it manually.
You can also target the container with the standard CSS :fullscreen pseudo-class and style its ::backdrop pseudo-element:
Controlled state
Use open and onOpenChange to control the state externally. The second argument to onOpenChange includes a reason that distinguishes between user interactions:
You can also drive the fullscreen state from a button outside <Fullscreen.Root>. Flipping open to true inside a click handler triggers requestFullscreen() synchronously in the same task as the click, satisfying the spec’s user-activation requirement:
If open is set to true outside the browser’s transient-activation window (no recent user gesture, or more than ~5 seconds after one), the browser rejects the request. Base UI catches the rejection, dispatches onOpenChange(false, { reason: 'none' }) so the controlled state can roll back, and logs a warning in development.
Detached triggers
A <Fullscreen.Trigger> can also live anywhere in the React tree — for example in a global toolbar, away from the element that goes fullscreen. Connect them by creating a handle with Fullscreen.createHandle() and passing it to both <Fullscreen.Root> and <Fullscreen.Trigger>:
Camera 01
Imperative open and close
The handle returned by Fullscreen.createHandle() also exposes imperative methods. Calling handle.open() from any user-gesture handler (click, keypress, command-palette action, etc.) enters fullscreen the same way a trigger press would:
handle.open() carries the same user-activation requirement as <Fullscreen.Trigger>. If invoked outside the activation window, the browser rejects the request and Base UI dispatches onOpenChange(false, { reason: 'none' }) to roll the state back.
Mount only when open
Wrap the <Fullscreen.Container> in a <Fullscreen.Portal> to keep the fullscreen content out of the DOM until the user enters fullscreen. By default the portal renders into document.body and tears its children down again when the user exits.
The user-activation chain is preserved: pressing the trigger flips open, the portal mounts the container synchronously, and requestFullscreen() runs in the same task. Pass keepMounted to keep the children in the DOM even when not in fullscreen — they are hidden via the hidden attribute (matching <Dialog.Portal>) so consumer styles such as width: 100vw don’t leak into the page. Pass container to portal into a custom node.
Detecting unsupported browsers
The Fullscreen API is unavailable in some environments (notably iOS Safari for iPhone). <Fullscreen.Trigger> handles this for you out of the box — when the API is unsupported it sets disabled, aria-disabled="true", and data-disabled, and silently no-ops on activation. Most apps can ship <Fullscreen.Trigger>Enter fullscreen</Fullscreen.Trigger> as-is.
To render entirely different UI in the unsupported case, branch inside the trigger’s render prop. Spread props on the supported branch (so the trigger’s click handler, ref, and ARIA attributes wire up), and render a plain non-interactive node on the unsupported branch — do not spread props there, otherwise you’ll attach button-like behavior to an element that can’t actually enter fullscreen:
Hint to the browser about navigation UI
Pass navigationUI to <Fullscreen.Root> to forward the FullscreenOptions.navigationUI hint to requestFullscreen(). The browser is free to honor user preference over this hint.
Fullscreen any element
Sometimes the fullscreen target lives outside the React tree — most commonly the entire page (document.documentElement). Two complementary entry points cover this case:
- Pass a
targetprop to<Fullscreen.Root>for a managed setup that still gives you triggers, closes, controlled state, anddata-fullscreenreactivity. - Call
Fullscreen.request(element)andFullscreen.exit()directly from a user-gesture handler for fire-and-forget cases that don’t need state management.
target accepts a callback that returns the element (lazy and SSR-safe) or a React.RefObject pointing at the element. <Fullscreen.Container> cannot be used together with target.
For one-off cases the imperative utilities are simplest:
Like <Fullscreen.Trigger> and handle.open(), Fullscreen.request() must run inside a user-gesture handler. The returned promise rejects if the browser refuses or the API isn’t available on the element’s owner document.
API reference
Root
Groups all parts of the fullscreen. Doesn’t render its own HTML element.
defaultOpenbooleanfalse
- Name
- Description
Whether the container is initially displayed in fullscreen.
The Fullscreen API requires a user gesture to enter fullscreen, so an initially open value can only be honored after the user interacts with the page. To render a controlled fullscreen, use the
openprop instead.- Type
- Default
false
openboolean—
- Name
- Description
Whether the container is currently displayed in fullscreen.
To render an uncontrolled fullscreen, use the
defaultOpenprop instead.- Type
onOpenChangefunction—
- Name
- Description
Event handler called when the container enters or exits fullscreen.
- Type
handleFullscreen.Handle—
- Name
- Description
A handle to control the fullscreen imperatively or to associate detached
<Fullscreen.Trigger>components with this root. Create one withFullscreen.createHandle().- Type
navigationUIFullscreenNavigationUI'auto'
- Name
- Description
Hint to the browser describing how the navigation UI should be presented while the container is in fullscreen. Forwarded to
Element.requestFullscreen().- Type
- Default
'auto'
targetFullscreenTarget—
- Name
- Description
An external element to present in fullscreen instead of
<Fullscreen.Container>. Useful for fullscreening the entire page (document.documentElement) or a sibling DOM node.Accepts a callback that returns the element (lazy, SSR-safe) or a
React.RefObjectpointing at the element.<Fullscreen.Container>must not be used together withtarget.- Type
disabledbooleanfalse
- Name
- Description
Whether the component should ignore user interaction.
- Type
- Default
false
childrenReact.ReactNode—
- Name
- Description
The content of the fullscreen.
- Type
Fullscreen.Root.StateHide
Fullscreen.Root.ChangeEventReasonHide
Fullscreen.Root.ChangeEventDetailsHide
Fullscreen.Root.TargetHide
Trigger
A button that toggles the fullscreen state of the container.
Renders a <button> element.
handleFullscreen.Handle—
- Name
- Description
A handle to associate the trigger with a fullscreen root rendered elsewhere in the tree. Create one with
Fullscreen.createHandle().- Type
nativeButtonbooleantrue
- Name
- Description
Whether the component renders a native
<button>element when replacing it via therenderprop. Set tofalseif the rendered element is not a button (for example,<div>).- Type
- Default
true
idstring—
- Name
- Description
ID of the trigger. Forwarded to the rendered element and used internally to identify which trigger activated the fullscreen.
- Type
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-fullscreen
Present when the container is currently displayed in fullscreen.
data-not-fullscreen
Present when the container is not currently displayed in fullscreen.
| Attribute | Description | |
|---|---|---|
data-fullscreen | Present when the container is currently displayed in fullscreen. | |
data-not-fullscreen | Present when the container is not currently displayed in fullscreen. | |
Fullscreen.Trigger.StateHide
Container
The element that is presented in fullscreen.
Renders a <div> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-fullscreen
Present when the container is currently displayed in fullscreen.
data-not-fullscreen
Present when the container is not currently displayed in fullscreen.
| Attribute | Description | |
|---|---|---|
data-fullscreen | Present when the container is currently displayed in fullscreen. | |
data-not-fullscreen | Present when the container is not currently displayed in fullscreen. | |
Fullscreen.Container.StateHide
Close
A button that exits the fullscreen container.
Renders a <button> element.
nativeButtonbooleantrue
- Name
- Description
Whether the component renders a native
<button>element when replacing it via therenderprop. Set tofalseif the rendered element is not a button (for example,<div>).- Type
- Default
true
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-fullscreen
Present when the container is currently displayed in fullscreen.
data-not-fullscreen
Present when the container is not currently displayed in fullscreen.
| Attribute | Description | |
|---|---|---|
data-fullscreen | Present when the container is currently displayed in fullscreen. | |
data-not-fullscreen | Present when the container is not currently displayed in fullscreen. | |
Fullscreen.Close.StateHide
Portal
A portal that mounts its children outside the regular React tree (by default
into <body>) only while the container is in fullscreen.
Useful for “dialog-like” fullscreen UI: the trigger lives in the regular page, and the fullscreen content is absent from the DOM until the user enters fullscreen.
Doesn’t render its own HTML element.
containerFullscreen.Portal.Container—
- Name
- Description
The element to portal into. Defaults to
document.body.- Type
childrenReact.ReactNode—
- Name
- Description
The content of the portal.
- Type
keepMountedbooleanfalse
- Name
- Description
Whether to keep the contents mounted in the DOM while the container is not in fullscreen.
- Type
- Default
false
Fullscreen.Portal.ContainerHide
Handle
A handle to control a Fullscreen imperatively and to associate detached triggers with it.
Pass the handle to <Fullscreen.Root handle={...}> and to any detached
<Fullscreen.Trigger handle={...}> rendered outside the root. Calling
open() from a user-gesture handler enters fullscreen the same way a
trigger press would.
Constructor parameters
storeFullscreenStore—
- Name
- Type
Properties
isOpenreadonly
- Name
- Description
Indicates whether the container is currently in fullscreen.
- Type
- Modifiers
readonly
Methods
open(triggerId?)
- Name
- Description
Enters fullscreen and associates the change with the trigger with the given id, if provided.
requestFullscreen()requires the document to have transient activation, so this method must be called from within a user-gesture event handler (click, keydown, etc.) or from a task that still inherits a recent activation. Calls outside that window will be rejected by the browser; the rejection is caught and reverts state viaonOpenChange(false, { reason: 'none' }).- Parameters
triggerId?—ID of the trigger to associate with the change. If null or omitted, the change is dispatched without an associated trigger.
- Returns
close()
- Name
- Description
Exits fullscreen.
Unlike
open(), exiting fullscreen does not require a user gesture and can be called at any time.- Returns