Actions

Work Header

Rating:
Archive Warning:
Fandoms:
Additional Tags:
Language:
English
Series:
Part 1 of AO3 Skins , Part 1 of :has() selector
Collections:
Ao3 Skins
Stats:
Published:
2022-08-22
Completed:
2023-08-10
Words:
2,232
Chapters:
3/3
Comments:
236
Kudos:
299
Bookmarks:
280
Hits:
10,379

Permablocking Specific Tags - Site Skin

Summary:

It finally exists. You can block any tag you want forever! You no longer need 3rd party extensions for this!

Notes:

(See the end of the work for notes and other works inspired by this one.)

Chapter Text

Hey, so there is a new thing in the web developer world that is slowly being rolled out to the major browsers that has made it so you can permablock specific tags on AO3 using a site skin. Yes, really. Currently it is working in safari, chrome, and firefox, though firefox and desktop chrome you have to enable a flag to allow it due to it being experimental on the current (non-beta) versions everyone has. I'll cover how to do it, plus how to enable the flags.


So the new thing is a pseudo-selector called :has(). A generic example using it might be


.blurb:has(a) {
color: blue;
}

That would make all work blurbs that have any link (which they all will of course) turn the main text blue. It's a good way to test if you have the :has() flag enabled. Here is what a work search would look like with that code:



Scroll to the flag enabling section at the end if yours doesn't have blue text where mine does.


Now, the next part is to get the actual link to the tag you want to block. This is fairly straightforward, just right click/long press the tag you don't want to see anymore and copy the link. Somewhat important that you don't just click the link and copy from the url bar at the top. This is because the way we are checking which tag is going to be blocked requires the exact link, not whatever it redirects to. So, sadly, you can't utilize wrangled top-level tags to block their subtags or synonyms.


(For example, if you block the tag Romance, it will block things tagged with "Romance", and not things tagged with "Courtship", "a bit of romance", or "summertime love", which are all part of the Romance tag tree, either as subtags or synonyms)


You can however block non-canonical tags. Also, as a commenter pointed out, there is an option for string matching which I'll lay out further down.


So the link you got will look something like https://archiveofourown.org/tags/Drama/works


You will want to remove the https://archiveofourown.org part, leaving only the /tags/Drama/works part.


Then change the first line of your css code from before to say


