HTML-Quine and Source-Stylesheet

There are quite a few tricks with CSS you might not know.

For instance, you are able to add content via CSS, preceding or following existing elements.

el:before{ content:"lorem"; }
el:after { content:"ipsum"; }

Now, couldn’t we just visualize the source of the document? E.g.:

p:before{ content:"<p>"; }
p:after { content:"</p>"; }

Or, if we wanted it nicely wrapped:

p:after {

If you do that with all the 100-150 elements of HTML you’ll have quite a nice outline, but the attributes are still missing.

This is where the CSS-attr()-function comes in handy, which prints the contents of attributes.

A typical use would be to make otherwise “invisible” attributes that hold content visible and thus accessible,


<blockquote cite="">
    You have reached this web page by
    typing "", "",
    or "" into your web browser.


   content:"Source: "attr(cite);


Example of a blockquote with it's cite printed

With this in mind we can visualize the attributes as well, thus enhancing our outline:

  content:'<p class="'attr(class)'">';

Of course, this would print an empty class for any element that hasn’t a class defined, and we’ll have to cater for this eventuality. Since there is nothing like if...else in CSS, we have to do with something like this:

  content:'<p class="'attr(class)'">';

which will print a <p> before any paragraph, and overwrite that with <p class=”…”> for any paragraph carrying a class, using an attribute selector.

Since there are a lot more attributes than class, we’ll need to include more attributes, like this

  content:'<p class="'attr(class)'">';
  content:'<p id="'attr(id)'">';
  content:'<p class="'attr(class)'" id="'attr(id)'">';

I think you get the general idea.

Now, if we’ll go and try to do this for all the attributes, we’ll likely run into issues with our file size. Assuming we don’t care about the attribute order1 (which we can’t in CSS, anyway) we’ll have n of m attribute possibilities, where n is the number of attributes a specific element can actually have and m the number of attributes we care about.

Since every element can have (or lack) n attributes we’ll get 2n combinations2 for every element, plus 1 that’s closing it… in short, we’ll get a lot of lines to write3.

So, for practical reasons (and because there are better things to do) we’ll just include the most important elements in our style sheet, which I deem to be class, id, style, title, lang and action, method, type, value, scope, alt for specific elements which are mandatory anyway.

Having done all that, you can see a live example of this style sheet applied to an actual HTML document or go ahead and get a zipped copy.

In case you haven’t noticed: I think it’s rather astonishing that this is even effective on elements otherwise invisible, e.g. <html> <head>.

Note that, even though this technique works surprisingly well, there are problems with self-closing elements inside the body (e.g. <br /> <img />) and the <html> tag itself. Here is why:

Note. This specification does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML).CSS 2.1 Specification,

But there is even more!

World premier!

If you are a programmer, you’ve probably heard of Quines which is basically a program which prints itself. With this technique, we’re in a position to write our own HTML-Quine, which does exactly that!

As far as I know, this hasn’t been done before, thus making this a worldwide novelty4 !

You can download or take it for a spin.

  1. meaning we don not differentiate between <p class=”…” id=”…”> und <p id=”…” class=”…”> []
  2. someone’s done the maths… []
  3. x*4*(2n+1), to be precise, where x is the number of elements we’ll include []
  4. for all I know and want to know []

Possibly related:

2 comments to “HTML-Quine and Source-Stylesheet”

  1. # Jonas Höglund on 2010-03-03 at 11:18

    Nice job! I did a CSSish quine, but kind of cheated, I simply set the style element to display: block. (And then do some :before/:after trickery, just like you do, but much simpler.

  2. # Johann on 2010-03-08 at 00:01

    Hey Jonas,
    I really like your solution, it really is much simpler. Wouldn’t have thought of that.