IFrame: Pseudo-Fullscreen on iOS
On iOS devices, when entering fullscreen mode the browser uses the native fullscreen API, which can conflict with Kinescope player controls. This script solves the problem: it preserves the original controls and works correctly with dynamic watermarks.
Who this article is for
- Web application developers — need to ensure correct fullscreen behavior on iOS
- Content owners with watermarks — need correct display of dynamic watermarks on iOS
- Frontend developers — need to configure player behavior on mobile devices
When you need pseudo-fullscreen mode on iOS
Use this code if:
- Dynamic watermarks on iOS — watermarks must display correctly in fullscreen mode
- Preserving player controls — it’s important that the original player controls remain accessible
- Correct iOS behavior — correct fullscreen behavior is needed on iOS devices (Safari, Chrome for iOS)
How the script works (3 steps)
- The player sends an event — when the user enters or exits fullscreen mode, the player sends a
KINESCOPE_PLAYER_FULLSCREEN_CHANGEevent. - The script handles the event — saves the current iframe styles and applies fullscreen display styles (or restores the originals).
- Controls are preserved — the original player controls remain accessible, dynamic watermarks work correctly.
Now let’s go through how to set this up.
Setup: step 1 — adding the script to the page
Place the script on the page where the Kinescope player is embedded, before the closing </body> tag or in the <head> section. The script will automatically handle all Kinescope player iframes on the page.
Example placement in HTML:
<!DOCTYPE html>
<html>
<head>
<title>Page with Kinescope Player</title>
</head>
<body>
<!-- Your content -->
<iframe src="https://kinescope.io/embed/pcFNnQGsD59CMKte2SQQaz" width="640" height="360" frameborder="0"></iframe>
<!-- Script for iOS fullscreen mode -->
<script>
// Script code here
</script>
</body>
</html>
DOMContentLoaded event for initialization if placing the script in <head>.Setup: step 2 — the script code
Here is the ready-to-use code for your page:
window.addEventListener('message', (event) => {
if (event.data.type && event.data.type === 'KINESCOPE_PLAYER_FULLSCREEN_CHANGE') {
const frames = document.getElementsByTagName('iframe');
for (let i = 0; i < frames.length; i++) {
if (frames[i].contentWindow === event.source) {
if (event.data.value) {
// Save original styles
if (!frames[i].dataset.originalStyles) {
frames[i].dataset.originalStyles = frames[i].style.cssText;
}
// Apply fullscreen styles
frames[i].style.cssText = `
background: #000;
border: none;
position: fixed;
z-index: 9999;
width: 100%;
height: 100%;
bottom: 0;
right: 0;
top: 0;
left: 0;`;
} else {
// Restore old styles if they were saved
if (frames[i].dataset.originalStyles) {
frames[i].style.cssText = frames[i].dataset.originalStyles;
delete frames[i].dataset.originalStyles;
} else {
frames[i].style.cssText = '';
}
}
break;
}
}
}
});
How it works (in detail)
Here’s what happens when a user opens the page with the player:
- User opens the page — the script starts tracking events from all iframes on the page.
- User enters fullscreen mode — the Kinescope player sends a
KINESCOPE_PLAYER_FULLSCREEN_CHANGEevent withvalue: true. - The script handles the event — finds the right iframe by event source, saves its current styles, and applies fullscreen display styles.
- User exits fullscreen mode — the player sends an event with
value: false, the script restores the original iframe styles.
The KINESCOPE_PLAYER_FULLSCREEN_CHANGE event
The Kinescope player automatically sends this event via window.postMessage when:
- User enters fullscreen mode (
event.data.value === true) - User exits fullscreen mode (
event.data.value === false)
Event format:
{
type: 'KINESCOPE_PLAYER_FULLSCREEN_CHANGE',
value: true // or false
}
iframe style management
When entering fullscreen:
- Current iframe styles are saved in
dataset.originalStyles(to restore later) - Fullscreen display styles are applied:
- Fixed position (
position: fixed) — iframe stays in place when scrolling - Full screen size (
width: 100%,height: 100%) — occupies the entire screen - High z-index (
z-index: 9999) — iframe on top of other elements - Black background (
background: #000) — for correct display
- Fixed position (
When exiting fullscreen:
- Original iframe styles are restored from
dataset.originalStyles - Saved styles are deleted from
dataset
Security
The script verifies that the event originates from the correct iframe (event.source matches iframe.contentWindow). This ensures security when working with multiple iframes on the page — each iframe is handled independently.
How it works:
1. Receive event from iframe
2. Check: event.source === iframe.contentWindow
3. If matched — handle the event
4. If not matched — ignore
Usage examples
Example 1: Simple integration
If you have one player on the page, the code above will work out of the box:
<iframe src="https://kinescope.io/embed/pcFNnQGsD59CMKte2SQQaz" width="640" height="360" frameborder="0"></iframe>
<script>
// Fullscreen handling code
</script>
Example 2: Multiple players on the page
If there are multiple players on the page, the script will automatically handle each one independently:
<iframe src="https://kinescope.io/embed/video1" id="player1" width="640" height="360"></iframe>
<iframe src="https://kinescope.io/embed/video2" id="player2" width="640" height="360"></iframe>
<script>
// Code will handle both players independently
</script>
Example 3: Using with frameworks
If you use React, Vue, or another framework, place the script in the component that mounts after DOM loading:
React:
import { useEffect } from 'react';
function VideoPlayer() {
useEffect(() => {
// Fullscreen handling code
// ... (insert code from step 2)
}, []);
return <iframe src="https://kinescope.io/embed/pcFNnQGsD59CMKte2SQQaz" />;
}
Vue:
export default {
mounted() {
// Fullscreen handling code
// ... (insert code from step 2)
}
}
Done! Now fullscreen mode will work correctly on iOS devices, and player controls will be preserved.
What’s next?
- Embedding — basic player embedding
- IFrame Player API — programmatic player control
- Dynamic watermarks — configuring watermarks for content protection
Still have questions? Write to the support chat within the Kinescope interface — our specialists will help!