Created
August 11, 2025 15:22
-
-
Save mil1i/e941be6170fb49dfc1bb6b99fe71d456 to your computer and use it in GitHub Desktop.
YouTube Full Theater Mode userscript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name YouTube Full Theater Mode | |
| // @namespace azb-truetheater | |
| // @version 0.8 | |
| // @description Apply a custom css when you enter theater mode in YouTube, hiding everything except the video. | |
| // @author Azb | |
| // @match https://www.youtube.com/* | |
| // @license MIT | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| function applyCustomStyles() { | |
| if (document.getElementById('custom-youtube-styles')) return; | |
| const customCSS = ` | |
| ytd-watch-flexy[theater] #full-bleed-container.ytd-watch-flexy { | |
| height: 100vh; | |
| max-height: none; | |
| } | |
| #masthead-container.ytd-app { | |
| margin-top: 0px; | |
| padding-bottom: 5px; | |
| opacity: 0; | |
| transition: margin 0ms, padding 0ms, opacity 400ms; | |
| } | |
| #masthead-container.ytd-app:hover { | |
| margin-top: 0; | |
| padding-bottom: 0; | |
| opacity: 1; | |
| background: #0f0f0f; | |
| } | |
| #page-manager.ytd-app { | |
| margin-top: -6px; | |
| } | |
| ytd-feed-filter-chip-bar-renderer[fluid-width] #chips-content.ytd-feed-filter-chip-bar-renderer { | |
| display: none !important; | |
| } | |
| `; | |
| const styleElement = document.createElement('style'); | |
| styleElement.textContent = customCSS; | |
| styleElement.id = 'custom-youtube-styles'; | |
| document.head.appendChild(styleElement); | |
| } | |
| function removeCustomStyles() { | |
| const styleElement = document.getElementById('custom-youtube-styles'); | |
| if (styleElement) styleElement.remove(); | |
| } | |
| function isOnWatchPage() { | |
| return location.pathname === '/watch' && location.search.includes('v='); | |
| } | |
| let flexyObserver = null; | |
| function observeTheaterMode(watchFlexy) { | |
| if (flexyObserver) flexyObserver.disconnect(); | |
| if (!watchFlexy) return; | |
| flexyObserver = new MutationObserver(() => { | |
| if (isOnWatchPage() && watchFlexy.hasAttribute('theater')) { | |
| applyCustomStyles(); | |
| } else { | |
| removeCustomStyles(); | |
| } | |
| }); | |
| flexyObserver.observe(watchFlexy, { attributes: true, attributeFilter: ['theater'] }); | |
| } | |
| function waitForWatchFlexy(callback) { | |
| const check = () => { | |
| const node = document.querySelector('ytd-watch-flexy'); | |
| if (node) { | |
| callback(node); | |
| return true; | |
| } | |
| return false; | |
| }; | |
| if (check()) return; | |
| const mo = new MutationObserver(() => { | |
| if (check()) mo.disconnect(); | |
| }); | |
| mo.observe(document.body, { childList: true, subtree: true }); | |
| } | |
| function handleNavigationOrLoad() { | |
| if (isOnWatchPage()) { | |
| waitForWatchFlexy((watchFlexy) => { | |
| observeTheaterMode(watchFlexy); | |
| if (watchFlexy.hasAttribute('theater')) { | |
| applyCustomStyles(); | |
| } else { | |
| removeCustomStyles(); | |
| } | |
| }); | |
| } else { | |
| removeCustomStyles(); | |
| if (flexyObserver) flexyObserver.disconnect(); | |
| } | |
| } | |
| window.addEventListener('yt-navigate-finish', () => { | |
| setTimeout(handleNavigationOrLoad, 50); | |
| }); | |
| document.addEventListener('DOMContentLoaded', () => { | |
| setTimeout(handleNavigationOrLoad, 50); | |
| }); | |
| setTimeout(handleNavigationOrLoad, 500); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment