useHooks.iov4.1.2
DocsBlogGitHub
Hooks
No hooks found in any category.

useFullscreen

dom

Installation

npx usehooks-cli@latest add use-fullscreen

Description

A hook for managing fullscreen mode using the Fullscreen API. Provides cross-browser support for entering and exiting fullscreen mode with callback options.

Parameters

NameTypeDefaultDescription
targetRef?React.RefObject<Element>-Reference to the element to make fullscreen (defaults to document.documentElement)
options?UseFullscreenOptions-Configuration options for fullscreen behavior

Parameter Properties

options properties:

NameTypeDescription
onEnter?() => voidCallback fired when entering fullscreen mode
onExit?() => voidCallback fired when exiting fullscreen mode
onError?(error: Error) => voidCallback fired when fullscreen operation fails

Return Type

UseFullscreenReturn
PropertyTypeDescription
isFullscreenbooleanWhether currently in fullscreen mode
isSupportedbooleanWhether the Fullscreen API is supported
enter(element?: Element) => Promise<void>Enter fullscreen mode for the specified element
exit() => Promise<void>Exit fullscreen mode
toggle(element?: Element) => Promise<void>Toggle fullscreen mode
elementElement | nullThe current fullscreen element

Examples

Basic Fullscreen Toggle

Simple fullscreen toggle for the entire page

1import { useFullscreen } from '@usehooks/use-fullscreen'; 2 3function FullscreenDemo() { 4 const { 5 isFullscreen, 6 isSupported, 7 enter, 8 exit, 9 toggle 10 } = useFullscreen(); 11 12 if (!isSupported) { 13 return <div>Fullscreen not supported</div>; 14 } 15 16 return ( 17 <div style={{ padding: '20px' }}> 18 <h2>Fullscreen Demo</h2> 19 <p>Status: {isFullscreen ? 'Fullscreen' : 'Normal'}</p> 20 21 <div> 22 <button onClick={() => enter()}>Enter Fullscreen</button> 23 <button onClick={() => exit()}>Exit Fullscreen</button> 24 <button onClick={() => toggle()}>Toggle Fullscreen</button> 25 </div> 26 27 {isFullscreen && ( 28 <div style={{ 29 position: 'fixed', 30 top: 0, 31 left: 0, 32 right: 0, 33 bottom: 0, 34 backgroundColor: 'black', 35 color: 'white', 36 display: 'flex', 37 alignItems: 'center', 38 justifyContent: 'center', 39 flexDirection: 'column' 40 }}> 41 <h1>Fullscreen Mode</h1> 42 <button onClick={() => exit()}>Exit Fullscreen</button> 43 </div> 44 )} 45 </div> 46 ); 47}

Element-specific Fullscreen

Make a specific element fullscreen with ref

1import { useFullscreen } from '@usehooks/use-fullscreen'; 2import { useRef } from 'react'; 3 4function VideoPlayer() { 5 const videoRef = useRef<HTMLVideoElement>(null); 6 const { 7 isFullscreen, 8 enter, 9 exit, 10 toggle 11 } = useFullscreen(videoRef, { 12 onEnter: () => console.log('Video entered fullscreen'), 13 onExit: () => console.log('Video exited fullscreen'), 14 onError: (error) => console.error('Fullscreen error:', error) 15 }); 16 17 return ( 18 <div> 19 <video 20 ref={videoRef} 21 width="400" 22 height="300" 23 controls 24 style={{ 25 border: isFullscreen ? 'none' : '2px solid #ccc', 26 backgroundColor: 'black' 27 }} 28 > 29 <source src="/sample-video.mp4" type="video/mp4" /> 30 Your browser does not support the video tag. 31 </video> 32 33 <div style={{ marginTop: '10px' }}> 34 <button onClick={() => toggle()}> 35 {isFullscreen ? 'Exit' : 'Enter'} Fullscreen 36 </button> 37 <p>Video is {isFullscreen ? 'fullscreen' : 'normal'}</p> 38 </div> 39 </div> 40 ); 41}

Image Gallery Fullscreen

Fullscreen image viewer with navigation

