Youtube Shorts Text Removal

Toggles text visible that is overlaying the Youtube Short(e.g captions, channel name)

  1. // ==UserScript==
  2. // @name Youtube Shorts Text Removal
  3. // @namespace Violentmonkey Scripts
  4. // @match *://www.youtube.com/*
  5. // @grant none
  6. // @version 1.0
  7. // @description Toggles text visible that is overlaying the Youtube Short(e.g captions, channel name)
  8. // @license MIT
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. let isTextHidden = false; // Default: text is visible
  13. let defaultHidden = false; // Default setting for new reels
  14. let buttonsContainer = null; // Holds the buttons
  15. let observer = null;
  16.  
  17. function addButtons() {
  18. if (buttonsContainer) return; // Prevent duplicate buttons
  19.  
  20. buttonsContainer = document.createElement('div');
  21. buttonsContainer.style.cssText = `
  22. position: fixed;
  23. bottom: 20px;
  24. right: 20px;
  25. z-index: 9999;
  26. display: flex;
  27. flex-direction: column;
  28. gap: 5px;
  29. opacity: 0.2;
  30. transition: opacity 0.3s ease;
  31. `;
  32.  
  33. // Add hover effect to container
  34. buttonsContainer.addEventListener('mouseenter', () => {
  35. buttonsContainer.style.opacity = '0.9';
  36. });
  37.  
  38. buttonsContainer.addEventListener('mouseleave', () => {
  39. buttonsContainer.style.opacity = '0.2';
  40. });
  41.  
  42. // Toggle text button
  43. const toggleButton = document.createElement('button');
  44. toggleButton.textContent = 'Toggle Text';
  45. toggleButton.style.cssText = `
  46. padding: 8px 16px;
  47. background: rgba(0, 0, 0, 0.7);
  48. color: white;
  49. border: none;
  50. border-radius: 4px;
  51. cursor: pointer;
  52. transition: background 0.3s ease;
  53. `;
  54. toggleButton.addEventListener('click', () => toggleTextVisibility());
  55.  
  56. // Add hover effect to button
  57. toggleButton.addEventListener('mouseenter', () => {
  58. toggleButton.style.background = 'rgba(0, 0, 0, 0.9)';
  59. });
  60.  
  61. toggleButton.addEventListener('mouseleave', () => {
  62. toggleButton.style.background = 'rgba(0, 0, 0, 0.7)';
  63. });
  64.  
  65. // Default mode button
  66. const modeButton = document.createElement('button');
  67. modeButton.textContent = 'Default: Visible';
  68. modeButton.style.cssText = `
  69. padding: 8px 16px;
  70. background: rgba(0, 0, 0, 0.7);
  71. color: white;
  72. border: none;
  73. border-radius: 4px;
  74. cursor: pointer;
  75. transition: background 0.3s ease;
  76. `;
  77. modeButton.addEventListener('click', () => {
  78. defaultHidden = !defaultHidden;
  79. modeButton.textContent = defaultHidden ? 'Default: Hidden' : 'Default: Visible';
  80. });
  81.  
  82. // Add hover effect to button
  83. modeButton.addEventListener('mouseenter', () => {
  84. modeButton.style.background = 'rgba(0, 0, 0, 0.9)';
  85. });
  86.  
  87. modeButton.addEventListener('mouseleave', () => {
  88. modeButton.style.background = 'rgba(0, 0, 0, 0.7)';
  89. });
  90.  
  91. buttonsContainer.appendChild(toggleButton);
  92. buttonsContainer.appendChild(modeButton);
  93. document.body.appendChild(buttonsContainer);
  94. }
  95.  
  96. function removeButtons() {
  97. if (buttonsContainer) {
  98. buttonsContainer.remove();
  99. buttonsContainer = null;
  100. }
  101. }
  102.  
  103. function toggleTextVisibility(forceState = null) {
  104. const textElements = document.querySelectorAll('.ytShortsTitleText, .metadata-container');
  105. const hideText = forceState !== null ? forceState : !isTextHidden;
  106.  
  107. textElements.forEach(element => {
  108. element.style.display = hideText ? 'none' : '';
  109. });
  110.  
  111. isTextHidden = hideText;
  112. }
  113.  
  114. function applyDefaultTextVisibility() {
  115. setTimeout(() => {
  116. toggleTextVisibility(defaultHidden);
  117. }, 100);
  118. }
  119.  
  120. function fixButtonPositions() {
  121. const actionContainers = document.querySelectorAll('.action-container.style-scope.ytd-reel-player-overlay-renderer');
  122. actionContainers.forEach(actionContainer => {
  123. if (actionContainer) {
  124. actionContainer.style.cssText = `
  125. margin-right: 0 !important;
  126. display: flex !important;
  127. flex-direction: column !important;
  128. gap: 8px !important;
  129. position: absolute !important;
  130. right: 12px !important;
  131. top: 50% !important;
  132. transform: translateY(-50%) !important;
  133. z-index: 2000 !important;
  134. `;
  135. }
  136. });
  137.  
  138. const buttons = document.querySelectorAll('.button-container');
  139. buttons.forEach(button => {
  140. button.style.display = 'flex';
  141. button.style.visibility = 'visible';
  142. button.style.opacity = '1';
  143. });
  144. }
  145.  
  146. function setupObserver() {
  147. if (observer) observer.disconnect(); // Clear old observer
  148.  
  149. observer = new MutationObserver(() => {
  150. fixButtonPositions();
  151. applyDefaultTextVisibility();
  152. });
  153.  
  154. observer.observe(document.body, {
  155. childList: true,
  156. subtree: true
  157. });
  158. }
  159.  
  160. function checkPage() {
  161. if (location.pathname.startsWith("/shorts/")) {
  162. addButtons();
  163. fixButtonPositions();
  164. applyDefaultTextVisibility();
  165. setupObserver();
  166. } else {
  167. removeButtons(); // Remove buttons when leaving Shorts
  168. }
  169. }
  170.  
  171. // Detect SPA (YouTube false navigation)
  172. const ytNavigationObserver = new MutationObserver(() => {
  173. checkPage();
  174. });
  175.  
  176. ytNavigationObserver.observe(document.body, {
  177. childList: true,
  178. subtree: true
  179. });
  180.  
  181. checkPage(); // Initial check on load
  182. })();