Greasy Fork is available in English.

Drag upwards to open in new tab

Click and drag a link upwards (20 pixels or more) to open it in a new tab. This script is particularly convenient if you override links to open in current tab by default using an extension or a script like https://greasyfork.org/scripts/4416

// ==UserScript==
// @name        Drag upwards to open in new tab
// @description Click and drag a link upwards (20 pixels or more) to open it in a new tab. This script is particularly convenient if you override links to open in current tab by default using an extension or a script like https://greasyfork.org/scripts/4416
// @match       *://*/*
// @grant       none
// @run-at      document-start
// @namespace   https://greasyfork.org/en/users/2159-woxxom
// @author      wOxxOm
// @version     1.0.0
// @license     MIT
// ==/UserScript==

let timer, a, x, y, evtMove, evtEnd, isDragging;

addEventListener('mousedown', start, true);
addEventListener('dragstart', start, true);

function start(e) {
  stop();
  if ((a = !isDragging && !e.button && e.composedPath().find(el => el.localName === 'a'))) {
    evtMove = /drag/.test(e.type) ? 'dragover' : 'mousemove';
    addEventListener(evtMove, observe);
    startTimer();
    x = e.clientX;
    y = e.clientY;
  }
}

function startTimer() {
  if (timer)
    clearTimeout(timer);
  timer = setTimeout(stop, 1000);
}

function observe(e) {
  if (!a)
    return stop();
  e.preventDefault();
  if (Math.abs(e.clientX - x) / Math.abs(y - e.clientY || 1) > .5 || e.clientY > y) {
    stop();
  } else if (!isDragging && y - e.clientY > 20) {
    isDragging = true;
    a.style.outline = 'green solid 2px';
    a.style.outlineOffset = '5px';
    evtEnd = /drag/.test(e.type) ? 'dragend' : 'mouseup';
    addEventListener(evtEnd, open);
  }
}

function open(e) {
  if (isDragging && e.screenY > 0 && e.clientY > 0)
    Object.assign(a.cloneNode(), {target: '_blank'}).click();
  stop();
}

function stop() {
  if (timer)
    clearTimeout(timer);
  if (isDragging) {
    isDragging = false;
    a.style.outline = '';
    a.style.outlineOffset = '';
  }
  removeEventListener(evtMove, observe);
  removeEventListener(evtEnd, open);
}