1import { useFullscreen } from '@usehooks/use-fullscreen'; 2import { useRef, useState } from 'react'; 3 4function ImageGallery() { 5 const imageRef = useRef<HTMLDivElement>(null); 6 const [currentImage, setCurrentImage] = useState(0); 7 const { 8 isFullscreen, 9 enter, 10 exit 11 } = useFullscreen(imageRef); 12 13 const images = [ 14 '/image1.jpg', 15 '/image2.jpg', 16 '/image3.jpg' 17 ]; 18 19 const nextImage = () => { 20 setCurrentImage((prev) => (prev + 1) % images.length); 21 }; 22 23 const prevImage = () => { 24 setCurrentImage((prev) => (prev - 1 + images.length) % images.length); 25 }; 26 27 const handleImageClick = () => { 28 if (!isFullscreen) { 29 enter(); 30 } 31 }; 32 33 return ( 34 <div> 35 <div 36 ref={imageRef} 37 style={{ 38 position: 'relative', 39 width: isFullscreen ? '100vw' : '400px', 40 height: isFullscreen ? '100vh' : '300px', 41 backgroundColor: 'black', 42 display: 'flex', 43 alignItems: 'center', 44 justifyContent: 'center', 45 cursor: isFullscreen ? 'default' : 'pointer' 46 }} 47 onClick={handleImageClick} 48 > 49 <img 50 src={images[currentImage]} 51 alt={`Image ${currentImage + 1}`} 52 style={{ 53 maxWidth: '100%', 54 maxHeight: '100%', 55 objectFit: 'contain' 56 }} 57 /> 58 59 {isFullscreen && ( 60 <> 61 <button 62 onClick={(e) => { 63 e.stopPropagation(); 64 prevImage(); 65 }} 66 style={{ 67 position: 'absolute', 68 left: '20px', 69 top: '50%', 70 transform: 'translateY(-50%)', 71 fontSize: '24px', 72 padding: '10px' 73 }} 74 > 7576 </button> 77 78 <button 79 onClick={(e) => { 80 e.stopPropagation(); 81 nextImage(); 82 }} 83 style={{ 84 position: 'absolute', 85 right: '20px', 86 top: '50%', 87 transform: 'translateY(-50%)', 88 fontSize: '24px', 89 padding: '10px' 90 }} 91 > 9293 </button> 94 95 <button 96 onClick={(e) => { 97 e.stopPropagation(); 98 exit(); 99 }} 100 style={{ 101 position: 'absolute', 102 top: '20px', 103 right: '20px', 104 fontSize: '18px', 105 padding: '10px' 106 }} 107 > 108109 </button> 110 </> 111 )} 112 </div> 113 114 {!isFullscreen && ( 115 <div style={{ marginTop: '10px' }}> 116 <button onClick={prevImage}>Previous</button> 117 <span style={{ margin: '0 10px' }}> 118 {currentImage + 1} of {images.length} 119 </span> 120 <button onClick={nextImage}>Next</button> 121 <p>Click image to view fullscreen</p> 122 </div> 123 )} 124 </div> 125 ); 126}

Dependencies

react

Notes

  • Requires user gesture to enter fullscreen mode
  • Cross-browser support for webkit, moz, and ms prefixes
  • Automatically handles fullscreen change events
  • Cleans up event listeners on component unmount
  • Some browsers may have restrictions on which elements can be fullscreen
  • Fullscreen mode may be blocked by browser settings or extensions

Implementation

