Toggle dark mode with Ctrl+Shift+D

Toggles dark mode with Ctrl+Shift+D.

As of 2025-04-17. See the latest version.

// ==UserScript==
// @name         Toggle dark mode with Ctrl+Shift+D
// @description  Toggles dark mode with Ctrl+Shift+D.
// @version      1.0
// @namespace	 https://github.com/yookibooki
// @author       yookibooki
// @license      MIT
// @homepage     https://github.com/yookibooki/userscripts/tree/main/google-search-site-switch
// @supportURL   https://github.com/yookibooki/userscripts/issues
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
    'use strict';

    // Configuration
    const STORAGE_KEY = 'universal-dark-mode-enabled';
    const CSS_CLASS = 'universal-dark-mode-active';

    // Add persistent styles
    GM_addStyle(`
        /* Smooth transition for dark mode toggle */
        html {
            transition: filter 0.3s ease !important;
            min-height: 100vh !important;
        }

        /* Restore media elements to original colors */
        .${CSS_CLASS} img,
        .${CSS_CLASS} video,
        .${CSS_CLASS} iframe,
        .${CSS_CLASS} canvas {
            filter: invert(1) hue-rotate(180deg) !important;
        }

        /* Fix text selection colors */
        .${CSS_CLASS}::selection {
            background: #fff !important;
            color: #000 !important;
        }
    `);

    // Toggle functionality
    function toggleDarkMode() {
        const html = document.documentElement;
        const isActive = html.classList.toggle(CSS_CLASS);

        // Save state
        GM_setValue(STORAGE_KEY, isActive);
    }

    // Keyboard shortcut handler
    function handleShortcut(e) {
        if (e.ctrlKey && e.shiftKey && e.keyCode === 68) { // Ctrl+Shift+D
            toggleDarkMode();
            e.preventDefault();
            e.stopPropagation();
        }
    }

    // Initialize state
    if (GM_getValue(STORAGE_KEY, false)) {
        document.documentElement.classList.add(CSS_CLASS);
    }

    // Event listeners
    document.addEventListener('keydown', handleShortcut, true);

    // Apply inversion filter dynamically to handle CSP issues
    const style = document.createElement('style');
    style.textContent = `
        .${CSS_CLASS} {
            filter: invert(1) hue-rotate(180deg) !important;
            background: #fff !important; /* Create inversion base */
        }
    `;
    document.head.appendChild(style);
})();