BlogKovo

How to Handle Fullscreen Problems in Embedded Browser Games

October 16, 2026 · 5 min read
How to Handle Fullscreen Problems in Embedded Browser Games

Fullscreen in an embedded game fails for one of three reasons: the iframe was not given permission, the browser does not offer fullscreen for that kind of element, or the request did not come from a real click or tap. This guide shows each case with what we measured, then gives you a fallback that works when the browser has no fullscreen at all.

Case 1: The iframe has no permission

A frame from another site may only go fullscreen if the page that embeds it allows it. That is the allow="fullscreen" attribute (or the older allowfullscreen). We tested a cross-origin test frame with a button that called requestFullscreen():

IframeResult after a click on the button inside the frame
Without allow="fullscreen"Failed: "Disallowed by permissions policy". document.fullscreenEnabled was false in the frame, and the console showed "Permissions policy violation: fullscreen is not allowed in this document."
With allow="fullscreen"Worked, and document.fullscreenEnabled was true

MDN states the same rule for its legacy form: iframes opt in with the allowfullscreen attribute.

Fix: use the full embed code, which includes allow="fullscreen; autoplay; gamepad; pointer-lock" and allowfullscreen. The most common cause of a dead fullscreen button is a trimmed embed code.

Case 2: The request is not a user action

MDN notes that fullscreen requests need to be made from within an event handler, or they are denied. If you build your own fullscreen button, call requestFullscreen() directly in the click handler. Do not call it after a timer or a network request.

Case 3: The browser does not support it for this element

This is the case you cannot fix with an attribute. MDN's browser compatibility data for Element.requestFullscreen() records, for Safari on iOS and iPadOS:

  • support from version 16.4, marked as a partial implementation;
  • the note: "Only available on iPad, not on iPhone";
  • a second note that it shows an overlay button that cannot be disabled, and swiping down exits fullscreen, which makes it unsuitable for some uses such as games.

So on an iPhone, a button that asks the page's frame to go fullscreen has nothing to call. The game may still offer its own fullscreen or "rotate" prompt. We cannot test iPhones here, so check this on a real device.

The fallback: a CSS "pretend fullscreen"

If native fullscreen is missing or fails, make the game fill the screen yourself. The wrapper becomes a fixed layer covering the viewport, with a visible exit button:

<div class="wrap" id="w">
  <button class="exit" id="exit">Exit fullscreen</button>
  <iframe src="https://playkovo.com/embed/block-bash" title="Block Bash"
    allow="fullscreen; autoplay; gamepad; pointer-lock" allowfullscreen></iframe>
</div>
<button id="go">Fullscreen</button>

<style>
.wrap { position: relative; max-width: 960px; aspect-ratio: 16/9; margin: 0 auto; background: #000; }
.wrap iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.wrap.is-pseudo-fs { position: fixed; inset: 0; z-index: 2147483000; max-width: none; aspect-ratio: auto; width: 100%; height: 100dvh; }
.wrap .exit { display: none; position: absolute; top: 8px; right: 8px; z-index: 2; padding: 8px 12px; }
.wrap.is-pseudo-fs .exit { display: block; }
</style>

<script>
const w = document.getElementById("w");
function setPseudo(on) {
  w.classList.toggle("is-pseudo-fs", on);
  document.documentElement.style.overflow = on ? "hidden" : "";
}
go.onclick = async () => {
  if (w.requestFullscreen) {
    try { await w.requestFullscreen(); return; } catch (e) {}
  }
  setPseudo(true);
};
exit.onclick = () => setPseudo(false);
addEventListener("keydown", (e) => { if (e.key === "Escape") setPseudo(false); });
</script>

Note that the script asks for fullscreen on the wrapper, not on the iframe, so your exit button and any overlays come with it, and falls back to the CSS layer when the call is missing or refused.

We tested this page in Chrome 155:

TestResult
Desktop 1280 by 720, native API availableNative fullscreen used; the wrapper measured 1280 by 720, the same as the viewport
Phone profile (Pixel 7) with the Fullscreen API removed to imitate an iPhoneFallback used; the wrapper measured 412 by 839, the same as the viewport
Escape in fallback modeWrapper returned to its normal class

That second test is a simulation. A real iPhone has its own browser chrome, safe-area insets and a keyboard-less gesture to leave, so test the fallback on a real device and add padding: env(safe-area-inset-*) if content hides behind the notch.

Mobile fullscreen tips

  • Use 100dvh, not 100vh. Mobile browsers have an address bar that changes the visible height. dvh follows it.
  • Offer a visible exit. Do not rely on the user knowing a swipe or a key.
  • Lock nothing. Do not call orientation locks you cannot undo. Many portrait games expect portrait, and landscape games work better rotated, so let the player rotate the phone.
  • Hide only your own chrome. Games may show their own fullscreen button. If both appear, do not fight it. Offer yours only where the game has none.

A quick diagnosis

  1. Does the iframe carry allow="fullscreen"? If not, add it.
  2. Is your button calling requestFullscreen() inside the click handler?
  3. Is the device an iPhone? Use the CSS fallback.
  4. Does the console say "Permissions policy violation"? The embed code lost its allow list.
  5. Does fullscreen work in the normal browser but not inside another app's built-in browser? We did not test in-app browsers, but they are a likely place for restrictions, so offer a link to open the page in the normal browser.

A game to test it on

Try it live · PlayKovo catalog

Warbirds.io game artworkDesktopsupportedMobilesupported

A free, browser-based multiplayer dogfighter set in a Minecraft-inspired voxel world. Two teams, planes, tanks, and ships, one golden ring to fight over.

Related Posts