YouTube Fullscreen Scroll Disabler

Disable scrolling when YouTube is in fullscreen mode and hide scrollbar. Also hide certain fullscreen UI elements.

Από την 14/10/2025. Δείτε την τελευταία έκδοση.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         YouTube Fullscreen Scroll Disabler
// @namespace    https://youtube.com
// @version      1.0.2
// @description  Disable scrolling when YouTube is in fullscreen mode and hide scrollbar. Also hide certain fullscreen UI elements.
// @author       Lolen10
// @match        *://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?domain=youtube.com
// @grant        none
// @license      GNU GPLv3
// ==/UserScript==

(function() {
    'use strict';

    // Store references to hidden elements and their previous display values
    let hiddenElements = [];

    // Store previous overflow values so we can restore them
    let previousOverflow = { html: '', body: '' };
    let styleElementId = 'ytfs-scrollblocker-style';
    let listenersAdded = false;

    // Event listeners for fullscreen change
    document.addEventListener('fullscreenchange', toggleScrollAndContent, false);
    document.addEventListener('webkitfullscreenchange', toggleScrollAndContent, false); // Older WebKit
    document.addEventListener('mozfullscreenchange', toggleScrollAndContent, false);    // Firefox

    // Also handle when the user presses F (YouTube's fullscreen toggle) or when the player switches programmatically.
    // We'll run the toggle function once on script load to handle pages that already are fullscreen (rare).
    setTimeout(toggleScrollAndContent, 500);

    function toggleScrollAndContent() {
        if (isFullScreen()) {
            enterFullscreenMode();
        } else {
            exitFullscreenMode();
        }
    }

    function isFullScreen() {
        return !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement);
    }

    // ---------- Fullscreen enter/exit ----------

    function enterFullscreenMode() {
        // Disable scroll input
        disableScroll();

        // Hide content below the #single-column-container (existing behavior)
        removeContentBelowContainer();

        // Hide ytp fullscreen grid main content(s)
        hideBySelectorAll('.ytp-fullscreen-grid-main-content');

        // Hide expand button(s)
        hideBySelectorAll('.ytp-fullscreen-grid-expand-button.ytp-button');
    }

    function exitFullscreenMode() {
        // Re-enable scrolling
        enableScroll();

        // Restore previously hidden elements
        restoreHiddenElements();
    }

    // ---------- Hiding / restoring helpers ----------

    function hideBySelectorAll(selector) {
        const nodes = document.querySelectorAll(selector);
        nodes.forEach(node => {
            // Avoid hiding same node twice
            if (!hiddenElements.some(entry => entry.el === node)) {
                hiddenElements.push({ el: node, prevDisplay: node.style.display || '' });
                node.style.display = 'none';
            }
        });
    }

    // Remove all content below #single-column-container (keeps previous behavior but stores prev display)
    function removeContentBelowContainer() {
        const container = document.getElementById('single-column-container');
        if (container) {
            let nextSibling = container.nextElementSibling;
            while (nextSibling) {
                if (!hiddenElements.some(entry => entry.el === nextSibling)) {
                    hiddenElements.push({ el: nextSibling, prevDisplay: nextSibling.style.display || '' });
                    nextSibling.style.display = 'none';
                }
                nextSibling = nextSibling.nextElementSibling;
            }
        }
    }

    function restoreHiddenElements() {
        hiddenElements.forEach(entry => {
            try {
                entry.el.style.display = entry.prevDisplay;
            } catch (err) {
                // element might have been removed from DOM — ignore
            }
        });
        hiddenElements = [];
    }

    // ---------- Scroll blocking ----------

    function preventScroll(e) {
        // Only prevent if in fullscreen (defensive)
        if (!isFullScreen()) return;
        e.preventDefault();
        e.stopPropagation();
        return false;
    }

    function preventKeyScroll(e) {
        if (!isFullScreen()) return;
        // Keys that can scroll the page
        const blockedKeys = [
            'PageUp', 'PageDown', 'Home', 'End', ' '
        ];
        if (blockedKeys.includes(e.key)) {
            // Allow if user is focused in an input/textarea/contenteditable
            const target = e.target;
            const tag = target && target.tagName ? target.tagName.toLowerCase() : '';
            const isEditable = target && (target.isContentEditable || tag === 'input' || tag === 'textarea' || target.getAttribute('role') === 'textbox');
            if (!isEditable) {
                e.preventDefault();
                e.stopPropagation();
                return false;
            }
        }
    }

    function disableScroll() {
        if (listenersAdded) return; // don't add twice

        // Save previous overflow values
        previousOverflow.html = document.documentElement.style.overflow || '';
        previousOverflow.body = document.body.style.overflow || '';

        // Force hide overflow to block scrollbar-based scrolling as a robust fallback
        try {
            document.documentElement.style.overflow = 'hidden';
            document.body.style.overflow = 'hidden';
        } catch (err) {
            // ignore if not allowed
        }

        // Insert style to hide scrollbars (visual)
        if (!document.getElementById(styleElementId)) {
            const style = document.createElement('style');
            style.id = styleElementId;
            style.type = 'text/css';
            style.appendChild(document.createTextNode(
                'html, body { overscroll-behavior: none !important; height: 100% !important; } ' +
                '::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }'
            ));
            (document.head || document.documentElement).appendChild(style);
        }

        // Add wheel & touchmove listeners (passive: false to allow preventDefault)
        window.addEventListener('wheel', preventScroll, { passive: false, capture: true });
        window.addEventListener('touchmove', preventScroll, { passive: false, capture: true });

        // Keydown to block space/arrow/page keys
        window.addEventListener('keydown', preventKeyScroll, { passive: false, capture: true });

        listenersAdded = true;
    }

    function enableScroll() {
        if (!listenersAdded) {
            // still attempt to clean up style/overflow even if listeners weren't marked as added
            cleanupOverflowAndStyle();
            return;
        }

        window.removeEventListener('wheel', preventScroll, { capture: true });
        window.removeEventListener('touchmove', preventScroll, { capture: true });
        window.removeEventListener('keydown', preventKeyScroll, { capture: true });

        cleanupOverflowAndStyle();

        listenersAdded = false;
    }

    function cleanupOverflowAndStyle() {
        // Restore previous overflow values
        try {
            document.documentElement.style.overflow = previousOverflow.html || '';
            document.body.style.overflow = previousOverflow.body || '';
        } catch (err) {
            // ignore
        }

        // Remove style element that hid scrollbars
        const style = document.getElementById(styleElementId);
        if (style && style.parentNode) {
            style.parentNode.removeChild(style);
        }
    }

    // Keep things tidy if the user navigates or the page rebuilds heavy parts of the DOM:
    // If the fullscreen element is removed unexpectedly, make sure we restore.
    const observer = new MutationObserver(() => {
        if (!isFullScreen() && (hiddenElements.length > 0 || listenersAdded)) {
            // Force restore if DOM changed and we are no longer fullscreen
            exitFullscreenMode();
        }
    });

    observer.observe(document.documentElement, { childList: true, subtree: true });

    // Clean up on unload
    window.addEventListener('beforeunload', () => {
        try { observer.disconnect(); } catch (e) {}
        enableScroll();
    });

})();