Restores scrollable fullscreen mode to show title, comments, likes, and related videos. Disables new UI's bottom recommendations.
当前为
// ==UserScript==
// @name YouTube Restore Scrollable Fullscreen
// @namespace burak-tools
// @version 1.9
// @description Restores scrollable fullscreen mode to show title, comments, likes, and related videos. Disables new UI's bottom recommendations.
// @author Waldoocs (https://x.com/Waldoocs) [https://github.com/Waldoocs](https://github.com/Waldoocs)
// @match https://www.youtube.com/*
// @run-at document-idle
// @grant GM_addStyle
// @grant GM.addStyle
// @license MIT
// @compatible firefox
// @compatible chrome
// ==/UserScript==
(function() {
'use strict';
// Cross-browser GM_addStyle
const addStyle = (css) => {
if (typeof GM_addStyle !== 'undefined') {
GM_addStyle(css);
} else if (typeof GM !== 'undefined' && GM.addStyle) {
GM.addStyle(css);
} else {
const style = document.createElement('style');
style.type = 'text/css';
style.textContent = css;
document.head.appendChild(style);
}
};
addStyle(`
ytd-app[fullscreen] {
overflow: auto !important;
}
ytd-app[scrolling] {
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: calc((var(--ytd-app-fullerscreen-scrollbar-width) + 1px)*-1) !important;
bottom: 0 !important;
overflow-x: auto !important;
}
ytd-watch-flexy[fullscreen] #single-column-container.ytd-watch-flexy,
ytd-watch-flexy[fullscreen] #columns.ytd-watch-flexy {
display: flex !important;
}
/* Hide the fullscreen grid with recommended videos */
.ytp-fullscreen-grid,
.ytp-fullscreen-grid-main-content,
.ytp-fullscreen-grid-stills-container,
.ytp-modern-videowall-still,
.ytp-fullscreen-grid-expand-button,
.ytp-fullscreen-grid-hover-overlay {
display: none !important;
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
height: 0 !important;
max-height: 0 !important;
overflow: hidden !important;
}
/* Completely disable grid scrolling CSS variables */
.html5-video-player.ytp-grid-scrollable,
.html5-video-player {
--ytp-grid-scroll-percentage: 0 !important;
--ytp-grid-peek-height: 0px !important;
}
/* Hide any fullscreen education panels and overlays */
.ytp-fullerscreen-edu-panel,
.ytp-cards-teaser,
.ytp-cards-teaser-box,
div[class*="fullerscreen"] {
display: none !important;
opacity: 0 !important;
visibility: hidden !important;
}
`);
// JavaScript to detect and disable new UI scroll behavior
function disableNewUIScroll() {
const player = document.querySelector('.html5-video-player');
if (player) {
// Remove the grid scrollable class
if (player.classList.contains('ytp-grid-scrollable')) {
player.classList.remove('ytp-grid-scrollable');
}
// Force CSS variables to 0
player.style.setProperty('--ytp-grid-scroll-percentage', '0', 'important');
player.style.setProperty('--ytp-grid-peek-height', '0px', 'important');
}
// Remove fullscreen grid elements
const gridElements = document.querySelectorAll('.ytp-fullscreen-grid, .ytp-fullscreen-grid-main-content, .ytp-fullscreen-grid-stills-container, .ytp-modern-videowall-still');
gridElements.forEach(el => {
el.style.display = 'none';
el.style.visibility = 'hidden';
try {
el.remove();
} catch (e) {
console.debug('Element already removed');
}
});
// Remove fullscreen education panels
const panels = document.querySelectorAll('.ytp-fullerscreen-edu-panel, .ytp-cards-teaser, div[class*="fullerscreen"]');
panels.forEach(panel => {
panel.style.display = 'none';
panel.style.visibility = 'hidden';
try {
panel.remove();
} catch (e) {
console.debug('Panel already removed');
}
});
}
// Initialize the script
function init() {
// Run immediately
disableNewUIScroll();
// Watch for DOM changes
const observer = new MutationObserver((mutations) => {
// Only run if there are relevant mutations
const shouldRun = mutations.some(mutation => {
// Check if the mutation is relevant
return (mutation.type === 'childList' && mutation.addedNodes.length > 0) ||
(mutation.type === 'attributes' &&
(mutation.attributeName === 'class' ||
mutation.attributeName === 'style'));
});
if (shouldRun) {
disableNewUIScroll();
}
});
// Start observing the entire document
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class', 'style']
});
// Run periodically as backup
const backupInterval = setInterval(disableNewUIScroll, 300);
// Clean up on script unload
window.addEventListener('unload', () => {
clearInterval(backupInterval);
observer.disconnect();
});
// Intercept scroll events
const handleScroll = () => disableNewUIScroll();
document.addEventListener('scroll', handleScroll, true);
document.addEventListener('wheel', handleScroll, true);
}
// Start the script when the DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();