Skip to contents

Fullscreen

Presents an element in fullscreen using the browser Fullscreen API.

View as Markdown

Preview

Live broadcast

Usage 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. Flipping open from any external handler triggered by a user gesture (including a deferred setTimeout that 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"). The supported state is also exposed on Root, Trigger, Container, and Close so you can render fallback UI.
  • Inside iframes: The hosting <iframe> must include the allowfullscreen attribute (or allow="fullscreen") and any Permissions Policy must permit the fullscreen feature for the document. Without these, requests are rejected with a TypeError.
  • 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 fullscreenchange event and reconciles state automatically — onOpenChange is fired with reason: '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 call event.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 to document.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 explicit container prop are respected as-is.

Anatomy

Import the component and assemble its parts:

Anatomy

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.

Hide trigger in fullscreen, show close only when fullscreen

You can also target the container with the standard CSS :fullscreen pseudo-class and style its ::backdrop pseudo-element:

Native :fullscreen and ::backdrop

Controlled state

Use open and onOpenChange to control the state externally. The second argument to onOpenChange includes a reason that distinguishes between user interactions:

Controlled fullscreen

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:

External trigger

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>:

Detached 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:

Imperative control

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.

Mount only when open

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:

Render alternate UI when unsupported

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.

Prefer maximum screen real estate

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 target prop to <Fullscreen.Root> for a managed setup that still gives you triggers, closes, controlled state, and data-fullscreen reactivity.
  • Call Fullscreen.request(element) and Fullscreen.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.

Fullscreen the page with a managed Root

For one-off cases the imperative utilities are simplest:

Imperative request and exit

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
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 open prop instead.

Type
Default
false
openboolean
Name
Description

Whether the container is currently displayed in fullscreen.

To render an uncontrolled fullscreen, use the defaultOpen prop instead.

Type
onOpenChangefunction
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 with Fullscreen.createHandle().

Type
navigationUIFullscreenNavigationUI'auto'
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.RefObject pointing at the element.

<Fullscreen.Container> must not be used together with target.

Type
disabledbooleanfalse
Description

Whether the component should ignore user interaction.

Type
Default
false
childrenReact.ReactNode
Description

The content of the fullscreen.

Type

Fullscreen.Root.PropsHide

Re-Export of Root props as FullscreenRootProps

Fullscreen.Root.StateHide

Fullscreen.Root.ChangeEventReasonHide

Fullscreen.Root.ChangeEventDetailsHide

Fullscreen.Root.NavigationUIHide

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
Description

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if 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
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 ReactElement or 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.

AttributeDescription
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.PropsHide

Re-Export of Trigger props as FullscreenTriggerProps

Fullscreen.Trigger.StateHide

Container

The element that is presented in fullscreen. Renders a <div> element.

classNamestring | function
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 ReactElement or 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.

AttributeDescription
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.PropsHide

Re-Export of Container props as FullscreenContainerProps

Fullscreen.Container.StateHide

Close

A button that exits the fullscreen container. Renders a <button> element.

nativeButtonbooleantrue
Description

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).

Type
Default
true
classNamestring | function
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 ReactElement or 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.

AttributeDescription
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.PropsHide

Re-Export of Close props as FullscreenCloseProps

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
Description

The element to portal into. Defaults to document.body.

childrenReact.ReactNode
Description

The content of the portal.

Type
keepMountedbooleanfalse
Description

Whether to keep the contents mounted in the DOM while the container is not in fullscreen.

Type
Default
false

Fullscreen.Portal.PropsHide

Re-Export of Portal props as FullscreenPortalProps

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 via onOpenChange(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