.blurb:has(a[href$="/tags/Drama/works"]) {


This will change it so only the blurbs with the tag you chose will have the blue text. Here is how that would look:



*New Section Added* Of course, just blocking singular tags is great but sometimes you want to block more general things. Maybe it's all things tagged with a certain character in any relationship, or reader inserts, or just anything that might mention a certain trigger word, even if the tag is saying "No [trigger word]". It's up to you. For that, we need to modify the lookup line ever so slightly and can then remove parts of our link.

xianvar in the comments gave an example of reader and you relationship tags. That code is as follows (slightly altered to make it non-case sensitive):

.blurb:has(a[href*="*s*You/works" i]),
.blurb:has(a[href*="*s*Reader/works" i]),
.blurb:has(a[href*="/tags/Reader*s*" i]),
.blurb:has(a[href*="/tags/You*s*" i])

The change comes in by changing the href$= to href*=.

For any relationship tag, you're going to want to do both halves of the tag so out of order tags will be picked up and blocked too.

Here is how a search page will look if you do the above code, when specifically searching for the tag "Reader Insert" as an additional tag.

Note that because we included the *s* (/) from the relationship tags in the code, it doesn't pickup the one that is tagged with "Reader" and "reader-Insert" without using a reader relationship tag. If you wanted to block everything tagged with a tag that included the word 'reader' you would just leave off the *s*.

*End new section*

Then just change your color:blue line to not display


display: none !important;

So the full code reads like


.blurb:has(a[href$="/tags/Drama/works"]) {
display: none !important;
}

Make sure you are copying the url correctly. A lot of characters have to be encoded in urls such as spaces, non-latin characters, and accented characters. You should not copy the name of the tag and assume the url will match the tag directly.

Here is a before and after of a results page where I filtered out the tags of "Drama" and the non-canonical "oops i made it dramatic" using this code (note the comma between the two tags)


.blurb:has(a[href$="/tags/oops%20i%20made%20it%20dramatic/works"]),
.blurb:has(a[href$="/tags/Drama/works"]) {
display: none !important; }

Before:


After:


Flag Enabling:


Here is how to enable the flags on chrome if you are before version 105 (desktop version, ios is already on 105 and I don't have an android to be able to check):


1: Go to chrome://flags/

2: search Experimental Web Platform features

3: enable it


And for firefox (desktop, seems to work on firefox for ios for me too)

1: Go to about:config

2: accept the instability risk warning

3: search for layout.css.has-selector.enabled

4: enable it


Chapter 2: Tips, Tricks, and Extending things

Summary:

Some tips and tricks I've picked up or been told about since I first made this, plus a little bit about extending this to make things even easier to use

Chapter Text

So, MANY of you have commented and left tips and tricks and notes that have helped, and one person even made their own work inspired by this one that has a TON of info and tips that are super useful. I wanted to make an addition here to showcase some of those tips and tricks and to show a little bit of how this can be combined with some things that make this even easier to work with.


Tip 1: This is just a reminder that when you are getting the url, copy the link! Don't copy it from the URL bar at the top of the page! A LOT of characters get encoded for URLs, but especially punctuation, non-english alphabet characters (including characters with accent marks and umlauts), and some other common text things like spaces. The vast majority of people asking for help troubleshooting have ended up with this being their issue.

Tip 2: Case sensitivity is a thing. Take this example: Fic 1 is tagged with "Lawyer!AU", and fic 2 is tagged with "lawyer!au". If you used a standard lookup of a[href="Lawyer!AU"] you would be surprised to find out that only fic 1 would be selected for being hidden/highlighted/etc. This is because upper and lowercase letters are different things for computers. Luckily, whoever dictates CSS made an easy workaround by adding an "i" to the end of the lookup info before the closing bracket. So for our example, switching to a[href="Lawyer!AU" i] would select both fic 1 and fic 2.

Tip 3: Not entirely relevant to blacklisting tags, but the :has() selector has a lot of other possible uses. I really recommend checking out najio's work that was inspired by this one for some examples of useful things it can do.

and lastly Tip 4/how to extend this: So, you're a avid reader and you have particular tastes. You find yourself wanting to blacklist a whole bunch of different tags and their permutations. But site skins have a character limit and also typing up hundreds of different sets of these codes is a lot of work, right? Even worse, you want to blacklist things unless a specific other tag shows up? Well, as najio pointed out in their work, there are really useful other pseudo selectors called :is() and :not(). (note: :is() used to be called :matches() so some older browsers you may need to switch out the :is() for that)


The way :is() works is that it allows for a bunch of possible options to be listed and selected between. So, for example, if I wanted to filter out Magic, Mutants, and Family, I could do the following code


.blurb:has(a[href*="Magic" i])

{

display: none !important;

}

.blurb:has(a[href*="Mutants" i])

{

display: none !important;

}

.blurb:has(a[href*="Family" i])

{

display: none !important;

}

Which can be shortened down to

.blurb:has(a[href*="Magic" i]),

.blurb:has(a[href*="Mutants" i]),

.blurb:has(a[href*="Family" i])

{

display: none !important;

}

But, you can shorten it even further with :is(), which would look like:

.blurb:has(a:is([href*="Magic" i], [href*="Mutants" i], [href*="Family" i]))

{

display: none !important;

}

Which is super useful to make things a little easier to type out when you have LOTS you want to exclude.

But, what about effectively whitelisting a tag? Let's say you really don't like AUs, but you don't mind a certain type of AU like canon divergence. So you want to exclude all of the possible AU tags, but not the ones that are canon divergence. Well, that's where the :not() pseudo selector comes into play. You just tack it onto the end with a :has() inside and use it just like you do the regular :has() selector by putting in the tag you want whitelisted (you can also use the :is() here if you want multiple whitelisted tags). So the code example I used was:


.blurb:has(a:is([href*="Alternate%20Universe" i],[href*="%20AU" i],[href*="!au" i])):not(:has(a[href*="Canon%20Divergence" i]))

{

display: none !important;

}

That will blacklist all of the tags that contain the terms "Alternate Universe", " AU" (note there is a space before the AU) or "!AU" , but if the work blurb has "Alternate Universe - Canon Divergence" or "Canon Divergence" as a tag, it would show up.

(second note, "au" is a semi-common letter combination outside of being an acronym for Alternate Universe, so this may select a handful of works that have tags like "Character has autism" or "reading auras" etc. just be warned of that kind of thing when using partial matches on short letter combinations.)

So example:

Fic 1 has the tag of "Alternate Universe - Fairies", Fic 2 has the tag "Alternate Universe - Canon Divergence", Fic 3 has the tags "fairy au" and "Alternate Universe - Canon Divergence", Fic 4 has the tags "Fairy!AU" and "Canon Divergence", using the code above, Fic 1 would be hidden, and fics 2, 3, and 4 would show up. To switch it so fics 1, 3 and 4 all were hidden and only fic 2 showed up, move the :not() inside of the :has() like so


.blurb:has(a:is([href*="Alternate%20Universe" i],[href*="%20AU" i],[href*="!au" i]):not(a[href*="Canon%20Divergence" i]))

{

display: none !important;

}

Anyways, I hope this helped some of you out. Let me know if you have any issues or comments!

Chapter 3: Knowing when something was removed

Summary:

The current way this is done, you don't see any information about the thing being hidden. Here is how to add something to signify that a blurb was removed

Chapter Text

Hey, so sorry there aren't any images right now, I'll add some later. But for now, here is a bit of an update for those who don't want the muted tagged work blurbs to completely disappear (so you know when something is removed).

So if our current code is:

.blurb:has(a[href*="/tags/Violet%20the%20Hippo/works" i])
{
display: none !important;
}

that would remove the work blurb entirely. So we're going to add a new part in addition to that.

.blurb:has(a[href*="/tags/Violet%20the%20Hippo/works" i]):before
{
content: "Work blurb removed for containing a muted tag";
}

That will add a little note into the blurb box that says whatever is written in the quotes. In this case "Work blurb removed for containing a muted tag".

but it won't show up if we just added that in addition to the first bit of code. This is because that first bit of code just makes the entire box (including the line we added) disappear. So we need to edit it to only remove the child elements. You can do this like so:

.blurb:has(a[href*="/tags/Violet%20the%20Hippo/works" i]) > *
{
display: none !important;
}

That will remove all of the elements inside the blurb box, except for the note we added about it having a muted word.

So, combined, your code will be like this:

.blurb:has(a[href*="/tags/Violet%20the%20Hippo/works" i]):before
{
content: "Work blurb removed for containing a muted tag";
}
.blurb:has(a[href*="/tags/Violet%20the%20Hippo/works" i]) > *
{
display: none !important;
}

Notes section:

  • This should still work with all of the other fancy options for selection like :is() and :not(), you just need to copy it exactly.

  • If you are using an :is() selector to select for multiple possible tags, there isn't a way to make the text say which tag caused the blurb to be muted.
  • You cannot add a link to the work to bypass the mute. Only plain text can be added sadly. If you want to be able to access the work despite having the muted tag, change your code to this (plus the other half from before with the muting note):
    .blurb:has(a[href*="/tags/Violet%20the%20Hippo/works" i]) > *:not(.module) {
    display: none !important;
    }

    Just the header will show up under the note we added. There are ways to also remove things like the ratings boxes and fandom tags if you just wanted the link and nothing else, but that seemed too specific for a general tutorial like this. Ask in the comments if you want the code for that!

Hope this helps!

Notes:

Let me know if you are having any trouble! <3

Series this work belongs to: