Reddit - Sidebar Toggle, Text Zoom, & Centered Layout

Declutter Reddit with a hideable sidebar and adjustable text size. Center-aligned content with optimal reading width. Zoom settings saved across sessions.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Reddit - Sidebar Toggle, Text Zoom, & Centered Layout
// @namespace    http://tampermonkey.net/
// @version      1.8.1
// @description  Declutter Reddit with a hideable sidebar and adjustable text size. Center-aligned content with optimal reading width. Zoom settings saved across sessions.
// @author       mrbrownjeremy & Claude AI
// @match        https://www.reddit.com/*
// @icon         https://www.redditstatic.com/shreddit/assets/favicon/64x64.png
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // Get saved zoom level or default to 1.05 (105%)
    let zoomLevel = GM_getValue('textZoom', 1.05);

    // Function to apply zoom
    function applyZoom(zoom) {
        zoomLevel = zoom;
        GM_setValue('textZoom', zoom);
        document.documentElement.style.setProperty('--reddit-text-zoom', zoom);
    }

    // Add CSS to hide sidebar, style toggle button, and adjust layout
    GM_addStyle(`
        /* Set custom property for zoom */
        :root {
            --reddit-text-zoom: ${zoomLevel};
        }

        /* Hide the right sidebar by default */
        #right-sidebar-container {
            display: none !important;
        }

        /* Show sidebar when toggled */
        body.sidebar-visible #right-sidebar-container {
            display: block !important;
        }

        /* Adjust grid layout when sidebar is hidden */
        body:not(.sidebar-visible) .main-container {
            grid-template-columns: 1fr !important;
            place-content: center !important;
        }

        /* Center and constrain main content for readability when sidebar is hidden */
        body:not(.sidebar-visible) .main-container > main {
            max-width: min(75ch, 80vw) !important;
            margin: 0 auto !important;
            width: 100% !important;
        }

        /* Keep comfortable margins */
        body:not(.sidebar-visible) .main-container > main {
            padding-left: 1rem;
            padding-right: 1rem;
        }

        /* Apply text zoom more aggressively to all content elements */
        .main-container > main *,
        .main-container > main {
            font-size: calc(1em * var(--reddit-text-zoom)) !important;
            line-height: calc(1.5 * var(--reddit-text-zoom)) !important;
        }

        /* Specifically target post title - VERY aggressive selectors */
        h1[slot="title"],
        h1[id^="post-title-"],
        shreddit-post h1,
        [slot="title"],
        .post-title,
        .main-container > main h1 {
            font-size: calc(1.75em * var(--reddit-text-zoom)) !important;
            font-weight: 600 !important;
        }

        /* Other headings */
        h2, h3 {
            font-size: calc(1.35em * var(--reddit-text-zoom)) !important;
        }

        /* Target comment text */
        shreddit-comment p,
        .md p,
        [slot="comment"] {
            font-size: calc(1em * var(--reddit-text-zoom)) !important;
        }

        /* Control panel container */
        #reddit-controls {
            position: fixed;
            top: 100px;
            right: 10px;
            z-index: 9999;
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        /* Toggle button styling */
        #sidebar-toggle {
            background: #FF4500;
            color: white;
            border: none;
            border-radius: 4px;
            padding: 10px 15px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            transition: background 0.2s;
        }

        #sidebar-toggle:hover {
            background: #ff5722;
        }

        /* Zoom controls styling */
        #zoom-controls {
            background: #0079D3;
            color: white;
            border-radius: 4px;
            padding: 8px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 12px;
        }

        .zoom-btn {
            background: rgba(255,255,255,0.2);
            color: white;
            border: none;
            border-radius: 3px;
            width: 24px;
            height: 24px;
            cursor: pointer;
            font-size: 16px;
            font-weight: bold;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.2s;
        }

        .zoom-btn:hover {
            background: rgba(255,255,255,0.3);
        }

        #zoom-display {
            min-width: 45px;
            text-align: center;
            font-weight: bold;
        }

        /* Make sure controls don't get zoomed */
        #reddit-controls,
        #reddit-controls * {
            font-size: initial !important;
            line-height: initial !important;
        }
    `);

    // Create control panel container
    const controlPanel = document.createElement('div');
    controlPanel.id = 'reddit-controls';

    // Create sidebar toggle button
    const toggleButton = document.createElement('button');
    toggleButton.id = 'sidebar-toggle';
    toggleButton.textContent = '◀ Sidebar';
    toggleButton.title = 'Toggle Sidebar';

    // Function to format zoom display as relative value
    function formatZoomDisplay(zoom) {
        const percent = Math.round(zoom * 100);
        const diff = percent - 100;

        if (diff === 0) {
            return '±0';
        } else if (diff > 0) {
            return '+' + diff;
        } else {
            return diff.toString(); // negative sign is already included
        }
    }

    // Create zoom controls
    const zoomControls = document.createElement('div');
    zoomControls.id = 'zoom-controls';
    zoomControls.innerHTML = `
        <button class="zoom-btn" id="zoom-decrease" title="Decrease text size">−</button>
        <span id="zoom-display">${formatZoomDisplay(zoomLevel)}</span>
        <button class="zoom-btn" id="zoom-increase" title="Increase text size">+</button>
    `;

    // Add buttons to control panel
    controlPanel.appendChild(toggleButton);
    controlPanel.appendChild(zoomControls);

    // Toggle sidebar functionality
    toggleButton.addEventListener('click', function() {
        document.body.classList.toggle('sidebar-visible');
        if (document.body.classList.contains('sidebar-visible')) {
            toggleButton.textContent = '▶ Hide';
        } else {
            toggleButton.textContent = '◀ Sidebar';
        }
    });

    // Zoom functionality
    function updateZoomDisplay() {
        document.getElementById('zoom-display').textContent = formatZoomDisplay(zoomLevel);
    }

    // Add zoom button listeners (using event delegation)
    zoomControls.addEventListener('click', function(e) {
        if (e.target.id === 'zoom-increase') {
            zoomLevel = Math.min(zoomLevel + 0.01, 2.0); // Max 200%, increment by 1%
            applyZoom(zoomLevel);
            updateZoomDisplay();
        } else if (e.target.id === 'zoom-decrease') {
            zoomLevel = Math.max(zoomLevel - 0.01, 0.5); // Min 50%, decrement by 1%
            applyZoom(zoomLevel);
            updateZoomDisplay();
        }
    });

    // Add control panel to page when DOM is ready
    function addControls() {
        if (!document.getElementById('reddit-controls')) {
            document.body.appendChild(controlPanel);
            applyZoom(zoomLevel); // Apply saved zoom level
        }
    }

    // Wait for page to load
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addControls);
    } else {
        addControls();
    }

    // Re-add controls after dynamic content loads (for SPA navigation)
    const observer = new MutationObserver(addControls);
    observer.observe(document.body, { childList: true, subtree: true });
})();