How to properly deal with portal containers and the fullscreen API?
- Dominant language
- TypeScript
- Stars
- 15.9k
- Forks
- 1.6k
- Avg merge
- 3d 9m
- Merged PRs (30d)
- 59
Description
### Discussed in https://github.com/adobe/react-spectrum/discussions/9206
Originally posted by **janvorwerk** November 19, 2025
Hello gents,
My app is using the DOM [fullscreen API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API) for several cases.
Let's consider two of them:
1. Part of the screen needs a lot of screen space… and still has many interactions that will open portaled content (popover…)
2. A dialog (Modal for instance) is showing a Youtube iframe, in which the user wants to trigger full screen mode to better view the video
By default, case 1 does not work because as soon as the component goes fullscreen, the `document.body` seems no longer visible so that any portaled component isn't either.
What I thought was a very smart move was to use the [PortalProvider](https://react-spectrum.adobe.com/react-aria/PortalProvider.html)… despite the fact that it was flagged "UNSAFE".
```ts
export function SkPortalProvider(props: { children: ReactNode }) {
return {props.children};
}
function getDomRoot(): HTMLElement | null {
return document?.fullscreenElement instanceof HTMLElement ? document.fullscreenElement : document.body;
}
```
Clever, ugh? Actually not so much because then, case 2 won't work any longer : as soon as the video goes fullscreen, the portal is changed, so that the dialog containing the video node vanishes…
Then I tried to be more clever than ever 😁…
```ts
function getDomRoot(): HTMLElement | null {
// If there are existing modals/dialogs in document.body, keep using document.body
// to avoid moving them when fullscreen is triggered. This prevents modals from
// disappearing when fullscreen is activated.
const hasExistingModals = document.body?.querySelector('[role="dialog"], [role="alertdialog"]') != null;
if (hasExistingModals) {
return document.body;
}
// Otherwise, use fullscreen element if available (for popovers within fullscreen),
// or document.body as fallback
return document?.fullscreenElement instanceof HTMLElement ? document.fullscreenElement : document.body;
}
```
… but then case 1 no longer works properly…
**Hence my questions: did you guys consider using/supporting fullscreen? How did you do?**
Many thanks in advance 🙏
Contributor guide
Research direction
Start with the linked PortalProvider documentation and the DOM Fullscreen API behavior described in the discussion. Compare the two cases in the issue and the provided getContainer examples, especially how portal content moves when a video enters fullscreen. The issue names no repository files or tests, and a done condition is not defined beyond supporting both scenarios.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100