Published on

Keyboard Navigation for Google Search with j/k Keys

Google Search Result Keyboard Focus Navigation

This simple userscript, which runs in browser extensions like Tampermonkey or Greasemonkey, allows you to navigate search results using keyboard shortcuts inspired by vim-style navigation:

  • Press j to move down to the next search result
  • Press k to move up to the previous search result
// ==UserScript==
// @name         Google Search Result Keyboard Focus Navigation
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Move focus to links using the "j" and "k" keys
// @author
// @match        https://www.google.com/search?*
// @exclude
// @grant        none
// ==/UserScript==

;(function () {
  'use strict'

  // Add custom CSS to forcibly show the outline when focused
  const style = document.createElement('style')
  style.innerHTML = `
        /* Use !important to prevent being overridden by Google's custom styles */
        a:focus {
            outline: 1px dotted #212121 !important;
            outline: 5px auto -webkit-focus-ring-color !important;
        }
    `
  document.head.appendChild(style)

  let currentIndex = -1
  let resultLinks = []

  // Function to get search result links
  function refreshResults() {
    resultLinks = []
    const h3Elements = document.querySelectorAll('#search a h3')
    h3Elements.forEach(function (h3) {
      const a = h3.closest('a')
      if (a) {
        resultLinks.push(a)
      }
    })
  }

  // Get the initial set of search result links
  refreshResults()
  if (resultLinks.length > 0) {
    currentIndex = 0
    focusResult(currentIndex)
  }

  // Focus the currently selected link and scroll to it
  function focusResult(index) {
    if (resultLinks[index]) {
      resultLinks[index].focus()
      resultLinks[index].scrollIntoView({ behavior: 'smooth', block: 'center' })
    }
  }

  // Listen for key presses
  document.addEventListener('keydown', function (e) {
    // Ignore key presses inside input fields or textareas
    const tagName = e.target.tagName.toLowerCase()
    if (tagName === 'input' || tagName === 'textarea') return

    // Pressing "j" focuses the next link
    if (e.key === 'j' || e.key === 'J') {
      if (currentIndex < resultLinks.length - 1) {
        currentIndex++
        focusResult(currentIndex)
      }
    }
    // Pressing "k" focuses the previous link
    else if (e.key === 'k' || e.key === 'K') {
      if (currentIndex > 0) {
        currentIndex--
        focusResult(currentIndex)
      }
    }
  })
})()

Installation

To use this script:

  1. Install a userscript manager like Tampermonkey or Greasemonkey for your browser
  2. Create a new script and paste the above code
  3. Save and enable the script
  4. Visit Google and start searching