🪄 YouTube UI Enhancer — Resize Thumbnails & Customize Layout

Get rid of oversized thumbnails, adjust rows, and clean up layout for a more streamlined YouTube experience.

Instalar este script¿?
Script recomendado por el autor

Puede que también te guste 🔊 YouTube Volume Control on Scroll.

Instalar este script
// ==UserScript==
// @name         🪄 YouTube UI Enhancer — Resize Thumbnails & Customize Layout
// @namespace    https://greatest.deepsurf.us/users/1461079
// @version      2.0.1
// @description  Get rid of oversized thumbnails, adjust rows, and clean up layout for a more streamlined YouTube experience.
// @author       Michaelsoft
// @match        *://www.youtube.com/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // WARNING: Users should update their preferences through UI - values below will be overwritten every time the script is updated.
    const userSettings = {
        videosPerRow: 6, // Set how many videos per row (e.g., 4, 5, 6, etc.). Default value is 6.
        shortsPerRow: 12, // Set how many Shorts per row (e.g., 7, 8, 9, etc.). Default value is 12.
        disableShorts: false, // Set to true to completely hide the Shorts section. Default value is false.
        enableShowMoreFix: true, // Set to true to auto-expand Shorts ("Show More" fix). Default value is true.
        hideUIButton: false, // Set to true to hide the floating settings button. Default value is false.
        hideUIButtonShortcut: true, // Set to true to allow Alt+Shift+U shortcut to toggle button visibility. Default value is true.
    };

    const settings = {};
    for (const key in userSettings) {
        settings[key] = GM_getValue(key, userSettings[key]);
    }

    function saveSetting(key, value) {
        GM_setValue(key, value);
        settings[key] = value;
        applyCustomizations();
    }

    function resetSettings() {
        for (const key in userSettings) {
            saveSetting(key, userSettings[key]);
        }
        enableShowMoreFix();
    }

    let customStyle = null;

    function applyCustomizations() {
        if (customStyle) customStyle.remove();
        customStyle = GM_addStyle(`
            ytd-rich-grid-renderer {
                --ytd-rich-grid-items-per-row: ${settings.videosPerRow} !important;
                --ytd-rich-grid-posts-per-row: ${settings.videosPerRow} !important;
                --ytd-rich-grid-slim-items-per-row: ${settings.shortsPerRow} !important;
                --ytd-rich-grid-game-cards-per-row: 7 !important;
                --ytd-rich-grid-gutter-margin: 0px !important;
            }
            ytd-rich-shelf-renderer {
                --ytd-rich-grid-items-per-row: ${settings.shortsPerRow} !important;
            }
            ${settings.disableShorts ? `
                ytd-rich-section-renderer.style-scope.ytd-rich-grid-renderer {
                    display: none !important;
                }
            ` : ''}
        `);
    }

    applyCustomizations();

    let observer;
    function enableShowMoreFix() {
        if (observer) observer.disconnect();
        if (!settings.enableShowMoreFix) return;

        observer = new MutationObserver(() => {
            document.querySelectorAll('ytd-rich-item-renderer[hidden]').forEach(el => {
                el.removeAttribute('hidden');
            });
            document.querySelectorAll('ytd-rich-shelf-renderer').forEach(el => {
                el.setAttribute('is-show-more-hidden', '');
            });
        });

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

    enableShowMoreFix();

    function isDarkTheme() {
        const html = document.querySelector('html');
        return html && html.getAttribute('dark') !== null;
    }

    let uiButton = null;

    function createSettingsButton() {
        uiButton = document.createElement('div');
        uiButton.innerHTML = 'Customize Layout';
        uiButton.style.position = 'fixed';
        uiButton.style.bottom = '20px';
        uiButton.style.right = '20px';
        uiButton.style.zIndex = '9999';
        uiButton.style.padding = '10px 20px';
        uiButton.style.fontSize = '16px';
        uiButton.style.backgroundColor = '#065fd4';
        uiButton.style.color = '#fff';
        uiButton.style.borderRadius = '8px';
        uiButton.style.cursor = 'pointer';
        uiButton.style.boxShadow = '0 4px 12px rgba(0,0,0,0.4)';
        uiButton.style.opacity = '1';
        uiButton.style.transition = 'opacity 0.3s ease';
        uiButton.style.display = settings.hideUIButton ? 'none' : 'block'; // <--- important

        uiButton.onclick = openSettingsMenu;
        document.body.appendChild(uiButton);

        if (settings.hideUIButtonShortcut) {
            window.addEventListener('keydown', (e) => {
                if (e.altKey && e.shiftKey && e.key === 'U') {
                    toggleUIButtonVisibility();
                }
            });
        }
    }

    function toggleUIButtonVisibility() {
        if (uiButton) {
            if (uiButton.style.display === 'none') {
                uiButton.style.display = 'block';
                saveSetting('hideUIButton', false);
            } else {
                uiButton.style.display = 'none';
                saveSetting('hideUIButton', true);
            }
        }
    }

    function openSettingsMenu() {
        const darkMode = isDarkTheme();

        // Disable floating button while modal is open
        uiButton.style.pointerEvents = 'none';
        uiButton.style.opacity = '0.5';

        const overlay = document.createElement('div');
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100vw';
        overlay.style.height = '100vh';
        overlay.style.backgroundColor = 'rgba(0,0,0,0.7)';
        overlay.style.zIndex = '9998';
        overlay.onclick = () => {
            document.body.removeChild(overlay);
            uiButton.style.pointerEvents = 'auto';
            uiButton.style.opacity = '1';
        };

        const menu = document.createElement('div');
        menu.style.position = 'fixed';
        menu.style.top = '50%';
        menu.style.left = '50%';
        menu.style.transform = 'translate(-50%, -50%)';
        menu.style.backgroundColor = darkMode ? '#222' : '#fff';
        menu.style.color = darkMode ? '#eee' : '#000';
        menu.style.padding = '20px 20px 20px 20px';
        menu.style.borderRadius = '12px';
        menu.style.boxShadow = '0 8px 24px rgba(0,0,0,0.6)';
        menu.style.width = '320px';
        menu.style.zIndex = '9999';
        menu.style.fontSize = '14px';
        menu.style.lineHeight = '1.5';
        menu.style.textAlign = 'left';
        menu.onclick = e => e.stopPropagation();

        menu.innerHTML = `
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;">
                <a href="https://greatest.deepsurf.us/en/scripts/533654-youtube-ui-enhancer-resize-thumbnails-modify-layout-more" target="_blank" style="text-decoration:none;color:inherit;font-size:20px;font-weight:bold;">
                    🪄 YouTube UI Enhancer
                </a>
                <button id="closeOverlay" style="background:none;border:none;color:${darkMode ? 'white' : 'black'};font-size:26px;line-height:1;cursor:pointer;padding:0;margin-left:10px;padding-bottom:5px;">×</button>
            </div>
            <label style="display:block; margin-bottom:10px;">Videos Per Row: <input id="videosPerRow" type="number" min="1" value="${settings.videosPerRow}" style="width:60px;"/></label>
            <label style="display:block; margin-bottom:20px;">Shorts Per Row: <input id="shortsPerRow" type="number" min="1" value="${settings.shortsPerRow}" style="width:60px;"/></label>
            <label style="display:block; margin-bottom:10px;">
                <input id="disableShorts" type="checkbox" ${settings.disableShorts ? 'checked' : ''} /> Hide Shorts Section
            </label>
            <label style="display:block; margin-bottom:20px;">
                <input id="enableShowMoreFix" type="checkbox" ${settings.enableShowMoreFix ? 'checked' : ''} /> Expand Shorts Automatically
            </label>
            <div style="margin-top:20px; margin-bottom:20px; border-top:1px solid ${darkMode ? 'white' : 'lightgrey'};"></div>

            <label style="display:block; margin-bottom:20px;">
                <input id="hideUIButton" type="checkbox" ${settings.hideUIButton ? 'checked' : ''} /> Hide Script Button (Alt+Shift+U to Show)
            </label>
            <button id="saveSettingsBtn" style="padding:8px 14px;background:#065fd4;color:white;border:none;border-radius:8px;font-size:15px;font-weight:500;cursor:pointer;">Save Changes</button>
            <button id="resetSettingsBtn" style="margin-left:10px;padding:8px 14px;background:none;color:${darkMode ? 'white' : 'black'};border:1px solid lightgrey;border-radius:8px;font-size:15px;font-weight:500;cursor:pointer;">Reset to Default</button>
        `;

        overlay.appendChild(menu);
        document.body.appendChild(overlay);

        document.getElementById('closeOverlay').onclick = () => {
            document.body.removeChild(overlay);
            uiButton.style.pointerEvents = 'auto';
            uiButton.style.opacity = '1';
        };

        document.getElementById('saveSettingsBtn').onclick = () => {
            const showMoreBefore = settings.enableShowMoreFix;
            saveSetting('videosPerRow', parseInt(document.getElementById('videosPerRow').value, 10));
            saveSetting('shortsPerRow', parseInt(document.getElementById('shortsPerRow').value, 10));
            saveSetting('disableShorts', document.getElementById('disableShorts').checked);
            saveSetting('enableShowMoreFix', document.getElementById('enableShowMoreFix').checked);
            saveSetting('hideUIButton', document.getElementById('hideUIButton').checked);

            if (document.getElementById('hideUIButton').checked) {
                uiButton.style.display = 'none';
            } else {
                uiButton.style.display = 'block';
            }

            if (showMoreBefore !== document.getElementById('enableShowMoreFix').checked) {
                location.reload();
            }

            enableShowMoreFix();
            document.body.removeChild(overlay);
            uiButton.style.pointerEvents = 'auto';
            uiButton.style.opacity = '1';
        };

        document.getElementById('resetSettingsBtn').onclick = () => {
            resetSettings();
            document.body.removeChild(overlay);
            uiButton.style.pointerEvents = 'auto';
            uiButton.style.opacity = '1';
        };
    }

    createSettingsButton();

    // Hide or show button when navigating to the home or subscriptions page
    function checkPageAndToggleUIButton() {
        const isHomeOrSubscriptions = window.location.pathname === '/' || window.location.pathname === '/feed/subscriptions';
        if (isHomeOrSubscriptions) {
            uiButton.style.display = settings.hideUIButton ? 'none' : 'block';
        } else {
            uiButton.style.display = 'none';
        }
    }

    // Listen for page navigation changes and handle button visibility
    window.addEventListener('yt-navigate-finish', checkPageAndToggleUIButton);
    checkPageAndToggleUIButton();
})();