Safari's Custom Style Sheet

I had no idea I could do this
I had no idea I could do this

This past weekend, I discovered a real rabbit hole of a thing: Desktop Safari has the ability to load custom style sheets!

😱

What does this mean, exactly?

  1. It means I no longer have to harangue the proprietors of horribly designed websites to change things up 👍🏼

  2. It means bye bye Arial, and hello Avenir 💯

  3. It means I can finally read Daring Fireball without Reader mode 🤓

The History of User-defined Style Sheets in Desktop Safari

As far as I can tell, Safari’s had the option of loading a custom style sheet since version 1 was released in January 2003.

I scoured the web for official Safari release notes from those early days, but alas, I couldn’t find any.

The best evidence I’ve found that custom style sheets have been an option since version 1 is Sven-S. Porst’s snarky blog post from January 2003, entitled Quarter Life Crisis. In his post, Porst compares the newly-released Safari with Chimera:

Then, everything that’s missing in Chimera is there: Font encoding menu? Check. Google search field? Check. Location bar/sheet that autocompletes, taking into account both the history and your bookmarks? Check. Popup window blocking that’s easy to toggle on and off in case there’s a stubborn site? Check. Same for cache cleaning? Check. (Well, that’d be rather useless, frankly, if Safari were cleverer about reloading pages. It’s cache seems to be a bit more reluctant to reload pages and see changes in them while Chimera has no troubles whatsoever with this.) Very easy preferences? Check. …that still enables you to set a style sheet? Check. That one’s quite cool. [emphasis added]

I checked the page source, but his post predates the convention of including a <meta> tag with the publishing time. So I checked the Wayback Machine. The earliest cached entry for Porst’s post was March 2004. So while there’s no cached version of the post from January 2003, March of the next year is definitely still pre-Safari 2 (April 2005).

Of course I went to the source. Gramps, also known as Don Melton, is a former Director of Internet Technologies at Apple, and headed the teams behind Safari and WebKit development.

So no help there, but it seems custom style sheets have been around since the beginning.


Although I’m elated the Safari/WebKit team decided to include this feature, part of me wonders why it was included at all.

Apple has never been that open of a company. Allowing users to make their own decisions about how things should function, or how things should look—or what they even want—that isn’t exactly Apple’s M.O.

Because my own Apple journey started in 2006, Safari 1 was before my time. My hunch is that the Safari/WebKit team added a custom style sheet option because back then, most web designers were not utilizing CSS. From what I gather about the early days of the web, referencing external style sheets was not commonplace at first. Moreover, having a nice-looking website wasn’t necessarily a priority back then. Rather than have a sub-optimal web browsing experience, Safari/WebKit engineers let power users choose their own styles.

Of course, CSS eventually became more prominent, and then a web standard. It’s 2018. The case for a custom style sheet option in today’s Safari may not be as strong as it was 15 years ago. But it’s probably one of those things that current Safari engineers look at every year and ask, “Why take it out now?”

I sure am glad it’s there 😆

And that’s it for my brief history of Safari’s custom style sheet option.[1]

Now let’s talk about implementing the custom style sheet, so that you can make your web browsing dreams come true.

Implementing Safari’s Custom Style Sheet

It’s easy:

  1. Create a style sheet and put it somewhere you’ll remember

    Here’s mine in SCSS/Sass, because I forget whether CSS finally has variables:[2]

    Never have I used so many `!important` value additions in my declarations 😞 (More on that later)
    Never have I used so many `!important` value additions in my declarations 😞 (More on that later)
  2. Open Safari preferences, and navigate to the Advanced tab

  3. From the `Style sheet` dropdown menu, locate and select the style sheet you created in Step 1

  4. Be happy.

Issues

After spending the better part of last weekend tweaking my custom style sheet, I have to say: I’m pretty impressed with myself 🎉

I meant what I said earlier, though: this has been such a rabbit hole. I thought endlessly tweaking the minutia of my own websites was tiring. Little did I know it would be even more daunting to mess with everyone else’s websites.

And in scratching that itch, I have run into a few walls 🏗️

All or Nothing

After fiddling with it a bit, I realized my custom style sheet was being applied to all websites I visited. (Duh 🤦🏼‍♂️) And the problem with that is some websites have great styles without my help—why would I want inject my own styles if their’s were already okay?

And if I needed to selectively apply my styles, what was the best way to go about it?

Blacklisting vs./and/or Whitelisting Websites

At first, I was trying to target each website individually. I would peek at the page source, looking for id's or class's that were unique to each website, and target those specific websites in my style sheet—sort of like a blacklist. But then I realized—I did a lot of realizing this past weekend—that method would be untenable, because bad websites with horrible styles likely outnumber the good websites with pleasing styles—by a huge margin, no doubt.[3]

So what about applying the opposite approach? Instead of targeting specific ugly websites and their specific ugly website selectors, I could just assume that most websites look like trash![4] And then I could just apply my styles to all websites, and selectively un-style those sites that already looked good. In other words, I could have a whitelist.

What I ended up doing was something more like a blacklist, but with some whitelist characteristics mixed in.

I knew I didn’t want to apply my generic website styles to my personal websites (or websites for which I am a quasi-administrator).

So I applied a class toni to the <html> elements of all my websites:

<html class="toni">

That allowed me to use the negation pseudo-class :not() to prevent any of my custom styles from being applied to the websites I’ve made or administer:

html:not(.toni) {
	body {
		font-family: Avenir !important;
		font-weight: 500 !important;
		// (More styles)
	}
}

