Hide that crap from people or pages you don't follow on facebook. Requires some scrolling before it works.
https://*.facebook.com/*
(function () {
let clusterFound = false;
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
function isValidClusterCandidate(el) {
if (!el || el.tagName !== "DIV") return false;
const classList = Array.from(el.classList);
return (
classList.length >= 1 &&
!Array.from(classList).some(c => c.startsWith("__fb-"))
);
}
function findClusterClassFromHeader() {
const headings = Array.from(document.querySelectorAll("h3"));
const header = headings.find(h => h.textContent.trim().toLowerCase() === "news feed posts");
if (!header) return null;
const siblings = Array.from(header.parentElement?.children || []);
const headerIndex = siblings.indexOf(header);
const containersAfterHeader = siblings.slice(headerIndex + 1);
const visibleDivs = containersAfterHeader.filter(el =>
el.tagName === "DIV" && el.getAttribute("aria-hidden") !== "true"
);
const targetContainer = visibleDivs[0];
if (!targetContainer) return null;
const classMap = {};
const children = Array.from(targetContainer.children);
for (const child of children) {
if (!isValidClusterCandidate(child)) continue;
const classKey = Array.from(child.classList).sort().join(" ");
classMap[classKey] = classMap[classKey] || [];
classMap[classKey].push(child);
}
const sorted = Object.entries(classMap)
.filter(([_, group]) => group.length > 1)
.sort((a, b) => b[1].length - a[1].length);
if (sorted.length === 0) return null;
return {
className: sorted[0][0],
container: targetContainer
};
}
function isRemovableItem(el) {
const text = el.innerText?.toLowerCase() || "";
return text.includes("follow") || text.includes("join");
}
function removeMatchingItems(classSelector) {
const items = Array.from(document.querySelectorAll(`div.${classSelector.split(" ").join(".")}`));
for (const item of items) {
if (isRemovableItem(item)) item.remove();
}
}
function observeNewItems(classSelector) {
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (!(node instanceof HTMLElement)) continue;
const selector = `div.${classSelector.split(" ").join(".")}`;
if (
node.matches?.(selector) &&
isRemovableItem(node)
) {
node.remove();
continue;
}
const nestedMatches = node.querySelectorAll?.(selector) || [];
for (const nested of nestedMatches) {
if (isRemovableItem(nested)) {
nested.remove();
}
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
console.log(`👀 Observing for new <div class="${classSelector}"> items`);
}
function attemptToFindClusterAndInit() {
if (clusterFound) return;
const cluster = findClusterClassFromHeader();
if (cluster?.className) {
clusterFound = true;
console.log(`✅ Cluster found: "${cluster.className}". Cleaning and observing.`);
removeMatchingItems(cluster.className);
observeNewItems(cluster.className);
// 🔁 Cleanup again shortly after observer starts, to catch race conditions
setTimeout(() => removeMatchingItems(cluster.className), 100);
} else {
console.log("❌ No valid cluster found. Will retry on scroll.");
}
}
// Initial run
attemptToFindClusterAndInit();
// Retry on scroll (debounced)
const debouncedRetry = debounce(attemptToFindClusterAndInit, 300);
window.addEventListener("scroll", debouncedRetry);
})();Install requires the InjectJS Chrome extension. Scripts run only on sites matching the pattern above. Review code before installing any community script.