I have a ReactJS app, and I want to be able to:
- Have a button that makes the app go into and out of FullScreen mode, at a specific element.
- Detect when the user uses other methods to enter/exit FullScreen mode (like the back button on a mobile device, or the escape key on a desktop).
- (Related to point 2) Update the UI to reflect that the user is in fullscreen mode or not.
Is it possible?
I've learned while reading the documentation that there is no support for "fullscreen" event in ReactJS, so one would have to configure such behavior manually.
To make things a bit more complicated, I learned by reading the Mozilla "Guide to the Fullscreen API" documentation that not all browsers use the same functions and events to interact with the fullscreen functionality. There is the "standard" API, the Webkit API, Mozilla API and Microsoft API.
I've looked around at the following Stack Overflow posts and Documentation, and found that there are several questions that answer pieces of this puzzle, but there isn't yet something that puts it all together and fulfills all my requirements at once.
- The MDN Fullscreen API is a good starting point. It seems that the
documentelement does provide methods to enter and exist the full screen:Element.requestFullscreen()andDocument.exitFullscreen(). IT also mentions the existence of thefullscreenchangeevent. This knowledge can be used for point #1. And this SO answer "Enter and exit full screen in browser using JavaScript" seems to get close to what I want, but it is not a React solution, and lacks support for all browsers. - The Microsoft Full Screen API has also a very nice example of how to accomplish the behavior with plain HTML + plain Javascript (but again, it is not the ReactJS solution I'm looking for):
<!DOCTYPE html>
<html>
<head>
<title>msFullscreenElement test</title>
<style>
/* Add a white border*/
div {
border: solid 2px white;
}
</style>
</head>
<body>
<div class="fullScreen" id="div-1" style="width:600px; height:350px; background-color:yellow">
This is Div 1
</div><p></p>
<div class="noFullScreen" id="div-2" style="width:600px; height:350px; background-color:red">
This is Div 2
</div>
<script>
var inFullScreen = false; // flag for in or out of full-screen mode.
// set up div that doesn't go into full-screen mode on the click event
var nfsClass = document.getElementsByClassName("noFullScreen");
for (var i = 0; i < nfsClass.length; i++) {
nfsClass[i].addEventListener("click", function (evt) {
evt.target.innerHTML = getFSWindow();
}, false);
}
var fsClass = document.getElementsByClassName("fullScreen");
for (var i = 0; i < fsClass.length; i++) {
fsClass[i].addEventListener("click", function (evt) {
if (inFullScreen == false) {
makeFullScreen(evt.target); // open to full screen
evt.target.innerHTML = getFSWindow().id;
} else {
reset();
}
}, false);
}
// request full screen across several browsers
function makeFullScreen(divObj) {
if (divObj.requestFullscreen) {
divObj.requestFullscreen();
}
else if (divObj.msRequestFullscreen) {
divObj.msRequestFullscreen();
}
else if (divObj.mozRequestFullScreen) {
divObj.mozRequestFullScreen();
}
else if (divObj.webkitRequestFullscreen) {
divObj.webkitRequestFullscreen();
}
inFullScreen = true;
return;
}
// reset full screen across several browsers
function reset() {
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
inFullScreen = false;
return;
}
// get full screen element across several browsers
function getFSWindow() {
if (document.fullscreenElement) {
return document.fullscreenElement;
}
else if (document.msFullscreenElement) {
return document.msFullscreenElement;
}
else if (document.mozFullScreenElement) {
return document.mozFullScreenElement;
}
else if (document.webkitFullscreenElement) {
return document.webkitFullscreenElement;
}
}
</script>
</body>
</html>
- The "Document: fullscreenchange event", I've learned that one can listen to the
fullscreenchangeevent. So it seems quite a good starting point for requirement #2. - HTML5 Fullscreen Event Listener: This seems like an interesting answer, because it reveals that there are different ways browsers might trigger the event (
"fullscreenchange","webkitfullscreenchange","mozfullscreenchange"and"msfullscreenchange")). - Is fullscreenchange event supported in React?: This is the closes answer I found that would accomplish what I need. It shows how to use React's
useLayoutEffectto override(?) thedocument.onfullscreenchangeevent, but I want to add an event listener, not to modify things in a hacky way. So, I want a better solution. - And again, the Microsoft Full Screen API has a very nice example of how to "Detect full-screen mode changes" with plain HTML + plain Javascript (yet again, this is not a full ReactJS solution, and doesn't cover all browsers):
if (document.requestFullscreen) {
document.addEventListener("fullscreenchange", function () {
if (document.fullscreenElement != null) {
console.info("Went full screen");
} else {
console.info("Exited full screen");
}
});
}
else if (document.msRequestFullscreen) {
document.addEventListener("MSFullscreenChange", function () {
if (document.msFullscreenElement != null) {
console.info("Went full screen");
} else {
console.info("Exited full screen");
}
});
}
- And finally this "Detecting if a browser is in full screen mode" SO Answer points to this Blog post that shows similarly how to request, exist and listen for full screen events (but it uses some deprecated functions).
So, is there a way to combine all the pieces of information into a simple solution that fulfils my objectives with ReactJS?
The solution I found is far from perfect, and definitely not simple, but it was the best I was able to come up with my limited ReactJS experience.
So, having said that, let's dive into it.
The UI
First, let's build the UI. Leaving all the boilerplate HTML, we will need:
id="app").<button>).So the goal is that when the
<button>is clicked, the browser fullscreens into theapp<div>element, or out of it.Then whenever the user enters or exits FullScreen, the buttons text should be updated regardless of how it happened.
Helper functions for the FullScreen API
Now let's make use of the FullScreen API. We'll need helper functions to interact with the API on different browsers (you can read more about it on the Guide to the Fullscreen API):
This is how the helper functions will look like:
Notice how we check for all variants of the FullScreen events (normal,
webkit,mozandms), not all of them capitalize the wordScreen, and the function to exist the FullScreen may have different names.React JS: Toggle FullScreen Button
Now with the above out of the way, we can finally begin playing with the ReactJS logic. Let's start with the button's click function. We need:
isFullScreen) that tracks if the page is in FullScreen mode.toggleFullScreenfunction that is compatible with React's States. We'll use ReactuseCallback. It must: ** Enter FullScreen mode on the selectedappelement ifisFullScreenis nottrue. ** Exit FullScreen mode ifisFullScreenistrue.The code would look like this:
React JS: Listen for FullScreen changes
Finally, it is time to track the FullScreen status. For that we'll need:
useEffect.isFulllScreenin the previous step).The code would look like this:
Final solution
When it is all put together, it looks like this:
This sample does not take care of handling unhappy scenarios (i.e. FullScreen being disabled), so be sure to check documentation and implement those yourself as you see fit. :)