I’m effectively selecting-out the “good” (my) websites that need no styling—like a whitelist. Theoretically, I could have done the same for other websites with good styles, but I’m too lazy for that, and I think my styles generally look better than their’s—even if they weren’t that bad to begin with.[5]

And for any situations where my styles are not specific enough, I’ve also included a few selectors targeting those stubborn sites—like a blacklist.

This is a portion of my style sheet targeting Marco Arment’s blog. I had to adjust the size of his “masthead,” because when I increased the font-size across the board, it overwhelms his colorful “masthead” at the top of the webpage:

#mastheadbackground {
  	height: 200px !important;
  	margin-bottom: -200px !important;
}
Without specific Marco.org blacklisting. See how the title text isn't vertically centered in the brown masthead?
Without specific Marco.org blacklisting. See how the title text isn’t vertically centered in the brown masthead?
With specific Marco.org blacklisting. See how the title text is now vertically centered in the brown masthead? That's because I made the masthead 'taller.' (Probably would have been better if Marco used `display: flex;` in this situation, but what do I know?)
With specific Marco.org blacklisting. See how the title text is now vertically centered in the brown masthead? That’s because I made the masthead ‘taller.’ (Probably would have been better if Marco used `display: flex;` in this situation, but what do I know?)

That’s just one example. If you dive into my style sheet, you’ll see more of what I’m talking about.

JavaScript Ruins Everything

Most of the websites/blogs I follow adhere to web standards and common practices. They have semantic document models, with id's and class's that make sense, and eschew inline styles for referenced external style sheets. Basically, I can style most websites easily enough.

However, the recent trend—especially for big publishers—is to dynamically generate content and styles using server-side and client-side JavaScript. Scripts running in the browser window collect data such as the browser type, and use that and other information to determine how to best present the content.

As far as styles go, that usually means inlining. If styles are based on classes that are generated by JavaScript, it’s that much more difficult for me to isolate them and override them. Moreover, the big websites usually have super complex style sheets—some with thousands of lines of code.

JavaScript inlining and complex style sheets make for a specificity nightmare! In those situations, I may have Avenir for the title of the site, or maybe in the other headings, for instance, but the body text may still be whatever the author chose. You’ll notice that I’ve included !important after every declaration. (That’s sort of like the `ignore everything else and just do what I said in this declaration` CSS command.) Sometimes, that’s not even enough to overcome the insane levels of specificity for some of these websites.

Still, mostly Avenir is better than mostly Arial /or Helvetica, Verdana, or Comic Sans (😖)—I’ll take what I can get.

If you haven’t already done so, try playing around with a custom style sheet in Safari—I think you’ll be glad you did 💻


  1. If there are any early Netscape/Chimera/Safari/WebKit engineers or historians or experts reading this blog post, please let me know whether my version of history is correct, and/or if I should add something for clarity 🤗

  2. Vanilla CSS does have variables, but CSS still doesn’t have nesting, or that neat little & that makes SCSS/Sass so great.

  3. My style sheet would be littered with stupid selectors like this:

    #collection-55f20fcce4b00eb5577ba5e2.transparent-header.enable-nav-button.nav-button-style-outline.nav-button-corner-style-rounded.banner-button-style-outline.banner-button-corner-style-rounded.banner-slideshow-controls-arrows.meta-priority-date.hide-entry-author.hide-list-entry-footer.hide-sidebar-title.hide-blog-sidebar.center-navigation--info.hide-site-info.event-thumbnails.event-thumbnail-size-32-standard.event-date-label.event-date-label-time.event-list-show-cats.event-list-date.event-list-time.event-list-address.event-icalgcal-links.event-excerpts.event-item-back-link.gallery-design-grid.aspect-ratio-auto.lightbox-style-light.gallery-navigation-bullets.gallery-info-overlay-show-on-hover.gallery-aspect-ratio-32-standard.gallery-arrow-style-no-background.gallery-transitions-fade.gallery-show-arrows.gallery-auto-crop.product-list-titles-under.product-list-alignment-center.product-item-size-11-square.product-image-auto-crop.product-gallery-size-11-square.show-product-price.show-product-item-nav.product-social-sharing.newsletter-style-light.opentable-style-light.small-button-style-solid.small-button-shape-square.medium-button-style-solid.medium-button-shape-square.large-button-style-solid.large-button-shape-square.image-block-poster-text-alignment-center.image-block-card-dynamic-font-sizing.image-block-card-content-position-center.image-block-card-text-alignment-left.image-block-overlap-dynamic-font-sizing.image-block-overlap-content-position-center.image-block-overlap-text-alignment-left.image-block-collage-dynamic-font-sizing.image-block-collage-content-position-top.image-block-collage-text-alignment-left.image-block-stack-dynamic-font-sizing.image-block-stack-text-alignment-left.button-style-solid.button-corner-style-square.tweak-product-quick-view-button-style-floating.tweak-product-quick-view-button-position-bottom.tweak-product-quick-view-lightbox-excerpt-display-truncate.tweak-product-quick-view-lightbox-show-arrows.tweak-product-quick-view-lightbox-show-close-button.tweak-product-quick-view-lightbox-controls-weight-light.native-currency-code-usd.collection-type-page.collection-layout-default.collection-55f20fcce4b00eb5577ba5e2.homepage.mobile-style-available.has-banner-image.general-page
    
  4. 🤣

  5. I don’t mean to imply that I’m some sort of amazing front-end designer or anything! I am not suggesting that someone else’s style looks bad (okay, maybe a little). Mostly, I just know what I think looks good, and that’s what done with my style sheet.