Web DevCenter    
 Published on Web DevCenter (http://www.oreillynet.com/javascript/)
 See this if you're having trouble printing code examples


The CSS Anarchist Strikes Again!

by Eric A. Meyer
03/09/2001

Great news, my revolutionary brothers and sisters! In the months since the publication of The CSS Anarchist's Cookbook, thousands upon thousands of readers have, um, read it. Although the rightness of our cause was never in doubt, this only confirms what I have always said: Nothing can stop the spread of visual anarchy. Thanks to the power of user stylesheets, anyone can upend the Web and turn careful design into uncontrolled chaos. No force can contain it.

Now, like a cobra striking out of the shadows, the CSS Anarchist is back to further arm you in your war against the designer heathen who seek to impose their order on our Web browsers. I bring to you more powerful versions of old design bombs, new ways to strike fear into the hearts of marketing departments, and even methods to drive your bourgeois pigdog co-workers crazy. Forward, comrades!

Upgrading old weapons

Before we start talking about new weapons, let's take a look at improvements to some old ones. One of the most popular instruments of destruction is the banner-ad killer. Version 1 looked like this:

img[height="60"][width="468"], img[height="60px"][width="468px"]
  {display: none !important;}

This isn't too bad, as far as it goes -- any image of standard banner-ad size will be prevented from display. However, this ignores other kinds of elements that might be used in banner ads, like Java applets. So we've upgraded the banner-killer to strike at multiple targets simultaneously:

*[height="60"][width="468"], *[height="60px"][width="468px"]
  {display: none !important;}

Now any element with a height of 60 pixels and a width of 468 pixels will be eliminated without mercy. Remember, this weapon is even more indiscriminate than before: Any element of the targeted size, even those which are not actually banner-ads, will be destroyed. The odds of other elements being precisely this size are admittedly somewhat small, but they are non-zero.

Comment on this articleTell us what you think about Eric's latest CSS recipes. And if you have your own twist on these ideas, well, let's have it.

It's also a good idea to remind you that this killer only works if the height and width of an element are explicitly set using the height and width attributes, and that they exactly match the values we've specified. If not, the weapon will miss its target. Well, nothing is ever perfect, but rest assured that our evil scientists are working to improve this weapon even further.

This warning is especially important in the face of our Mark 2 banner-killer. The Internet Advertising Bureau just recently announced new standard banner sizes. Well, the movement never sleeps, so we've already built an agent to stop this latest assault. Here's how you blow those guys away:

*[height="60"][width="468"],  *[height="60px"][width="468px"],
*[height="60"][width="234"],  *[height="60px"][width="234px"],
*[height="600"][width="120"], *[height="600px"][width="120px"],
*[height="600"][width="160"], *[height="600px"][width="160px"],
*[height="120"][width="240"], *[height="120px"][width="240px"],
*[height="150"][width="180"], *[height="150px"][width="180px"],
*[height="300"][width="250"], *[height="300px"][width="250px"],
*[height="336"][width="280"], *[height="336px"][width="280px"],
*[height="400"][width="240"], *[height="400px"][width="240px"],
*[height="250"][width="250"], *[height="250px"][width="250px"],
  {display: none !important;}

This weapon won't save you from pop-up ads -- you'll need to disable JavaScript if you want to do that -- but it will filter out any element which has the same dimensions as these new banner sizes. Obviously, the odds of innocent elements getting caught in the line of fire is much higher with this one, so be cautious. You might want to tune it to only attack those sizes which really annoy you the most, but of course the choice is yours. Hey, this is anarchy! Do as you like.

In a similar vein, you probably recall the image-killer from our last session:

img {display: none !important;}

This turns off almost every possible image you might encounter ... but not every image. Why is that? Because some images are displayed as part of an input element, as well as object and applet elements. Therefore, if we wish to hunt down as many images as possible, we need to upgrade to:

img, input[type="image"], applet, object, script
 {display: none !important;}

See Figure 1 for an example of using this.

By adding the object and applet elements to our list of targets, we've probably killed off more than just images, since many of these elements are used to display text or other data. Of course, they usually involve dancing text or some other such frippery, so it's really no great loss.

More hunter/killers

While we're at it, let's look at two new weapons which will completely eliminate certain types of data from the Web. The first will help calm down the occasional nervous page:

blink {display: none !important;}

There you go -- no more blink. You're welcome.

Okay, okay, so maybe you just want to neutralize blink without actually eliminating it. In that case, you can try the following:

blink {text-decoration: inherit !important;}

Now, assuming that the parent element has a text-decoration value other than blink, you'll turn off blinking. But you really ought to just blow the element away, if you ask me.

Okay, back to the hunter/killers. This one isn't as much fun to use on your own machine, but it can be downright deadly on somebody else's. How's this for a user stylesheet:

a:hover, a:focus {display: none !important;}

That's right, as soon as the mouse pointer moves over a link, it will completely disappear. Then, when the mouse moves away, it will come back. In many cases, actually, the link might flicker in and out of existence as it cycles in and out of a hover state. For that matter, thanks to the a:focus, links will disappear even when the user tabs to them using the keyboard, which some browsers let you do.

Imagine installing this as a user stylesheet on the system of that annoying guy in the next cubicle over. Then imagine his call to the technical support folks. Now that's entertainment!

Subversion tactics

As fun as wanton destruction can be, there are times when you want to be a little more subtle. Rather than knock big gaping holes in page designs, you might just want to warp the browser's behavior so it doesn't match the norm.

Here's just one possibility: Instead of making hyperlinks disappear whenever the mouse pointer hovers over them (or the user tabs to a link with the keyboard), you want to make them appear to stop being links, and instead seem to be like normal text or images. Here's how:

a:focus, a:hover {cursor: text !important; color: inherit !important;
text-decoration: inherit !important; outline-width: 0 !important;}
a:focus img, a:hover img {cursor: default !important;}

Figure 2
Figure 2. But it was a link, wasn't it? See article text on how to make links convert to plain text on mouseovers.

Text links will be most affected by the first rule. First, we set the cursor to be "text," which is usually an i-bar which lets the user select a range of text. Then we inherit the color and text-decoration of the parent element, which is likely to be normal text (although not always, which means that in some cases the link color might not change). Finally, we set the outline's width to be zero, which will turn off those dotted gray lines in Internet Explorer 5.x for Windows.

The second rule merely changes the cursor behavior if the linked element is an image. The value of default will cause the browser to use the normal system cursor, which is usually an arrow. With these styles, links will appear to become inactive as soon as the mouse moves over them. They'll still work, so navigation around the Web is no problem. They just won't "look right." This can also be fun to install on that annoying cubicle neighbor's machine -- assuming he's bright enough to even notice that his browser is acting weird.

Speaking of making things not look right, here's a fun way to mangle traditional pixel-GIF/HTML layout schemes without messing up larger (and, presumably, more useful) images:

img {min-width: 10px !important; min-height: 10px !important;}

This time, we've declared that images shall be no smaller than 10x10 pixels. All those Siegel-inspired layout tricks will go kablooey. Heh heh heh.

If, on the other hand, you value compact visuals, you could try reversing the trick and keeping all image elements below a certain size:

img {max-width: 10px !important; max-height: 10px !important;}

Single-pixel GIFs will stay at a single pixel, so this won't have quite the same layout-destroying effects, but it will make all of the images on the page pretty darned small.

Tearing down the hierarchy

Enough with the meekness! Back to the anarchy!

Long-time revolutionary comrades will have realized that most of the weapons in our arsenal involve use of the property display, and most of them use the value none to do their dirty work. It just so happens that display is more versatile than an instrument of destruction. For example, find a page that uses no tables and then view it using this stylesheet:

* {display: inline;}

The CSS Anarchist's Cookbook
The CSS Anarchist's Cookbook

That's right, every piece of text, and every image, will form the world's longest run-on paragraph. Even William Faulkner at his most verbose can't match it. We've reduced all the block-level elements like paragraphs, and even elements like list items, into normal everyday text.

Why did I caution against using this on pages with tables? Because current browsers get very confused when directed to turn table elements into inline elements. The resulting carnage is something that can horrify even the most battle-hardened anarchist (but try it anyway, just for kicks). Because of this, we can introduce some table-related styles into the bomb and make it a little smarter:

* {display: inline;}
table {display: table !important; height: auto !important;}
tr {display: table-row !important; height: auto !important;}
th {display: table-header !important; height: auto !important;}
td {display: table-cell !important; height: auto !important;}

This will help the tables keep their structure, while still forcing the table's contents (along with everything else) to run together.

See Figure 3 for a demonstration.

As with most of our sneaky design bombs, this one has a flipside. Consider:

* {display: block !important; margin-left: 1em !important; padding-left: 0.5em;
border-left: 1px solid black !important; font-size: 1em !important;
background: white !important; color: black !Important;}
img {height: 1em !important;}
table {display: table !important; height: auto !important;}
tr {display: table-row !important; height: auto !important;}
th {display: table-header !important; height: auto !important;}
td {display: table-cell !important; height: auto !important;}

This time, we've gone for an "outline" view of the document's structure by setting all non-table elements to have a display of block. Every non-table element will be block-level, just like a div or a paragraph. Each block element will be indented one em-space with respect to its parent element and have a left border with half-em left padding, and the font size of text will be the same throughout the document. In fact, even images will be only one em tall. Only table elements will escape this rearrangement, thanks to their touchy nature. Of course, if you'd like to hit the tables as well, then you know what to remove.

Cascading Style Sheets: The Definitive GuideCascading Style Sheets: The Definitive Guide
By Eric A. Meyer
May 2000
1-56592-622-6, Order Number: 6226
467 pages, $34.95

A word of warning about the outline bomb: Even in the latest browsers, this weapon is dangerously unstable. Even though its effectiveness has been theoretically proven, attempts to use it in the real world risk significant damage to the user. You might even trigger a software crash -- the ultimate revolutionary attack! Just think, if browser vendors hadn't gone to the effort of deliberately building substandard rendering engines, we wouldn't have a prayer of crashing browsers. Perhaps we should make these brave men and women honorary comrades for their assistance to our cause.

An end to anarchy? Never!

The last time we met, I promised that I'd be collecting new recipes for the CSS Anarchist's Cookbook. As you can see, that was no idle threat. Nothing will stop me from bringing you the tools of revolution, the means to strike back at those who think they know best how your Web-browsing experience should appear. Even as you read this, the forces of visual anarchy are on the move, searching for new and more terrible ways to subvert the Web as we know it. Join us! If you find an insidious new weapon, share it. I'll spread the news in my next communiqué, either under your true name or a revolutionary pseudonym of your choice. Our struggle to free the browser from the tyranny of design will never die!

Copyright © 2009 O'Reilly Media, Inc.