Top/Bottom Navigation Buttons

Adds sleek top and bottom navigation buttons with hover scrolling functionality for all websites

  1. // ==UserScript==
  2. // @name Top/Bottom Navigation Buttons
  3. // @namespace https://openuserjs.org/
  4. // @version 1.0.0
  5. // @description Adds sleek top and bottom navigation buttons with hover scrolling functionality for all websites
  6. // @author r3dhack3r
  7. // @license MIT
  8. // @match *://*/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Create CSS styles
  16. const style = document.createElement('style');
  17. style.textContent = `
  18. .nav-button {
  19. position: fixed;
  20. right: 20px;
  21. top: 50%;
  22. width: 36px;
  23. height: 36px;
  24. background: rgba(255, 255, 255, 0.95);
  25. border: 1px solid rgba(0, 0, 0, 0.1);
  26. border-radius: 6px;
  27. cursor: pointer;
  28. z-index: 10000;
  29. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
  30. transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  31. display: flex;
  32. align-items: center;
  33. justify-content: center;
  34. backdrop-filter: blur(8px);
  35. }
  36. .nav-button:hover {
  37. background: rgba(255, 255, 255, 1);
  38. border-color: rgba(0, 0, 0, 0.15);
  39. box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  40. transform: scale(1.05);
  41. }
  42. .nav-button:active {
  43. transform: scale(0.95);
  44. transition: all 0.1s ease;
  45. }
  46. .nav-button svg {
  47. width: 16px;
  48. height: 16px;
  49. fill: #374151;
  50. transition: all 0.25s ease;
  51. }
  52. .nav-button:hover svg {
  53. fill: #1f2937;
  54. }
  55. .nav-button.top {
  56. transform: translateY(-24px);
  57. opacity: 0;
  58. visibility: hidden;
  59. }
  60. .nav-button.bottom {
  61. transform: translateY(24px);
  62. opacity: 0;
  63. visibility: hidden;
  64. }
  65. .nav-button.visible {
  66. opacity: 1;
  67. visibility: visible;
  68. }
  69. .nav-button.scrolling {
  70. background: rgba(249, 250, 251, 1);
  71. border-color: rgba(0, 0, 0, 0.2);
  72. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
  73. }
  74. `;
  75. document.head.appendChild(style);
  76.  
  77. // Create top button
  78. const topButton = document.createElement('button');
  79. topButton.className = 'nav-button top';
  80. topButton.innerHTML = `
  81. <svg viewBox="0 0 24 24">
  82. <path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"/>
  83. </svg>
  84. `;
  85.  
  86. // Create bottom button
  87. const bottomButton = document.createElement('button');
  88. bottomButton.className = 'nav-button bottom';
  89. bottomButton.innerHTML = `
  90. <svg viewBox="0 0 24 24">
  91. <path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/>
  92. </svg>
  93. `;
  94.  
  95. // Add buttons to page
  96. document.body.appendChild(topButton);
  97. document.body.appendChild(bottomButton);
  98.  
  99. // Scroll variables
  100. let scrollInterval;
  101. let isScrolling = false;
  102.  
  103. // Smooth scroll function
  104. function smoothScroll(targetY, duration = 800) {
  105. const startY = window.pageYOffset;
  106. const distance = targetY - startY;
  107. const startTime = performance.now();
  108. function easeInOutCubic(t) {
  109. return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
  110. }
  111. function step(currentTime) {
  112. const elapsed = currentTime - startTime;
  113. const progress = Math.min(elapsed / duration, 1);
  114. const easedProgress = easeInOutCubic(progress);
  115. window.scrollTo(0, startY + distance * easedProgress);
  116. if (progress < 1) {
  117. requestAnimationFrame(step);
  118. }
  119. }
  120. requestAnimationFrame(step);
  121. }
  122.  
  123. // Continuous scroll function
  124. function startContinuousScroll(direction) {
  125. if (isScrolling) return;
  126. isScrolling = true;
  127. const button = direction === 'up' ? topButton : bottomButton;
  128. button.classList.add('scrolling');
  129. scrollInterval = setInterval(() => {
  130. const scrollAmount = direction === 'up' ? -15 : 15;
  131. window.scrollBy(0, scrollAmount);
  132. // Stop if reached limits
  133. if (direction === 'up' && window.pageYOffset <= 0) {
  134. stopContinuousScroll();
  135. } else if (direction === 'down') {
  136. const documentHeight = Math.max(
  137. document.body.scrollHeight,
  138. document.body.offsetHeight,
  139. document.documentElement.clientHeight,
  140. document.documentElement.scrollHeight,
  141. document.documentElement.offsetHeight
  142. );
  143. if ((window.innerHeight + window.pageYOffset) >= documentHeight - 10) {
  144. stopContinuousScroll();
  145. }
  146. }
  147. }, 20);
  148. }
  149.  
  150. function stopContinuousScroll() {
  151. if (scrollInterval) {
  152. clearInterval(scrollInterval);
  153. scrollInterval = null;
  154. }
  155. isScrolling = false;
  156. topButton.classList.remove('scrolling');
  157. bottomButton.classList.remove('scrolling');
  158. }
  159.  
  160. // Button event listeners
  161. topButton.addEventListener('click', (e) => {
  162. e.preventDefault();
  163. smoothScroll(0);
  164. });
  165.  
  166. bottomButton.addEventListener('click', (e) => {
  167. e.preventDefault();
  168. const documentHeight = Math.max(
  169. document.body.scrollHeight,
  170. document.body.offsetHeight,
  171. document.documentElement.clientHeight,
  172. document.documentElement.scrollHeight,
  173. document.documentElement.offsetHeight
  174. );
  175. smoothScroll(documentHeight - window.innerHeight);
  176. });
  177.  
  178. // Hover events for continuous scrolling
  179. topButton.addEventListener('mouseenter', () => {
  180. setTimeout(() => {
  181. if (topButton.matches(':hover')) {
  182. startContinuousScroll('up');
  183. }
  184. }, 500); // Delay before starting continuous scroll
  185. });
  186.  
  187. topButton.addEventListener('mouseleave', stopContinuousScroll);
  188.  
  189. bottomButton.addEventListener('mouseenter', () => {
  190. setTimeout(() => {
  191. if (bottomButton.matches(':hover')) {
  192. startContinuousScroll('down');
  193. }
  194. }, 500); // Delay before starting continuous scroll
  195. });
  196.  
  197. bottomButton.addEventListener('mouseleave', stopContinuousScroll);
  198.  
  199. // Show/hide buttons based on scroll position
  200. function updateButtonVisibility() {
  201. const scrollTop = window.pageYOffset;
  202. const documentHeight = Math.max(
  203. document.body.scrollHeight,
  204. document.body.offsetHeight,
  205. document.documentElement.clientHeight,
  206. document.documentElement.scrollHeight,
  207. document.documentElement.offsetHeight
  208. );
  209. const windowHeight = window.innerHeight;
  210. // Show top button if scrolled down
  211. if (scrollTop > 200) {
  212. topButton.classList.add('visible');
  213. } else {
  214. topButton.classList.remove('visible');
  215. }
  216. // Show bottom button if not at bottom
  217. if (scrollTop + windowHeight + 100 < documentHeight) {
  218. bottomButton.classList.add('visible');
  219. } else {
  220. bottomButton.classList.remove('visible');
  221. }
  222. }
  223.  
  224. // Throttled scroll listener
  225. let scrollTimeout;
  226. window.addEventListener('scroll', () => {
  227. if (scrollTimeout) {
  228. clearTimeout(scrollTimeout);
  229. }
  230. scrollTimeout = setTimeout(updateButtonVisibility, 10);
  231. });
  232.  
  233. // Initial visibility check
  234. setTimeout(updateButtonVisibility, 100);
  235.  
  236. // Keyboard shortcuts (optional)
  237. document.addEventListener('keydown', (e) => {
  238. if (e.ctrlKey || e.metaKey) {
  239. if (e.key === 'Home') {
  240. e.preventDefault();
  241. smoothScroll(0);
  242. } else if (e.key === 'End') {
  243. e.preventDefault();
  244. smoothScroll(document.body.scrollHeight - window.innerHeight);
  245. }
  246. }
  247. });
  248.  
  249. })();