Skip to content

Instantly share code, notes, and snippets.

@braebo
Created October 23, 2025 05:56
Show Gist options
  • Select an option

  • Save braebo/660ff6d8d3a2d3a464f033222f09c3b7 to your computer and use it in GitHub Desktop.

Select an option

Save braebo/660ff6d8d3a2d3a464f033222f09c3b7 to your computer and use it in GitHub Desktop.
Forces vertical arrow keys to always control volume instead of scrolling.
// ==UserScript==
// @name Youtube Arrow Key Fix
// @namespace Violentmonkey Scripts
// @match https://www.youtube.com/watch?v=*
// @grant none
// @version 1.0
// @author braebo
// @description Forces vertical arrow keys to always control volume instead of scrolling.
// @note Hold alt for 1% or shift for 10% volume changes.
// ==/UserScript==
document.addEventListener('keydown', fixArrowKeys, { capture: true, passive: false })
function fixArrowKeys(event) {
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
if (
document.activeElement?.tagName === 'INPUT' ||
document.activeElement?.isContentEditable // comment box
) {
return
}
const player = document.getElementById('movie_player')
// Relinquish control when the player is focused unless modifiers are pressed.
if (player === document.activeElement && !event.altKey && !event.shiftKey) {
return
}
event.preventDefault()
event.stopPropagation()
let step = event.altKey ? 1 : event.shiftKey ? 10 : 5
if (event.key === 'ArrowDown') step = -step
const current = player?.getVolume?.()
if (!isNaN(current)) {
player.setVolume(Math.round(current + step))
}
showVolumePopup(player)
}
}
let popup = null
let fade_timer = null
let fade_animation = null
function showVolumePopup(player) {
clearTimeout(fade_timer)
if (!popup) {
popup = document.createElement('div')
popup.id = 'volume-popup'
popup.style.cssText = /* s */ `
display: inline-block;
position: absolute;
top: 10%;
left: 0;
right: 0;
width: fit-content;
margin: 0 auto;
padding: 10px 20px;
color: #eee;
background: rgba(0, 0, 0, .5);
pointer-events: none;
border-radius: 3px;
font-family: "YouTube Noto", Roboto, Arial, Helvetica, sans-serif;
font-size: 175%;
line-height: 1.3;
-webkit-font-smoothing: antialiased;
z-index: 1000;
`
player.appendChild(popup)
}
fade_animation?.cancel()
fade_animation = popup.animate(
{ opacity: 1 },
{ duration: 100, easing: 'ease-out', fill: 'forwards' },
)
const current = player.getVolume?.()
if (!isNaN(current)) {
popup.textContent = `${current}%`
}
fade_timer = setTimeout(() => {
fade_animation = popup?.animate({ opacity: 0 }, { duration: 100, easing: 'ease-out' })
fade_animation?.finished.then(() => {
popup?.remove()
popup = fade_animation = null
})
}, 500)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment