Experimenting With HTML Only Sites


I made six websites using only HTML

No Images


No JavaScript

Just good, ol' fashion tags (including some depreciated ones). The sites are:

I hope you enjoy them,



"HTML is all you need to make a website.

Show me your HTML only websites!"

-- whitep4nth3r (via twitter)

That tweet from whitep4nth3r got me thinking.

I'd seen MotherF---ingWebsite, but I never thought about what I could do with only HTML. The constraint got me thinking. I took a crack at it and came up with six sites that don't use any JavaScript, CSS, or Images.


The first thing that came to mind was making an ASCII art gallery.

The pages work by using `pre`` and `code`` tags around the ASCII strings. Nothing fancy. The fun part was writing the script to generate the strings themselves. I used this tutorial to build my converter with python's Pillow/PIL image library.

link: ascii-art.alanwsmith.com

Pixel Art

Working on the ASCII art pages got me thinking about pixel art which, in turn, got me thinking about using an HTML table to make an image. This is where I got to draw on my ancient HTML knowledge from the before times.

The `td`` table cell tag has attributes to set width, height, and background color. The attributes are deprecated. CSS has taken over those roles. But, they still work in most browsers.

Going back to Pillow/PIL, I built a script that pulled the pixel values from an image of René Magritte's The Son Of Man and turned it into a 100 pixel wide set of table cells with fixed size and the appropriate color.

link: pixel-art.alanwsmith.com

ASCII Animation

The ASCII art idea was still percolating and ended up forming into an idea of making an animation out of it. Since I already had the code to make ASCII from images a big part of the work was done.

I decided to use the 1878 images from The Horse In Motion by Eadweard Muybridge.

I again dug back into my memory of ancient knowledge for a way to animate the images. Specifically, I used meta refresh calls.

I used to use meta refresh to update PGA TOUR leaderboard data at work before we became one of the first sites to use XMLHttpRequest calls. I wasn't sure if the meta tags would still work. They do.

In some browsers, the refresh time has to be set at one second intervals. In others, sub-seconds (e.g. "0.3") work.

The home page of the site has a little delay before moving into the one second version. There's also a link to the faster version which seems to work best in chrome. The big negative of the approach is that the refresh takes control away from the user while it's happening. This can make it hard/impossible to click on links. Sometimes you have to close the browser to get the thing to stop.

It can also cause the pages to flash some. So heads up if you're sensitive to that type of thing.

link: html-animation.alanwsmith.com

Display Board

That animation idea stuck in my head too. I was wondering if there was a way to do something like that without jumping between pages with the redirect. That naturally led me to the `marquee`` tag, but with the idea of pixels from the ASCII art thrown in.

Those things combined to see if I could setup a table where every cell had its own marquee tag in it.

A quick test confirmed that at least on my version of chrome the individual cells would stay in sync if the deprecated `face` tag was applied to make the font monospace.

You generally need seven pixels of height to create a bitmap font (which is effectively what I needed to do). So, I hand coded an list of lists in a python and output them with spacers to generate a "Hello World" display.

The width of each cell was set with one of those deprecated attributes to provide the consistency.

This one feels more like a prototype. I'm thinking of other stuff you could do with it if you narrowed with width and used █ characters.

link: html-display-board.alanwsmith.com


Moving out of the realm of art, I wanted to create something interactive. A maze seemed like it might work. The idea was to provide the movement by generating a page for each possible position, then cross linking them to represent the possible moves.

Before getting to that the trick of generating the maze needed to be solved. I could have come up with one by hand, but the chance to dig into algorithms was way more appealing. There are several different maze generation algorithms.

After reading through the wiki page, I decided to go with the iterative implementation of randomized depth-first search which looks like this:

- Choose the initial cell, mark it
as visited and push it to the stack

- While the stack is not empty:

    - Pop a cell from the stack and
    make it a current cell

    - If the current cell has any
    neighbours which have not been

        - Push the current cell
        to the stack

        - Choose one of the unvisited

        - Remove the wall between the
        current cell and the chosen cell

        - Mark the chosen cell as visited
        and push it to the stack

The initial algorithm is pretty straight-forward. Unfortunately, it didn't work for me. It builds a maze that identifies only the cells and then adds metadata to them saying which sides have walls.

My plan was to implement the maze in an HTML `table`` without CSS which means I couldn't use `border-left`, `border-right`, etc...

The solution was to expand out so that each wall got its own table cell in addition to the spaces in the maze the player moves through. I built this with a generator script that makes an initial JSON and a second one to produce the output HTML.

Those scripts generate every possible position in the maze and provide navigation links between them.

(If you're crafty, you can hack the URL to jump to the end without having to go through the maze.)

link: maze-html.alanwsmith.com

HTML Random Pattern

The final piece built off the preceding five.

It's a random pattern generator. The page is a collection of iframes coded to a specific width and height. The content of each iframe is one of a selection of pages that have a background color and a meta data refresh timer. The colors and refresh rates are randomized so each frame shifts to different colors at different times.

The order is pseudo random based off the original generation of the files. However, the page is static so it renders the same pattern ever time.

link: HTML Random Pattern

~ Fin ~

This was a really fun set of exercises.

A natural first reaction to being given a wild constraint like this is that it's ridiculous and dismiss it. I try to practice letting that feeling hit, then letting it pass. Litany Against Fear style

Once it does, I move play with the idea. I don't take it seriously, I don't worry about failing.

As far as I'm concerned, you can't fail at playing. That concept just doesn't make sense. So, I get to mess around and see what happens.

Sometimes cool things show up, but mostly (and most importantly) it's just fun.