Completely blocks YouTube thumbnail hover previews (animated WebP & video) while preserving progress badges, play buttons, and static images. Works on all pages: homepage, subscriptions, search, channels, etc. No permissions needed. Instant at page load.
当前为
// ==UserScript==
// @name YouTube - Block Autoplay Preview (Keep Badge)
// @name:vi YouTube - Chặn Preview Tự Động Khi Hover (Giữ Badge)
// @namespace https://greasyfork.org/users/979364-miebie-1412
// @version 1.0
// @description Completely blocks YouTube thumbnail hover previews (animated WebP & video) while preserving progress badges, play buttons, and static images. Works on all pages: homepage, subscriptions, search, channels, etc. No permissions needed. Instant at page load.
// @description:vi Chặn hoàn toàn hiệu ứng xem trước video khi di chuột qua thumbnail (WebP động & video), nhưng vẫn giữ nguyên badge tiến độ, nút play và ảnh tĩnh. Hoạt động trên mọi trang YouTube.
// @author miebie.1412
// @match *://*.youtube.com/*
// @match *://youtube.com/*
// @grant none
// @run-at document-start
// @license MIT
// @homepageURL https://greasyfork.org/en/users/979364-miebie-1412
// @supportURL https://greasyfork.org/en/users/979364-miebie-1412
// @icon https://www.youtube.com/favicon.ico
// @compatible chrome
// @compatible firefox
// @compatible edge
// @compatible opera
// @compatible safari
// @compatible brave
// ==/UserScript==
(function () {
'use strict';
// Polyfill for MutationObserver (enhanced for Safari/WebKit)
if (typeof MutationObserver === 'undefined') {
window.MutationObserver = window.WebKitMutationObserver || function(callback) {
return { observe: function() {}, disconnect: function() {} };
};
}
// Create and append CSS style safely
const style = document.createElement('style');
style.textContent = `
ytd-moving-thumbnail-renderer,
.ytd-moving-thumbnail-renderer,
ytd-thumbnail-overlay-resume-playback-renderer,
.ytd-thumbnail-overlay-resume-playback-renderer,
.ytp-cued-thumbnail-overlay,
.ytp-cued-thumbnail-overlay-image,
ytd-thumbnail-overlay-loading-preview-renderer,
.ytd-thumbnail-overlay-loading-preview-renderer,
ytd-video-preview,
.ytd-video-preview,
#thumbnail-overlay-play,
.thumbnail-overlay-play,
#video-preview-container,
.video-preview-container {
display: none !important;
visibility: hidden !important;
}
ytd-thumbnail img,
.ytd-thumbnail img {
transition: none !important;
opacity: 1 !important;
}
#overlays,
.ytd-rich-item-renderer #overlays,
ytd-thumbnail[has-inline-playback-button] #overlays,
ytd-thumbnail-overlay-toggle-pause-renderer,
.ytd-thumbnail-overlay-pause-renderer {
all: unset !important;
display: block !important;
}
`;
const appendStyle = () => {
const target = document.head || document.documentElement;
if (target && !target.querySelector('style[data-yt-block-preview]')) {
style.setAttribute('data-yt-block-preview', 'true');
target.appendChild(style);
}
};
// Block preview elements with debounce to prevent performance issues
let timeout;
const blockPreview = () => {
if (timeout) return;
timeout = setTimeout(() => {
document.querySelectorAll('img[src*="an_webp"], video[src*="an_webp"], img[src*="video-preview"], video[src*="video-preview"]').forEach(el => {
if (el.tagName === 'IMG') {
el.src = el.src.replace(/an_webp\/[^&]*&/g, '').replace(/video-preview\/[^&]*&/g, '');
el.srcset = '';
} else if (el.tagName === 'VIDEO') {
el.src = el.src.replace(/an_webp\/[^&]*&/g, '').replace(/video-preview\/[^&]*&/g, '');
if (el.pause) el.pause();
if (el.currentTime !== undefined) el.currentTime = 0;
el.removeAttribute('autoplay');
}
});
timeout = null;
}, 50);
};
// Setup MutationObserver with fallback
const observer = new MutationObserver(blockPreview);
const observe = () => {
if (document.documentElement) {
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['src', 'srcset']
});
}
};
// Run on page load or when ready (Safari-safe)
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
appendStyle();
observe();
blockPreview();
});
} else {
appendStyle();
observe();
blockPreview();
}
// Periodic check every 500ms (lightweight)
setInterval(blockPreview, 500);
})();