A Collection of Web Customizations
When I'm using a computer, I spend just under half of my time in a web browser, and often find occasion to customize this experience, mostly through userscripts or custom CSS. Most of these customizations are either too specific to me or too jury-rigged to make sense to publish, but for the ones that could be more generally applicable, I'll catalog them here. Most of these end up being for Google Apps, because there's a lot of things about their styling that annoy me.
Custom Bookmark Favicons in Firefox
I use Firefox as my main browser, and overall I'm very happy with it. However, one thing I like to do is to assign custom favicons to different sites to make them easier to spot in the tab bar.
There are many Firefox add-ons that allow you to assign custom favicons to URLs or URL patterns, but due to the way Firefox grabs bookmark favicons, none of these add-ons let you show those favicons in the Bookmarks bar.
The proper way to get around this would be to fix this in
Firefox, go through the PR process, etc. In the meantime, we
can get around this with a (somewhat silly) solution. I host a
stateless HTTP API at 0xA.click
that accepts two GET arguments: p,
a URL-encoded png;base64 string
with your chosen favicon, and u,
the target URL you want to go to.
The API will return a bare-bones HTML page that sets the
favicon and then meta redirects
your browser to the target page. It keeps no logs and has a
Cache-Control header of 1 year, so
your browser should only have to send a request on bookmark
creation and then annually afterwards.
(Show code)
import base64
import urllib.parse
def lambda_handler(event, context):
# Get query params
params = event.get("queryStringParameters", {}) or {}
p = params.get("p")
u = params.get("u")
favicon_data = ""
if p:
try:
# Decode URL encoding
p_decoded = urllib.parse.unquote(p)
favicon_data = f"data:image/jpeg;base64,{p_decoded}"
except Exception:
favicon_data = ""
redirect_meta = ""
if u:
u_decoded = urllib.parse.unquote(u)
redirect_meta = f'<meta http-equiv="refresh" content="0;url={u_decoded}">'
# Build HTML response
html=f'<!doctype html>{f"<link rel=icon href={favicon_data}>"if favicon_data else""}{redirect_meta}<style>body{{background:#000}}</style>'
return {
"statusCode": 200,
"headers": {
"Content-Type": "text/html; charset=utf-8",
"Cache-Control": "public, max-age=31536000, immutable"
},
"body": html
}
I must note that any half-decent security-minded person would (wisely) tell you never to trust a third-party API like this, as it leaves you vulnerable to redirection attacks by either (A) me or (B) anyone who manages to break into my AWS account. The (slightly) smarter thing to do would be to self-host this locally, or (probably best) to just deal with default favicons.
However, if you want custom favicons more than you value your own security, then please feel free to use it. I also maintain a Firefox add-on (linked above) which combines the API with normal local favicon injection and does some additional trickery to dodge Firefox's strange favicon caching behaviors.
The custom favicons look like the following (example: "Pm" favicon for personal mail, "Ym" favicon for Yale mail):
Better Google Sheets tab coloring
I tend to use Google Sheets for most of my spreadsheeting needs -- quick data visualization, manual labeling/cleaning, etc. I find it helpful to color-code spreadsheet tabs (sheets), but unlike in Excel, in Sheets the tab colors are only a small bar along the bottom.
With the following CSS injected into all
docs.google.com/spreadsheets/*, we can reproduce the
Excel behavior:
(Show code)
.docs-sheet-tab-color {
height: 100% !important;
z-index: -1;
opacity: 50%;
}
div:has(.docs-sheet-tab-color) span {
color:black !important;
}
This produces the following effect:
Color-coded Google accounts
I have a several different Google accounts -- a work email, a personal email, one for ham radio, one for Wikipedia, etc. The default Google accounts switcher does show color-coded profile icons and letters for easy switching, but the letters aren't so useful when most of your emails start with the same letter (for instance, the first letter of your name).
I inject the following CSS to all
*.google.com
to give custom color codes to accounts in the switcher:
(Show code)
/* Colored background: */
div[data-identifier="e1@email.com"], a[data-email="e1@email.com"] {
background-color: #color1 !important;
}
/* To "grey out" an account: */
div[data-identifier="grey@email.com"] *, a[data-email="grey@email.com"] * {
opacity: 0.7 !important;
}
div:has(> span > div > button[data-email="grey@email.com"]) {
opacity: 0.3 !important;
}
/* Text color (for dark mode): */
.lPxAeb .yAlK0b {
color: #444746 !important;
}
.lPxAeb .pGzURd {
color: #1f1f1f !important;
}
This produces the following effect:
Gmail search bar
One thing that always bothers me is the big gap in the Gmail header bar between the Gmail icon and the search bar. This is particularly noticeable when the window is narrower than about 1000px.
I inject the following CSS to
mail.google.com:
(Show code)
.gb_Qd.gb_pd.gb_qd {
min-width: 0px !important;
padding-right: 0px !important;
}
.qp.qp .aJf[method="get"][role="search"] {
margin-left: -45px;
}
.gb_Qd:not(.gb_Ke) .gb_Fe {
padding-left: 0px !important;
}
This produces the following effect:
Ebay prices
On the rare occasion I need to buy something on eBay, I prefer to
see the item price including any shipping costs, to make rapid
comparisons easier. I inject the following Javascript, along with a
minimal jQuery build, to
www.ebay.com/sch/i.html*:
(Show code)
(function() {
'use strict';
$('.su-card-container__attributes').each(function () {
// get price
let priceText = $(this).find('.s-card__price').first().text();
let price = parseFloat(priceText.replace(/[^0-9.]/g, ''));
// get shipping
let shippingText = $(this)
.find('.s-card__attribute-row:contains("delivery")')
.first()
.text();
let shipping = parseFloat((shippingText.match(/[\d.]+/) || [0])[0]);
// fallback if shipping not found
if (isNaN(shipping)) shipping = 0;
let total = price + shipping;
let ttf = total.toFixed(2).replace(".00", "");
let ptf = price.toFixed(2).replace(".00", "");
let stf = shipping.toFixed(2).replace(".00", "");
// update displayed price
$(this).find('.s-card__price').first().html('$' + ttf + '');
if (shipping > 0) {
$(this).find('.su-styled-text.secondary.large:contains("delivery")').first().html('$' + ptf + ' + $' + stf + ' delivery');
}
});
})();
This produces the following effect: