Unfix

Stop fixed/sticky elements leeching my valuable screen real estate!

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name	Unfix
// @description	Stop fixed/sticky elements leeching my valuable screen real estate!
// @author	Remph
// @license	GPL-3.0-or-later
// @version	0.2.5
// @include	*
// @namespace	https://git.sr.ht/~remph/unfix.js
// @homepageURL	https://git.sr.ht/~remph/unfix.js
// @supportURL	https://git.sr.ht/~remph/unfix.js
// @grant	none
// @compatible	firefox
// ==/UserScript==

'use strict';

function unfix_element(e) {
	var newpos;
	switch (getComputedStyle(e).position) {
	case 'fixed':
		newpos = 'absolute';
		break;
	case 'sticky':
		newpos = 'relative';
	}
	if (newpos) {
//		console.debug('setting ' + e.tagName + ' to ' + newpos);
		e.style.setProperty('position', newpos, 'important');
		/* I would rather not have abused !important ^ here, to let
		   pages specify when the position really *is* important
		   and shouldn't be elided, but no-one can be responsible
		   with it so I will take it away */
	}
}

function unfix_tree(root) {
	if (root.nodeType !== Node.ELEMENT_NODE)
		return;
	unfix_element(root);
	// NodeFilter.SHOW_ATTRIBUTE ?
	var t = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
	while (t.nextNode())
		unfix_element(t.currentNode);
}

(function () {
	// wait for window to finish loading to prevent races on style
	window.addEventListener('load', () => unfix_tree(document.body));

	// Catch sneaky attempts to re-fix an element from js
	new MutationObserver((muts) => muts.forEach(function (mut) {
		/* Are these sure to be mutually exclusive? Can an
		   attributes change also have addedNodes? */
		switch (mut.type) {
		case 'attributes':
			unfix_element(mut.target); // if (mut.attributeName == 'style') ?
			break;
		case 'childList':
			mut.addedNodes.forEach(unfix_tree);
		}
	})).observe(document.body, {
		subtree: true, childList: true, attributes: true
	});
})();