1'use client'; 2 3import { useState, useEffect, useCallback, useRef } from "react"; 4 5export interface UseFullscreenOptions { 6 onEnter?: () => void; 7 onExit?: () => void; 8 onError?: (error: Error) => void; 9} 10 11export interface UseFullscreenReturn { 12 isFullscreen: boolean; 13 isSupported: boolean; 14 enter: (element?: Element) => Promise<void>; 15 exit: () => Promise<void>; 16 toggle: (element?: Element) => Promise<void>; 17 element: Element | null; 18} 19 20export function useFullscreen( 21 targetRef?: React.RefObject<Element>, 22 options: UseFullscreenOptions = {} 23): UseFullscreenReturn { 24 const [isFullscreen, setIsFullscreen] = useState(false); 25 const [element, setElement] = useState<Element | null>(null); 26 const optionsRef = useRef(options); 27 28 // Update options ref when options change 29 useEffect(() => { 30 optionsRef.current = options; 31 }, [options]); 32 33 // Check if fullscreen is supported 34 const isSupported = Boolean( 35 document.fullscreenEnabled || 36 (document as any).webkitFullscreenEnabled || 37 (document as any).mozFullScreenEnabled || 38 (document as any).msFullscreenEnabled 39 ); 40 41 // Handle fullscreen change events 42 useEffect(() => { 43 const handleFullscreenChange = () => { 44 const fullscreenElement = 45 document.fullscreenElement || 46 (document as any).webkitFullscreenElement || 47 (document as any).mozFullScreenElement || 48 (document as any).msFullscreenElement; 49 50 const isCurrentlyFullscreen = Boolean(fullscreenElement); 51 setIsFullscreen(isCurrentlyFullscreen); 52 setElement(fullscreenElement); 53 54 if (isCurrentlyFullscreen) { 55 optionsRef.current.onEnter?.(); 56 } else { 57 optionsRef.current.onExit?.(); 58 } 59 }; 60 61 const handleFullscreenError = () => { 62 optionsRef.current.onError?.( 63 new Error("Failed to enter fullscreen mode") 64 ); 65 }; 66 67 // Add event listeners for different browsers 68 document.addEventListener("fullscreenchange", handleFullscreenChange); 69 document.addEventListener("webkitfullscreenchange", handleFullscreenChange); 70 document.addEventListener("mozfullscreenchange", handleFullscreenChange); 71 document.addEventListener("MSFullscreenChange", handleFullscreenChange); 72 73 document.addEventListener("fullscreenerror", handleFullscreenError); 74 document.addEventListener("webkitfullscreenerror", handleFullscreenError); 75 document.addEventListener("mozfullscreenerror", handleFullscreenError); 76 document.addEventListener("MSFullscreenError", handleFullscreenError); 77 78 // Set initial state 79 handleFullscreenChange(); 80 81 return () => { 82 document.removeEventListener("fullscreenchange", handleFullscreenChange); 83 document.removeEventListener( 84 "webkitfullscreenchange", 85 handleFullscreenChange 86 ); 87 document.removeEventListener( 88 "mozfullscreenchange", 89 handleFullscreenChange 90 ); 91 document.removeEventListener( 92 "MSFullscreenChange", 93 handleFullscreenChange 94 ); 95 96 document.removeEventListener("fullscreenerror", handleFullscreenError); 97 document.removeEventListener( 98 "webkitfullscreenerror", 99 handleFullscreenError 100 ); 101 document.removeEventListener("mozfullscreenerror", handleFullscreenError); 102 document.removeEventListener("MSFullscreenError", handleFullscreenError); 103 }; 104 }, []); 105 106 const enter = useCallback( 107 async (elementToFullscreen?: Element) => { 108 if (!isSupported) { 109 throw new Error("Fullscreen API is not supported"); 110 } 111 112 const target = 113 elementToFullscreen || targetRef?.current || document.documentElement; 114 115 if (!target) { 116 throw new Error("No element provided for fullscreen"); 117 } 118 119 try { 120 if (target.requestFullscreen) { 121 await target.requestFullscreen(); 122 } else if ((target as any).webkitRequestFullscreen) { 123 await (target as any).webkitRequestFullscreen(); 124 } else if ((target as any).mozRequestFullScreen) { 125 await (target as any).mozRequestFullScreen(); 126 } else if ((target as any).msRequestFullscreen) { 127 await (target as any).msRequestFullscreen(); 128 } else { 129 throw new Error("Fullscreen API is not supported"); 130 } 131 } catch (error) { 132 optionsRef.current.onError?.(error as Error); 133 throw error; 134 } 135 }, 136 [isSupported, targetRef] 137 ); 138 139 const exit = useCallback(async () => { 140 if (!isSupported) { 141 throw new Error("Fullscreen API is not supported"); 142 } 143 144 try { 145 if (document.exitFullscreen) { 146 await document.exitFullscreen(); 147 } else if ((document as any).webkitExitFullscreen) { 148 await (document as any).webkitExitFullscreen(); 149 } else if ((document as any).mozCancelFullScreen) { 150 await (document as any).mozCancelFullScreen(); 151 } else if ((document as any).msExitFullscreen) { 152 await (document as any).msExitFullscreen(); 153 } else { 154 throw new Error("Fullscreen API is not supported"); 155 } 156 } catch (error) { 157 optionsRef.current.onError?.(error as Error); 158 throw error; 159 } 160 }, [isSupported]); 161 162 const toggle = useCallback( 163 async (elementToFullscreen?: Element) => { 164 if (isFullscreen) { 165 await exit(); 166 } else { 167 await enter(elementToFullscreen); 168 } 169 }, 170 [isFullscreen, enter, exit] 171 ); 172 173 return { 174 isFullscreen, 175 isSupported, 176 enter, 177 exit, 178 toggle, 179 element, 180 }; 181} 182