Skip to content

Instantly share code, notes, and snippets.

@ericboehs
Last active April 2, 2025 13:06
Show Gist options
  • Save ericboehs/0bc11695a1cdb31a3adc405b5f672635 to your computer and use it in GitHub Desktop.
Save ericboehs/0bc11695a1cdb31a3adc405b5f672635 to your computer and use it in GitHub Desktop.
YouTube Vim-style Keyboard Navigation UserScript
// ==UserScript==
// @name YouTube Keyboard Navigation
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Navigate YouTube videos with Vim-style keys and open with Enter or Cmd+Enter
// @match https://www.youtube.com/*
// @match https://www.youtube.com/feed/*
// @grant none
// ==/UserScript==
/**
* YouTube Keyboard Navigation
*
* Navigate YouTube like a pro using Vim-style keys:
*
* - Ctrl-H / Ctrl-L → Move left/right
* - Ctrl-J / Ctrl-K → Move down/up a row (no wraparound)
* - Ctrl-A → Jump to the first video
* - Ctrl-E → Jump to the last video
* - Enter → Open selected video
* - Cmd+Enter → Open selected video in a new tab
*
* Tested in Safari with UserScripts. Should also work in Chrome or Firefox.
*/
(function () {
'use strict';
let selectedIndex = 0;
function getVideoItems() {
const isSearchPage = window.location.pathname.startsWith('/results');
const selector = isSearchPage ? 'ytd-video-renderer' : 'ytd-rich-item-renderer';
return Array.from(document.querySelectorAll(selector)).filter(el =>
el.offsetParent !== null
);
}
function getVideosPerRow() {
const items = getVideoItems();
if (items.length < 2) return 1;
const firstTop = items[0].offsetTop;
return items.findIndex(item => item.offsetTop !== firstTop) || items.length;
}
function scrollToAndHighlight(index) {
const items = getVideoItems();
if (!items[index]) return;
items.forEach(item => (item.style.outline = ''));
const target = items[index];
target.scrollIntoView({ behavior: 'smooth', block: 'center' });
target.style.outline = '3px solid #3ea6ff';
}
function selectVideoByOffset(offset, isVertical = false, allowWrap = true) {
const items = getVideoItems();
if (!items.length) return;
const step = isVertical ? getVideosPerRow() : 1;
const newIndex = selectedIndex + offset * step;
if (newIndex < 0 || newIndex >= items.length) {
if (allowWrap) {
selectedIndex = (newIndex + items.length) % items.length;
}
return; // Don't move if disallowed
}
selectedIndex = newIndex;
scrollToAndHighlight(selectedIndex);
}
function jumpToVideo(index) {
const items = getVideoItems();
if (items[index]) {
selectedIndex = index;
scrollToAndHighlight(index);
}
}
function activateSelectedVideo(openInNewTab = false) {
const items = getVideoItems();
const item = items[selectedIndex];
if (!item) return;
const isSearchPage = window.location.pathname.startsWith('/results');
const linkSelector = isSearchPage ? 'a#video-title' : 'a#video-title-link';
const link = item.querySelector(linkSelector);
if (link) {
if (openInNewTab) {
window.open(link.href, '_blank');
} else {
link.click();
}
} else {
item.click(); // Fallback
}
}
document.addEventListener('keydown', (e) => {
const key = e.key.toLowerCase();
if (!e.ctrlKey && !e.metaKey && key !== 'enter') return;
if (e.ctrlKey) {
switch (key) {
case 'h':
e.preventDefault();
return selectVideoByOffset(-1);
case 'l':
e.preventDefault();
return selectVideoByOffset(1);
case 'j':
e.preventDefault();
return selectVideoByOffset(1, true, false); // no wrap
case 'k':
e.preventDefault();
return selectVideoByOffset(-1, true, false); // no wrap
case 'a':
e.preventDefault();
return jumpToVideo(0);
case 'e':
e.preventDefault();
return jumpToVideo(getVideoItems().length - 1);
}
}
if (key === 'enter') {
e.preventDefault();
activateSelectedVideo(e.metaKey);
}
});
// Initial selection
setTimeout(() => scrollToAndHighlight(selectedIndex), 1000);
})();
@ericboehs
Copy link
Author

🎬 YouTube Vim-style Navigation with Tampermonkey

This UserScript lets you browse YouTube using your keyboard, inspired by Vim-style navigation. Perfect for navigating your YouTube experience without touching the mouse.

✨ Features

  • Ctrl-H / Ctrl-L — Move left and right
  • Ctrl-J / Ctrl-K — Move down/up a row (auto-detects number of columns)
  • Ctrl-A / Ctrl-E — Jump to the first/last video on the page
  • Enter — Open selected video
  • Cmd+Enter — Open selected video in a new tab (macOS-friendly)

📍 Supported Pages

  • ✅ YouTube homepage and feed pages
  • Search results
  • Channel pages: Videos, Shorts, and Live tabs (grid-style)
  • ✅ Works with dynamically loaded items (like infinite scroll)

🔧 Notes

  • Avoids targeting dynamic or generated element IDs
  • Adds a blue outline to the currently selected video
  • Tested in Safari + UserScripts
  • Should also work in Chrome and Firefox (via TamperMonkey)

⚠️ Not Supported

  • ❌ Shorts full-screen view
  • ❌ Playlists and Playlist grid pages
  • ❌ Channel Home tab (uses a non-grid, vertical “shelf” layout)
  • ❌ No mouse-free commenting, liking, or subscribing

Enjoy navigating YouTube without leaving the keyboard! 😎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment