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)