Scroll to top/bottom and PageUp/PageDown buttons

Add semi-transparent buttons to scroll to the top, bottom or by one page to the side of every page. Useful when reading web pages on e-ink screens.

As of 2023-02-28. See the latest version.

// ==UserScript==
// @name         Scroll to top/bottom and PageUp/PageDown buttons
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Add semi-transparent buttons to scroll to the top, bottom or by one page to the side of every page. Useful when reading web pages on e-ink screens.
// @author       xiaq
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant        none
// @license      BSD 2-clause
// ==/UserScript==

(function() {
    'use strict';

    const upDownScrollFactor = 0.8; // How much of the page PageUp/PageDown scrolls by
    const opacity = 0.5; // Opacity of all buttons. 0 = transparent, 1 = opaque
    const right = true; // true = right side, false = left side
    const sideGapPx = 8; // Gap between each button with the left/right side of the page
    const upDownGapPx = 12; // Gap between PageUp and PageDown buttons
    const topBottomGapPx = 16; // Gap between a Top/Bottom button with the top/bottom of the page
    const boxSizePx = 48;
    const fontSizePx = 32;

    const commonStyle = `
        opacity: ${opacity};
        width: ${boxSizePx}px;
        height: ${boxSizePx}px;
        font-size: ${fontSizePx}px;
        border: 1px solid black;
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        ${right? 'right' : 'left'}: ${sideGapPx}px;
    `;

    // Top
    addButton('⤒', () => { window.scrollTo(0, 0); },
             `top: ${topBottomGapPx}px;`);
    // Bottom
    addButton('⤓', () => { window.scrollTo(0, document.body.scrollHeight); },
             `bottom: ${topBottomGapPx}px;`)
    // PageUp
    addButton('▲', () => { scrollByFactor(-upDownScrollFactor) },
              `bottom: calc(50% + ${upDownGapPx / 2}px);`);
    // PageDown
    addButton('▼', () => { scrollByFactor(upDownScrollFactor) },
              `top: calc(50% + ${upDownGapPx / 2}px`);

    function addButton(text, onclick, style) {
        const button = document.createElement('button');
        button.innerText = text;
        button.onclick = onclick;
        button.style = commonStyle + style;
        document.body.appendChild(button);
    }

    function scrollByFactor(factor) {
        window.scrollBy(0, factor * document.documentElement.clientHeight);
    }
})();