JavaScript in CSS files

Works in Explorer and Opera.

Recently it has been discovered that it's possible to add JavaScript to CSS files. This page details why you shouldn't use this technique.

Unfortunately the original page of the discoverer is offline. I found a summary at milov.nl, but it doesn't contain all the code.

The trick

First of all let's review the trick itself. If you saw one or two alerts when entering this page the trick works in your browser. If you didn't see any alerts, it doesn't work. As far as I know it only works in Explorer (Windows and Mac) and Opera.

This DIV has the following styles
#test {
	border: 1px solid #000000;
	padding: 10px;
	background-image: url('javascript:alert(message);')
}

When parsing the CSS file, Explorer and Opera encounter the JavaScript and execute it. They execute it only once, though, so if you'd repeat the background-image: etc for another class or id, you still see one alert only.

As a second test I defined these styles for an element with id="test2":

#test2 {
	border: 1px solid #cc0000;
	padding: 10px;
	background-image: url('javascript:alert(message2);')
}

However, I did not put this element in my HTML. Explorer on Windows and Opera don't show the second alert, but Explorer on Mac does. Apparently Explorer Mac also parses styles for absent elements. Good to know.

Restrictions

So far so good, this simple example works. However, when I tried to actually do something useful I ran into the restrictions of this technique.

Quotes

First of all there is some trouble with quotes. My very first test was:

background-image: url('javascript:alert('It works');')

Explorer Windows showed the alert fine, but Explorer Mac complained about the quotes. Opera did nothing. When I tried

background-image: url('javascript:alert(\'It works\');')

Explorer Mac and Opera showed the alert fine, but Explorer Windows complained about the quotes. I'm not sure who's right here, and avoided the problem by rewriting my test to use a variable message to hold the alert text. In a real script this would be a serious problem, though.

Generating a background image

Then I tried to write a simple script that generates a random background image for an element. This was the only actual, practical use of the technique I could think of. I tried

background-image: url(javascript: document.write('pix/test'+(parseInt(Math.random()*5)+1)+'.gif'));

and Explorer Windows wrote the image name to the document, incidentally destroying this page. It didn't work without the document.write, either. At the moment I don't think generating a random background image is at all possible.

Useless

JavaScript belongs in a JavaScript file, not in a CSS file. I'd only insert JavaScript in a CSS file if that course of action would have clear advantages.

Since this technique doesn't work in all browsers and cannot be used to actually insert dynamic content into a CSS file, it has no redeeming features whatsoever. Therefore I don't see any reason to use it.

But how about using it to make sure a certain script is only executed in Explorer and Opera? I advise against it, for three reasons:

  1. You rarely need a script that works in Explorer and Opera, but no other browsers.
  2. Any attempt to make sure a certain script only works in one browser is worse than useless. Secretly this technique would serve as a browser detect, and anyone who uses a browser detects will get what he deserves.
  3. Besides, assuming this technique will remain restricted to these two browsers is very dangerous and would secretly be a CSS hack. Sure, at the moment it doesn't work in any other browser. But suppose we find a practical use for the technique? Then other browsers might start supporting it, too, and our scripts, written to be executed only in Explorer, would misfire disastrously.

If this technique is useful, we cannot count on it remaining restricted. On the other hand, if it is useless we don't need it anyway.