Created
December 7, 2025 06:11
-
-
Save Ppang0405/f6e13bacf69e98092f2a12976277b55d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Grayscale All Images (Auto-Enable) | |
| // @namespace http://tampermonkey.net/ | |
| // @version 1.1.0 | |
| // @description Automatically grays out all images on page load - toggle with Ctrl+Shift+G or floating button | |
| // @author You | |
| // @match *://*/* | |
| // @grant GM_addStyle | |
| // @grant GM_getValue | |
| // @grant GM_setValue | |
| // @run-at document-end | |
| // ==/UserScript== | |
| (function() { | |
| 'use strict'; | |
| // Configuration | |
| const STORAGE_KEY = 'grayscale_enabled'; | |
| const KEYBOARD_SHORTCUT = 'G'; // Ctrl+Shift+G (or Cmd+Shift+G on Mac) | |
| const AUTO_ENABLE = true; // Set to false to start disabled | |
| // State - defaults to TRUE (auto-enable on every page) | |
| let isGrayscaleEnabled = GM_getValue(STORAGE_KEY, AUTO_ENABLE); | |
| /** | |
| * Inject CSS styles for grayscale effect and toggle button | |
| */ | |
| GM_addStyle(` | |
| /* Grayscale styles */ | |
| body.grayscale-mode img, | |
| body.grayscale-mode picture img, | |
| body.grayscale-mode video, | |
| body.grayscale-mode canvas, | |
| body.grayscale-mode svg image { | |
| filter: grayscale(100%) !important; | |
| -webkit-filter: grayscale(100%) !important; | |
| } | |
| /* Floating toggle button */ | |
| #grayscale-toggle-btn { | |
| position: fixed; | |
| bottom: 20px; | |
| right: 20px; | |
| z-index: 2147483647; | |
| width: 56px; | |
| height: 56px; | |
| border-radius: 50%; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| border: 3px solid white; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.3s ease; | |
| font-size: 28px; | |
| color: white; | |
| user-select: none; | |
| opacity: 0.9; | |
| } | |
| #grayscale-toggle-btn:hover { | |
| opacity: 1; | |
| transform: scale(1.15); | |
| box-shadow: 0 6px 25px rgba(0, 0, 0, 0.5); | |
| } | |
| #grayscale-toggle-btn.active { | |
| background: linear-gradient(135deg, #4a5568 0%, #2d3748 100%); | |
| } | |
| #grayscale-toggle-btn::after { | |
| content: 'π¨'; | |
| } | |
| #grayscale-toggle-btn.active::after { | |
| content: 'β«'; | |
| } | |
| /* Tooltip */ | |
| #grayscale-toggle-btn:hover::before { | |
| content: attr(data-tooltip); | |
| position: absolute; | |
| bottom: 65px; | |
| right: 0; | |
| background: rgba(0, 0, 0, 0.95); | |
| color: white; | |
| padding: 10px 14px; | |
| border-radius: 8px; | |
| font-size: 13px; | |
| white-space: nowrap; | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
| pointer-events: none; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); | |
| } | |
| `); | |
| /** | |
| * Apply grayscale to all images including background images | |
| */ | |
| function applyGrayscale() { | |
| document.body.classList.add('grayscale-mode'); | |
| applyGrayscaleToBackgrounds(); | |
| isGrayscaleEnabled = true; | |
| GM_setValue(STORAGE_KEY, true); | |
| updateToggleButton(); | |
| console.log('β Grayscale mode ENABLED'); | |
| } | |
| /** | |
| * Remove grayscale filter from all images | |
| */ | |
| function removeGrayscale() { | |
| document.body.classList.remove('grayscale-mode'); | |
| removeGrayscaleFromBackgrounds(); | |
| isGrayscaleEnabled = false; | |
| GM_setValue(STORAGE_KEY, false); | |
| updateToggleButton(); | |
| console.log('β Grayscale mode DISABLED'); | |
| } | |
| /** | |
| * Toggle grayscale on/off | |
| */ | |
| function toggleGrayscale() { | |
| if (isGrayscaleEnabled) { | |
| removeGrayscale(); | |
| } else { | |
| applyGrayscale(); | |
| } | |
| } | |
| /** | |
| * Apply grayscale to elements with background images | |
| */ | |
| function applyGrayscaleToBackgrounds() { | |
| const elements = document.querySelectorAll('*'); | |
| elements.forEach(element => { | |
| // Skip the toggle button itself | |
| if (element.id === 'grayscale-toggle-btn') return; | |
| const computedStyle = window.getComputedStyle(element); | |
| const bgImage = computedStyle.backgroundImage; | |
| if (bgImage && bgImage !== 'none' && !element.hasAttribute('data-grayscale-bg')) { | |
| element.setAttribute('data-grayscale-bg', 'true'); | |
| const currentFilter = element.style.filter || ''; | |
| element.setAttribute('data-original-filter', currentFilter); | |
| element.style.filter = currentFilter ? `${currentFilter} grayscale(100%)` : 'grayscale(100%)'; | |
| } | |
| }); | |
| } | |
| /** | |
| * Remove grayscale from elements with background images | |
| */ | |
| function removeGrayscaleFromBackgrounds() { | |
| const elements = document.querySelectorAll('[data-grayscale-bg="true"]'); | |
| elements.forEach(element => { | |
| const originalFilter = element.getAttribute('data-original-filter'); | |
| element.style.filter = originalFilter || ''; | |
| element.removeAttribute('data-grayscale-bg'); | |
| element.removeAttribute('data-original-filter'); | |
| }); | |
| } | |
| /** | |
| * Create floating toggle button | |
| */ | |
| function createToggleButton() { | |
| // Remove existing button if any | |
| const existingButton = document.getElementById('grayscale-toggle-btn'); | |
| if (existingButton) { | |
| existingButton.remove(); | |
| } | |
| const button = document.createElement('div'); | |
| button.id = 'grayscale-toggle-btn'; | |
| button.setAttribute('data-tooltip', 'Toggle Grayscale (Ctrl+Shift+G)'); | |
| button.addEventListener('click', toggleGrayscale); | |
| // Add to page | |
| document.body.appendChild(button); | |
| // Update button state | |
| updateToggleButton(); | |
| console.log('π Toggle button created (bottom-right corner)'); | |
| } | |
| /** | |
| * Update toggle button appearance based on state | |
| */ | |
| function updateToggleButton() { | |
| const button = document.getElementById('grayscale-toggle-btn'); | |
| if (button) { | |
| if (isGrayscaleEnabled) { | |
| button.classList.add('active'); | |
| button.setAttribute('data-tooltip', 'Disable Grayscale (Ctrl+Shift+G)'); | |
| } else { | |
| button.classList.remove('active'); | |
| button.setAttribute('data-tooltip', 'Enable Grayscale (Ctrl+Shift+G)'); | |
| } | |
| } | |
| } | |
| /** | |
| * Check if element has background image and apply grayscale if needed | |
| */ | |
| function checkAndApplyToElement(element) { | |
| if (!isGrayscaleEnabled || !element || element.nodeType !== Node.ELEMENT_NODE) { | |
| return; | |
| } | |
| // Skip the toggle button | |
| if (element.id === 'grayscale-toggle-btn') return; | |
| const computedStyle = window.getComputedStyle(element); | |
| const bgImage = computedStyle.backgroundImage; | |
| if (bgImage && bgImage !== 'none' && !element.hasAttribute('data-grayscale-bg')) { | |
| element.setAttribute('data-grayscale-bg', 'true'); | |
| const currentFilter = element.style.filter || ''; | |
| element.setAttribute('data-original-filter', currentFilter); | |
| element.style.filter = currentFilter ? `${currentFilter} grayscale(100%)` : 'grayscale(100%)'; | |
| } | |
| } | |
| /** | |
| * Observe DOM changes for dynamically loaded images | |
| */ | |
| function initObserver() { | |
| const observer = new MutationObserver((mutations) => { | |
| if (!isGrayscaleEnabled) return; | |
| mutations.forEach((mutation) => { | |
| mutation.addedNodes.forEach((node) => { | |
| if (node.nodeType === Node.ELEMENT_NODE) { | |
| checkAndApplyToElement(node); | |
| if (node.querySelectorAll) { | |
| node.querySelectorAll('*').forEach(checkAndApplyToElement); | |
| } | |
| } | |
| }); | |
| }); | |
| }); | |
| observer.observe(document.body, { | |
| childList: true, | |
| subtree: true | |
| }); | |
| } | |
| /** | |
| * Setup keyboard shortcut (Ctrl+Shift+G or Cmd+Shift+G) | |
| */ | |
| function setupKeyboardShortcut() { | |
| document.addEventListener('keydown', (event) => { | |
| // Check for Ctrl+Shift+G (Windows/Linux) or Cmd+Shift+G (Mac) | |
| if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key.toUpperCase() === KEYBOARD_SHORTCUT) { | |
| event.preventDefault(); | |
| toggleGrayscale(); | |
| } | |
| }); | |
| } | |
| /** | |
| * Initialize the userscript | |
| */ | |
| function init() { | |
| console.log('π¨ Grayscale userscript loaded (AUTO-ENABLE version)'); | |
| // Create toggle button | |
| createToggleButton(); | |
| // Setup keyboard shortcut | |
| setupKeyboardShortcut(); | |
| // Apply grayscale automatically if enabled | |
| if (isGrayscaleEnabled) { | |
| console.log('β‘ Auto-applying grayscale...'); | |
| applyGrayscale(); | |
| } | |
| // Observe DOM changes for dynamic content | |
| initObserver(); | |
| // Show notification on first run | |
| if (GM_getValue('first_run', true)) { | |
| console.log('π‘ TIP: This script auto-enables grayscale on all pages!'); | |
| console.log('π‘ Press Ctrl+Shift+G (or Cmd+Shift+G on Mac) to toggle, or use the floating button!'); | |
| console.log('π‘ Look for the button in the bottom-right corner: π¨ or β«'); | |
| GM_setValue('first_run', false); | |
| } | |
| } | |
| // Wait for DOM to be ready | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', init); | |
| } else { | |
| init(); | |
| } | |
| })(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment