Removes YouTube's 2025 saturated hover effects.
< 脚本 YouTube No Saturated Hover 的反馈
Hmmm… very interesting! I wasn’t able to recreate the bug, but I slapped it through GPT-5 mini and I’ll post what it gave me 😅. Let me know if this fixes it and if it does, I’ll update it. If not, if you could share the HTML of the bugged link that would be very helpful. Thanks!
// ==UserScript==
// @name YouTube No Saturated Hover
// @namespace https://greasyfork.org/users/1476331-jon78
// @version 1.2.1
// @description Removes YouTube's 2025 saturated hover effects.
// @author jon78
// @license CC0
// @match *://*.youtube.com/*
// @icon https://www.youtube.com/favicon.ico
// @run-at document-idle
// @grant none
// ==/UserScript==
(() => {
"use strict";
const ID = "no-saturated-hover";
let styleEl = null;
let dark = undefined;
/* --------------------------
Detect YouTube Dark/Light mode
-------------------------- */
const detectDark = () => {
const html = document.documentElement;
if (html.hasAttribute("dark") || html.classList.contains("dark-theme")) return true;
if (html.hasAttribute("light") || html.classList.contains("light-theme")) return false;
try {
const cs = getComputedStyle(html);
const bg = (cs && cs.getPropertyValue("--yt-spec-base-background") || "").trim();
if (bg.startsWith("rgb(") || bg.startsWith("rgba(")) {
const nums = bg.match(/\d+/g);
if (nums && nums.length >= 3) {
const r = Number(nums[0]), g = Number(nums[1]), b = Number(nums[2]);
return ((r + g + b) / 3) < 60;
}
}
} catch (e) {}
return false;
};
/* --------------------------
Build CSS based on theme
-------------------------- */
const buildCss = d => {
return (`
html {
--ytc-base-background:${d ? "#0f0f0f" : "#fff"};
--ytc-additive-background:${d ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.05)"};
--ytc-text-primary:${d ? "#f1f1f1" : "#0f0f0f"};
--ytc-text-secondary:${d ? "#aaa" : "#606060"};
--yt-spec-base-background:var(--yt-spec-base-background,var(--ytc-base-background));
--yt-spec-additive-background:var(--yt-spec-additive-background,var(--ytc-additive-background));
--yt-spec-text-primary:var(--yt-spec-text-primary,var(--ytc-text-primary));
--yt-spec-text-secondary:var(--yt-spec-text-secondary,var(--ytc-text-secondary));
--yt-active-playlist-panel-background-color: var(--yt-spec-additive-background);
--yt-lightsource-primary-title-color: var(--ytc-text-primary);
--yt-lightsource-secondary-title-color: var(--ytc-text-secondary);
--iron-icon-fill-color: var(--yt-lightsource-primary-title-color);
}
/* Disable saturated hover feedback UI */
.yt-spec-touch-feedback-shape__hover-effect,
.yt-spec-touch-feedback-shape__stroke,
.yt-spec-touch-feedback-shape__fill {
display: none !important;
opacity: 0 !important;
pointer-events: none !important;
}
/* Remove highlight from promoted videos */
ytd-rich-item-renderer.ytd-rich-item-renderer-highlight {
background: transparent !important;
box-shadow: none !important;
--yt-spec-outline: transparent !important;
}
/* Primary title colors */
ytd-rich-grid-renderer #video-title,
.yt-lockup-metadata-view-model__title,
.yt-lockup-metadata-view-model__title a {
color: var(--yt-spec-text-primary, var(--ytc-text-primary)) !important;
}
/* Metadata / secondary text colors */
.yt-lockup-metadata-view-model__metadata,
.yt-lockup-metadata-view-model__metadata span,
#metadata-line span {
color: var(--yt-spec-text-secondary, var(--ytc-text-secondary)) !important;
}
/* Collapsed description */
ytd-watch-metadata #description,
ytd-video-secondary-info-renderer #description,
ytd-watch-info-text,
#metadata.ytd-watch-info-text,
#metadata-line.ytd-video-primary-info-renderer span,
#snippet-text,
#snippet-text *,
#attributed-snippet-text,
#attributed-snippet-text * {
color: var(--yt-spec-text-primary, var(--ytc-text-primary)) !important;
}
#snippet-text:hover,
#snippet-text *:hover,
#attributed-snippet-text:hover,
#attributed-snippet-text *:hover,
ytd-watch-info-text *:hover {
color: var(--yt-spec-text-primary, var(--ytc-text-primary)) !important;
filter: none !important;
opacity: 1 !important;
}
/* Highlighted links */
.yt-core-attributed-string--highlight-text-decorator > a.yt-core-attributed-string__link--call-to-action-color,
.yt-core-attributed-string--link-inherit-color .yt-core-attributed-string--highlight-text-decorator > a.yt-core-attributed-string__link--call-to-action-color {
color: var(--yt-spec-text-primary, var(--ytc-text-primary)) !important;
}
/* CTA links (hashtags, blue links) */
ytd-watch-metadata :not(.yt-core-attributed-string--highlight-text-decorator) > .yt-core-attributed-string__link--call-to-action-color,
#snippet-text :not(.yt-core-attributed-string--highlight-text-decorator) > .yt-core-attributed-string__link--call-to-action-color,
#attributed-snippet-text :not(.yt-core-attributed-string--highlight-text-decorator) > .yt-core-attributed-string__link--call-to-action-color {
color: var(--yt-spec-call-to-action, #3ea6ff) !important;
}
/* Reset saturation variables on watch page */
ytd-watch-metadata, .ytd-watch-metadata {
--yt-saturated-base-background: var(--ytc-base-background);
--yt-saturated-raised-background: var(--yt-spec-additive-background,var(--ytc-additive-background));
--yt-saturated-additive-background: var(--yt-spec-additive-background,var(--ytc-additive-background));
--yt-saturated-text-primary: var(--yt-spec-text-primary,var(--ytc-text-primary));
--yt-saturated-text-secondary: var(--yt-spec-text-secondary,var(--ytc-text-secondary));
--yt-saturated-overlay-background: var(--yt-spec-additive-background,var(--ytc-additive-background));
--yt-spec-overlay-background: var(--yt-spec-additive-background,var(--ytc-additive-background));
--yt-spec-static-overlay-background-light: var(--yt-spec-additive-background,var(--ytc-additive-background));
--yt-active-playlist-panel-background-color: var(--yt-spec-additive-background);
--yt-lightsource-primary-title-color: var(--ytc-text-primary);
--yt-lightsource-secondary-title-color: var(--ytc-text-secondary);
--iron-icon-fill-color: var(--yt-lightsource-primary-title-color);
}
/* Highlighted text background cleanup */
.yt-core-attributed-string--highlight-text-decorator {
background-color: var(--yt-spec-static-overlay-background-light, ${d ? "rgba(255,255,255,0.102)" : "rgba(0,0,0,0.051)"}) !important;
border-radius: 8px !important;
padding-bottom: 1px !important;
}
`).trim();
};
const CSS_CACHE = { dark: buildCss(true), light: buildCss(false) };
/* --------------------------
Apply or update CSS
-------------------------- */
const applyStyle = isDark => {
if (!styleEl) {
styleEl = document.getElementById(ID);
if (!styleEl) {
styleEl = document.createElement("style");
styleEl.id = ID;
(document.head || document.documentElement).appendChild(styleEl);
}
}
const newCss = isDark ? CSS_CACHE.dark : CSS_CACHE.light;
if (styleEl.textContent !== newCss) {
styleEl.textContent = newCss;
}
};
/* --------------------------
Playlist panel update
-------------------------- */
const updatePlaylistPanel = () => {
const panels = document.querySelectorAll("ytd-playlist-panel-renderer");
if (panels.length) {
panels.forEach(panel => {
try {
panel.style.setProperty("--yt-active-playlist-panel-background-color", "var(--yt-spec-additive-background)");
panel.style.setProperty("--yt-lightsource-primary-title-color", "var(--ytc-text-primary)");
panel.style.setProperty("--yt-lightsource-secondary-title-color", "var(--ytc-text-secondary)");
panel.style.setProperty("--iron-icon-fill-color", "var(--yt-lightsource-primary-title-color)");
} catch (e) {}
});
} else {
requestAnimationFrame(updatePlaylistPanel);
}
};
const scheduleUpdate = () => requestAnimationFrame(updatePlaylistPanel);
/* --------------------------
Refresh on SPA navigation or theme change
-------------------------- */
const refresh = () => {
const isDark = detectDark();
if (isDark !== dark) {
dark = isDark;
applyStyle(dark);
}
scheduleUpdate();
};
/* --------------------------
Initialization
-------------------------- */
const init = () => {
// Schedule initial CSS + playlist update in the next frame
requestAnimationFrame(() => {
dark = detectDark();
applyStyle(dark);
scheduleUpdate();
});
// SPA navigation / theme events
addEventListener("yt-navigate-finish", refresh, { passive: true });
addEventListener("yt-dark-mode-toggled", refresh, { passive: true });
};
if (document.documentElement && (document.head || document.readyState === "complete")) {
init();
} else {
addEventListener("DOMContentLoaded", init, { once: true });
}
})();
Yep, that seemed to fix it!
Works great, but also changes descriptive links into short urls with gibberish Ex. [YT Logo] [Video Title] becomes youtu.be/dflakdsfjaasdf52a or something like that.