A purple, red, black, and white circular logo which reads "GW USS"
The extension logo

The narrative before the recipe

I made a browser extension (my first one!) to allow adding custom css and javascript to any website when it's opened! This way, one can tweak colors, hide extraneous elements, and personalize the functionality of the site. I use it to hide things that annoy me (like AI in google searches) and improve contrast.

There are a good number of other browser extensions that do this same thing, but I wanted to build my own both to learn about that process and also to keep complete control over my browser.

I may write about my experience making this in a future tutorial - I definitely learned a lot!

Downloads

Code

My Snippits

fandom.com

Cleans up bloat

window.setInterval(() => {
	document.querySelectorAll(".top-ads-container, .bottom-ads-container, .gpt-ad").forEach(elem => elem.remove());
}, 50);
Script (js)
*:not(:has(main), main, main *:not(iframe, .upo-label),
:has(nav), nav, nav *,
:has(.wiki-tools), .wiki-tools, .wiki-tools *,
[id^="wds-icons"], [id^="wds-icons"] *,
path,
.fandom-community-header__background,
:has(.search-modal), .search-modal, .search-modal *,
dialog, dialog *) {
	display: none !important;
}

nav {
	padding-inline: 10px !important;
}

.community-header-wrapper {
	height: auto !important;
}
Style (css)

google.com

Hides AI overviews

div:has(> h1):has(svg[viewBox="0 0 471 471"]) {
	display: none !important;
}
Style (css)

github.com

Hides Copilot

:is([data-view-component="true"], button):has(svg.octicon-copilot) {
	display: none !important;
}
Style (css)

console.firebase.google.com

Hides Gemini

:has(> [aria-labelledby="navbar-project-genai"]), fire-gemini-button, button:has(helios-gemini-lockup) {
	display: none !important;
}
Style (css)

reddit.com

Hides ad posts; enables arrowkey carousel navigation

shreddit-ad-post,
shreddit-comments-page-ad,
[recommendation-source="global_good_visits"] {
	display: none !important;
}
Script (js)
document.addEventListener("click", (event) => {
	[...document.querySelectorAll(`gallery-carousel`)].forEach(carousel => {
		carousel.shadowRoot.removeEventListener("keydown", gwCarouselKeydown );
		carousel.shadowRoot.addEventListener("keydown", gwCarouselKeydown );
		carousel.shadowRoot.firstElementChild.setAttribute("tabindex", "-1");
	});
});

gwCarouselKeydown = (event) => {
	let parent = event.target;
	while(parent.parentElement) {
		parent = parent.parentElement;
	}

	if(gwTryAdvanceCarousel(parent, event.key)) {
		parent.focus();
		event.stopPropagation();
	}
};

document.addEventListener("keydown", (event) => {
	[...document.querySelectorAll(`gallery-carousel`)].forEach(carousel => {
		gwTryAdvanceCarousel(carousel.shadowRoot.firstElementChild, event.key);
	});
});

function gwTryAdvanceCarousel(parent, key) {
	let relevantButton = null;
	switch(key) {
		case "ArrowLeft":
			relevantButton = parent.querySelector(`button[aria-label="Previous page"]`);
			break;
		case "ArrowRight":
			relevantButton = parent.querySelector(`button[aria-label="Next page"]`);
			break;
	}
	if(relevantButton && gwIsButtonVisible(relevantButton)) {
		relevantButton.click();
		return true;
	}
	return false;
}

function gwIsButtonVisible(button) {
	if(!button.checkVisibility()) { return false; }
	
	const rect = button.getBoundingClientRect();
	const docElem = document.documentElement;
	return rect.top >= 0
		&& rect.left >= 0
		&& rect.bottom <= (window.innerHeight || docElem.clientHeight)
		&& rect.right <= (window.innerWidth || docElem.clientWidth);
}
Style (css)

tumblr.com

Makes it clearer who's the latest poster

article {
	box-shadow: -3px 0px 0px 0px #8d4a95;
	
	header {
		background-color: #8d4a95 !important;
		
		button, a[style] {
			background-color: rgb(var(--white));
		}
		
		*:not(:is(a, button, button > span)) {
			color: rgba(var(--black), 1) !important;
		}
	}
}

a:not(:has(time)) {
	text-decoration: underline !important;
}
Style (css)