Skip to content

Instantly share code, notes, and snippets.

@vbuaraujo
Last active September 27, 2024 11:26
Show Gist options
  • Select an option

  • Save vbuaraujo/bddb3b93a0b2b7e28e1b to your computer and use it in GitHub Desktop.

Select an option

Save vbuaraujo/bddb3b93a0b2b7e28e1b to your computer and use it in GitHub Desktop.
GreaseMonkey script to remove "position: fixed" from webpages
// ==UserScript==
// @name unfix-all-the-toolbars
// @description Removes "position: fixed" style from elements, unfixing "toolbars" and the such.
// @namespace http://inf.ufrgs.br/~vbuaraujo/
// @include *
// @version 1
// @grant none
// ==/UserScript==
/*
Based on https://stackoverflow.com/questions/13696100/greasemonkey-script-to-make-fixed-positioned-elements-static
2015-02-17: Original version.
2016-05-01: Added the styleWidth threshold heuristic.
2016-05-02: The fight goes on. Keep track of dynamic changes to "fixed".
The big problem here is we want to avoid unfixing *all* "position: fixed"
elements, because some of them are fake popup windows which become quite
unusable if you change them to "position: static". So we need some heuristic
to distinguish "legitimate" fixed elements from gratuitous ones like navbars.
Still some problems with weird cases where "bottom" is negative
(e.g., https://slack-files.com/T03JT4FC2-F151AAF7A-13fe6f98da?nojsmode=1).
I don't know how to handle this.
This is really kind of an uphill battle, but there we go.
*/
function numPixels(str) {
if (str.endsWith("px"))
return Number(str.slice(0, -2));
else {
console.log("unfix-all-the-toolbars: Computed width is not in pixels! " + width);
return null;
}
}
function pageAttributes() {
var bodyStyle = window.getComputedStyle(document.body);
if (bodyStyle === null) {
console.log("bodyStyle is null :(");
throw new Exception("bodyStyle is null :()");
}
var pageWidth = numPixels(bodyStyle.width);
var pageHeight = numPixels(bodyStyle.height);
var toolbarWidthThreshold = 0.6 * pageWidth;
return ({
bodyStyle: bodyStyle,
pageWidth: pageWidth,
pageHeight: pageHeight,
toolbarWidthThreshold: toolbarWidthThreshold
});
}
function unfixAll() {
var attrs = pageAttributes();
Array.forEach(
/* Assorted selection of likely fixed elements, to avoid querying all elements */
document.querySelectorAll("h1, h2, ul, ol, li, div, nav, header, footer, table, tbody, th, tr, td"),
function (el) {
unfixElement(el, attrs);
// Observe further changes.
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.attributeName == "style") {
console.log("Change in style: " + mutation.target);
unfixElement(mutation.target, attrs);
}
})
});
observer.observe(el, { attributes: true });
}
);
}
function unfixElement(el, attrs) {
var style = window.getComputedStyle(el);
if (style.position === "fixed") {
/* Avoid unfixing JavaScript popus like Twitter's "confirm retweet" window */
if (style.display === "none" || style.visibility === "hidden") return;
if (numPixels(style.width) < attrs.toolbarWidthThreshold) return;
// Try to select the best replacement for 'fixed'. Still breaks lots of things, though.
if (numPixels(style.bottom) === 0 && numPixels(style.top) > 0) {
//console.log("STATIC: " + el.id + " " + style.bottom + " " + style.top);
el.style.position = "static"; // Use static for footers.
}
else {
//console.log("ABSOLUTE: " + el.id + " " + style.bottom + " " + style.top);
el.style.position = "absolute";
}
}
}
window.addEventListener("load", unfixAll);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment