// ==UserScript==
// @name YouTube Fullscreen Fix — Disable “More Videos” Grid + Preserve Controls
// @namespace orangekite
// @version 1.3.5
// @description Removes the fullscreen recommendations grid & vignette; keeps scroll wheel volume. Prevents tick-4/7 vanish/jiggle on player controls without shifting layout. Restores V-key manual hide. Permanently hides interactive buttons (like, dislike, etc.) in fullscreen.
// @match https://www.youtube.com/*
// @run-at document-start
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function () {
'use strict';
GM_addStyle(`
/* Fullscreen-scoped: match when either the player OR an ancestor is fullscreen */
.html5-video-player:fullscreen,
:fullscreen .html5-video-player {
--ytp-grid-scroll-percentage: 0 !important;
--ytp-grid-peek-height: 0px !important;
--ytp-grid-peek-gradient: 0 !important;
--ytp-controls-peek-height: 0px !important;
--ytp-controls-peek-percent: 0 !important;
}
/* Hide the fullscreen recommendations grid and its moving parts */
.html5-video-player:fullscreen [class*="fullscreen-grid"],
.html5-video-player:fullscreen [class*="fullerscreen-grid"],
.html5-video-player:fullscreen [class*="grid-stills"],
.html5-video-player:fullscreen [class*="videowall-still"],
:fullscreen .html5-video-player [class*="fullscreen-grid"],
:fullscreen .html5-video-player [class*="fullerscreen-grid"],
:fullscreen .html5-video-player [class*="grid-stills"],
:fullscreen .html5-video-player [class*="videowall-still"] {
display: none !important;
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
height: 0 !important;
max-height: 0 !important;
overflow: hidden !important;
}
/* Hide the vignette/scrim/gradient behind the grid */
.html5-video-player:fullscreen [class*="grid-vignette"],
.html5-video-player:fullscreen [class*="grid-scrim"],
.html5-video-player:fullscreen [class*="gradient-bottom"],
:fullscreen .html5-video-player [class*="grid-vignette"],
:fullscreen .html5-video-player [class*="grid-scrim"],
:fullscreen .html5-video-player [class*="gradient-bottom"] {
display: none !important;
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* Hide “fullerscreen” education/teaser overlays */
.html5-video-player:fullscreen [class*="fullerscreen"],
.html5-video-player:fullscreen .ytp-fullerscreen-edu-panel,
.html5-video-player:fullscreen .ytp-cards-teaser,
.html5-video-player:fullscreen .ytp-cards-teaser-box,
:fullscreen .html5-video-player [class*="fullerscreen"],
:fullscreen .html5-video-player .ytp-fullerscreen-edu-panel,
:fullscreen .html5-video-player .ytp-cards-teaser,
:fullscreen .html5-video-player .ytp-cards-teaser-box {
display: none !important;
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* Safety net for lingering vignette/scrim overlays */
.html5-video-player:fullscreen [class*="vignette"],
.html5-video-player:fullscreen [class*="scrim"],
:fullscreen .html5-video-player [class*="vignette"],
:fullscreen .html5-video-player [class*="scrim"] {
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* --- Always show controls in fullscreen (no layout overrides) --- */
.html5-video-player:fullscreen .ytp-chrome-bottom,
:fullscreen .html5-video-player .ytp-chrome-bottom,
.html5-video-player:fullscreen .ytp-chrome-top,
:fullscreen .html5-video-player .ytp-chrome-top {
opacity: 1 !important;
transform: translateY(0) !important;
transition: none !important;
}
/* --- Anti-vanish for tick 4 (no display/bottom changes here) --- */
.html5-video-player:fullscreen.ytp-autohide .ytp-chrome-bottom,
.html5-video-player:fullscreen.ytp-hide-controls .ytp-chrome-bottom,
:fullscreen .html5-video-player.ytp-autohide .ytp-chrome-bottom,
:fullscreen .html5-video-player.ytp-hide-controls .ytp-chrome-bottom,
.html5-video-player:fullscreen .ytp-chrome-bottom,
:fullscreen .html5-video-player .ytp-chrome-bottom {
opacity: 1 !important;
visibility: visible !important;
transform: translateY(0) !important;
pointer-events: auto !important;
}
/* Keep only the control rows/buttons visible; don't touch progress layers */
.html5-video-player:fullscreen .ytp-chrome-bottom :is(
.ytp-left-controls,
.ytp-right-controls,
.ytp-chrome-controls,
.ytp-volume-panel,
.ytp-time-display,
.ytp-subtitles-button,
.ytp-settings-button,
.ytp-fullscreen-button,
.ytp-autonav-toggle-button
),
:fullscreen .html5-video-player .ytp-chrome-bottom :is(
.ytp-left-controls,
.ytp-right-controls,
.ytp-chrome-controls,
.ytp-volume-panel,
.ytp-time-display,
.ytp-subtitles-button,
.ytp-settings-button,
.ytp-fullscreen-button,
.ytp-autonav-toggle-button
) {
opacity: 1 !important;
visibility: visible !important;
transition: none !important;
}
/* Neutralize any “peek” transforms (class-based) */
.html5-video-player:fullscreen [class*="peek"],
:fullscreen .html5-video-player [class*="peek"] {
transform: none !important;
translate: 0 !important;
}
/* Stop tick-4 jiggle: anchor only the chrome container (not the progress bar) */
:is(.html5-video-player:fullscreen, :fullscreen .html5-video-player) .ytp-chrome-bottom {
bottom: 0 !important;
transform: translateY(0) !important;
translate: 0 !important;
margin-bottom: 0 !important;
}
/* If YouTube injects inline translateY on the chrome, zero it */
:is(.html5-video-player:fullscreen, :fullscreen .html5-video-player)
.ytp-chrome-bottom[style*="translate"] {
transform: translateY(0) !important;
}
/* -------- Permanently remove title + interactive overlay in fullscreen (expanded) -------- */
.html5-video-player:fullscreen :is(
.ytp-title,
.ytp-title-link,
.ytp-title-text,
.ytp-title-channel,
.ytp-title-expanded,
.ytp-chrome-top,
.ytp-overlay-bottom-right,
.branding-img-container.ytp-button
),
:fullscreen .html5-video-player :is(
.ytp-title,
.ytp-title-link,
.ytp-title-text,
.ytp-title-channel,
.ytp-title-expanded,
.ytp-chrome-top,
.ytp-overlay-bottom-right,
.branding-img-container.ytp-button
) {
display: none !important;
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
transform: none !important;
}
`);
// ---------------- Core JS helper: prevent tick-4 vanish without altering layout
let manualHideActive = false; // shared flag used by both handlers
const restoreChrome = () => {
const player = document.querySelector('.html5-video-player.ytp-fullscreen');
if (!player) return;
const chrome = player.querySelector('.ytp-chrome-bottom');
if (!chrome) return;
if (manualHideActive) {
// When user pressed V, don't force-show; let our V-handler control it.
return;
}
// Cache the native display value once (whatever YouTube uses in this build)
if (!chrome.dataset.nativeDisplay) {
chrome.dataset.nativeDisplay = getComputedStyle(chrome).display || 'flex';
}
// Undo autohide flags YouTube flips on wheel peek
player.classList.remove('ytp-autohide', 'ytp-hide-controls');
// If they temporarily set display:none, restore the native value
const disp = getComputedStyle(chrome).display;
if (disp === 'none' || chrome.style.display === 'none') {
chrome.style.display = chrome.dataset.nativeDisplay;
}
// Ensure visible (no layout overrides)
chrome.style.opacity = '1';
chrome.style.visibility = 'visible';
chrome.style.transform = 'translateY(0)';
};
// Run on wheel-triggered "peek" and on fullscreen transitions
window.addEventListener('wheel', restoreChrome, { passive: true });
document.addEventListener('fullscreenchange', () => {
manualHideActive = false; // reset on FS boundary
restoreChrome();
}, { passive: true });
// ---------------- V-key: restore manual hide with inline !important
(() => {
const playerSelector = '.html5-video-player.ytp-fullscreen';
const chromeSelector = '.ytp-chrome-bottom';
function applyManualHideStyles(chrome, hide) {
if (hide) {
chrome.style.setProperty('opacity', '0', 'important');
chrome.style.setProperty('visibility', 'hidden', 'important');
chrome.style.removeProperty('transform'); // allow YouTube's own state
} else {
chrome.style.removeProperty('opacity');
chrome.style.removeProperty('visibility');
// Immediately re-show to avoid residual fade
restoreChrome();
}
}
window.addEventListener('keydown', e => {
if (e.key.toLowerCase() !== 'v') return;
const player = document.querySelector(playerSelector);
if (!player) return;
const chrome = player.querySelector(chromeSelector);
if (!chrome) return;
manualHideActive = !manualHideActive;
applyManualHideStyles(chrome, manualHideActive);
}, true);
// Keep behavior consistent if other events fire while hidden
const syncIfNeeded = () => {
if (!manualHideActive) return;
const player = document.querySelector(playerSelector);
const chrome = player?.querySelector(chromeSelector);
if (chrome) applyManualHideStyles(chrome, true);
};
window.addEventListener('wheel', syncIfNeeded, { passive: true });
window.addEventListener('keyup', syncIfNeeded, { passive: true });
})();
})();