Using Firefox's userContent.css for website-specific fixes

March 19, 2017

In a comment on my entry on using pup to fix a Twitter issue, Chris Povirk suggested using Firefox's userContent.css feature to fix Twitter by forcing the relevant bit of Twitter's HTML to actually display. This is actually a pretty good idea, except for one problem; if you write normal CSS there, it will apply to all sites. Anywhere there is some bit of HTML that matches your CSS selector, Firefox will apply your userContent.css CSS fixup. In the case of this Twitter issue, this is probably reasonably safe because it's not likely that anyone else is going to use a CSS class of 'twitter-timeline-link', but in other cases it's not so safe and in general it makes me twitchy.

Luckily, it turns out that there is a way around this (as I found out when I did some research for this entry). In Firefox it's possible to write CSS that's restricted to a single site or even a single URL (among some other options), using a special Mozilla extension to CSS (it's apparently been proposed as a standard feature but delayed repeatedly). In fact if you use Stylish or some other extensions you've already seen this used, because Stylish relies on this Mozilla CSS feature to do its site-specific rules.

How you do this is with a @-moz-document CSS rule (see here for Mozilla's full list of their CSS extensions). The Stylish userstyles wiki has some examples of what you can do (and also), which goes all the way to regular expression matches (and also). If we want to restrict something to a domain, for example twitter.com, the matching operation we want is domain(twitter.com) or perhaps url-prefix(https://twitter.com/).

So in this particular case, the overall userContent.css I want is:

@-moz-document domain(twitter.com) {
  .twitter-timeline-link {
    display: inline !important;
  }
}

(I'm willing to have this affect any Twitter subdomains as well as twitter.com itself.)

This appears to work on Twitter, and I'm prepared to believe that it doesn't affect any other website without bothering to try to construct a test case (partly because it certainly seems to work for things like Stylish). I don't know if using just userContent.css is going to have the memory leak I see with Stylish, but I guess I'm going to find out, since I've now put this Twitter fix in my brand new userContent.css file.

An extension like Stylish appears to have only a few advantages over just modifying userContent.css, but one of them is a large one; Stylish can add and change its CSS modifications on the fly, whereas with userContent.css you appear to have to quit and restart your Firefox session to to pick up changes. For me this is an acceptable tradeoff to avoid memory leaks, because in practice I modified my overrides only rarely even when I was using Stylish.


Comments on this page:

This was super-useful, thanks!

Here's a way to make doing things on the fly with userContent.css doable. :-)

It's quite simple, but I'll give an advanced hack straight after it.

1. Open FireFox Developer Tools to the Style Editor, and you will see userContent.css in the list.
2. Any changes you make here are permanent.

Boom. :-)

But ... that's going to get unweildy now you have all this fresh access. So do this...

1. Make a subfolder in the FireFox chrome folder called (eg): websiteCss
2. Scan your userContent.css for a domain that has a LOT of stuff.
3. In the subfolder make a file: CHRIStwitter.css
4. Paste the entirety of the twitter userContent into the new file, including the @-moz-document opener/closer, then save and close the file.
5. Now in userContent.css, on the first line, type: @import url("websiteCss/CHRIStwitter.css");

This will now import that twitter file, and any declarations within it, when the userContent.css loads.

What's more, both will be in the Developer Tools Style Editor with all the funcationality that it brings. :-)

What's EVEN more ... is that you can do a further hack to organise your massive remake of Twitter. It's as simple as grouping things together under new @-moz-document calls.

This allows you to use the dev tools to 'roll up' the stuff that you're not working on. :-)

So ... Every time you find a bunch of CSS you would like to group together, just wrap them in the call, like so:

@-moz-document domain(twitter.com) /* PINK REDIRECTS */ {
  a[rel="noopener noreferrer"] {
    color: pink !important;
    visibility: visible !important;
    display: flex !important;
    flex-flow: row !important;
  }
}

@-moz-document domain(twitter.com) /* Remove Stuff */{
  a[aria-label="Home"],
  a[aria-label="Search and explore"],
  a[aria-label="Twitter"] {
    display:none !important;
  }
}
Written on 19 March 2017.
« Part of why Python 3.5's await and async have some odd usage restrictions
My theory on why Go's gofmt has wound up being accepted »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Mar 19 01:53:29 2017
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.