Making your website look like a typewritten page, part 2: Headings, colour and interest
At the time of writing – and this will most likely change soon as I’m already getting bored of this “look” – this website is set using a single size, monospace typeface. This is an attempt to render it according to the rules set by a mechanical typewriter – one typeface, two colours, one line height etc., which poses a set of design problems. In this post, I’ll share how I went about solving them.

A Corona mechanical typewriter.
Headings and hierarchy in a non-hierarchical space
One of the luxuries of digital typesetting is the ease with which we can change the size of our text, which in turn allows us to indicate the importance of something – a title, for example – by simply making it bigger. Generally, the bigger something is, the higher its place in a document’s hierarchy.
We don’t even have to do anything with font size when we create a document in a browser or wordprocessor as they offer a set of defaults:

Default h1-h6 font sizes in Firefox on Macos.
This leaves us with four basic techniques to style headings:
- Weight
- Colour
- Proximity
- Caps
And we only really need two of these to indicate we’re using a heading. We cheated a little by allowing ourselves bold text, and you’ll note from our screenshot that as well as being bigger than other elements, headings are also heavier.
What browsers don’t do by default is use proximity to separate a heading from its preceding text. In printed typography, a heading will normally have more space above it than below, thereby placing it closer to the content it relates to, creating a relationship between the two. You’ll see it a lot on the web as well.
This is an example of the principle of proximity: putting things closer together – and further away from other things – creates a single, grouped entity.

When we move subheadings nearer to the following content we create a single entity – with a clear heading.
Changing margins – of headings and other elements, such as figures – is easy with CSS and helps establish purpose in the text. When we only have one font size, it’s worth exaggerating these spaces to drive home the point.
(Note: I did consider capitalising headings, but it’s just plain ugly, especially when a headings runs over more than one line.)
So far, so easy, but what we have lost by using one font size is a hierarchy of headings. Our h6
looks exactly the same as our h1
, even if they both look different from, say, a paragraph.
This is a trickier problem to solve, but we can try by turning to our text editors for help: a logical enough approach as we’re using a single, monospace font and size.
If you edit text for the web chances are you’ve used a syntax called Markdown to generate HTML. I’m drafting this post in Markdown. It allows us to create web documents more quickly – compare how we make an h1
in Markdown with HTML:
# An h1 in Markdown
Two characters in one place.
<h1>An h1 in HTML</h1>
Nine characters five of which are different across two places.

A script will convert this Markdown to HTML.
The #
character indicates a heading, and the number of #
s indicates its level. So ### Some text
equates to <h3>Some text</h3>
. We can use this notation to suggest a hierarchy of headings. I couldn’t tell you how clear it is to anyone who hasn’t used Markdown, but I’m guessing you probably have. If you haven’t, it’d be interesting to hear whether it works for you – get in touch.
Indents and ch units
Where space allows, I’ve indented heading characters so they sit in the document margin. This reinforces the distinction between headings and other elements, and provides a little visual interest. That’s why I’ve added other, more decorative marks to things like article datelines and pagination.
I more or less nicked the CSS for this from Andy’s site – you basically set a negative indent and offset it with the number of characters in your notation plus a space. So an h1
would use this CSS:
h1 {
text-indent: -2ch; // -2 characters
}
h1::before {
content: '# '; // 2 characters, a hash and a space
}
The interesting part of this is the ch
unit. Although it’s presumably short for “character”, it’s not actually a defined width that all font characters fill; it’s the width of the 0
character in a font:
The advance measure (width) of the glyph “0” of the element’s font.
As we’re using a monospace we want every letter space we create to be exactly the same. If we were using a proportional font, the 0
might be different from the #
, so this wouldn’t work. However, as monospace font characters are by definition always the same width, 1ch
does serve as the width of a single character, rather than just the width of the 0
. The test of this is whether negatively indented text ends up aligning with the rest of the text when glyphs are added using :before
.

Heading text aligns with paragraph text while the Markdown characters sit in the margin.
Margins, space and line-height
As a rule of thumb, monospace text requires more space than proportional, so I’ve set the document line-height
to 1.618 (ho ho ho).
Typewriters work on a principle of lines, so vertical spaces can only be one, two, three, four etc. lines. With a 1.618
line-height, that means vertical margins and padding have to be 1.618rem
, 3.236rem
, 4.854rem
, 6.472rem
etc. Margins can quickly get very large under this sizing regime, so you have to be disciplined about spacing.
The approach I took was to create a hierarchy of page elements:
- Whole page elements, consisting of the page
header
, itsmain
content (normally an article, but whatever sits within themain
element) and itsfooter
- The structural elements of an article: its
header
, main body and itsfooter
- Elements within the article that combine to form a whole; for example a
figure
consisting of an image and its caption - Single elements within an article – usually paragraphs and lists (but not list items)
You’ll note we’re using proximity again to suggest relationship between and within page elements. Having this hierarchy, we can set some rules around spacing between the elements:
- Whole page elements have a space of four lines (or
6.472rem
) between them - The structural elements of an article have a space of three lines (or
4.854rem
) between them - Combinational elements within an article are separated from surrounding content by two lines (or
3.236rem
) - All single article elements have a single line margin (or
1.618rem
, i.e. the same as ourline-height
)
Note: custom properties and calc
are your friends.
Also note: while this makes logical sense, I’m not sure it looks quite right, especially on mobile where elements look too far apart. Consequently, I ended up tweaking margins between elements to get a design that looked “right”.
When setting horizontal margins and padding, we have more freedom as a mechanical typewriter allows us to move the margin stops by hand to wherever we want along the margin stop rod. We could use ch
units, of course.
Colour
Mechanical typewriters often had dual-colour ribbons. By engaging the ribbon colour indicator lever you could choose whether to use an accent colour (normally red, in my experience). I was using the named CSS colour crimson
(using named colours seems in keeping with the whole mechanical ethos) to underline links, which again provides a little bit of visual interest. I ended up opting for deeppink
as it’s more discernible for anyone who has trouble seing red.
Colour is especially helpful for differentiating code examples. code
is of course normally styled as a monospace font, so won’t stand out as it does when surrounded by proportional text.
Where I broke the rules
There were a few areas where I could have continued to set this blog according to the rules of mechanical typewritten text, but chose not to.
Firstly, I decided to keep italics. I could have used Markdown notation again by enclosing text within _
markers, but I think this is too obscure and simply doesn’t stand enough out. Besides, the link between the form of italicised letters and their voice is a strong one: using underscores would require a lot more cognitive effort.
Secondly, I use a mid-grey to indicate when a link has a visited state. :visited
is one of those simple, useful CSS features that make browsing a site a lot easier: I wasn’t willing to lose it – or try some sort of marker alternative – in the name of an experiment.
Finally, I’ve kept all those nice characters that make reading easier, such as “”–—‘’
and …
. Again, it seems pointless losing these.
Why and was it worth it?
I enjoy exploring seemingly simple typographical rules. Imposing a set of restraints on what you can and can’t do when you’re setting text makes you think through the purpose of every margin, indent and weight choice.
Also, it looks quite distinctive – although I can’t shake the feeling that, like all “brutalist” web design, it’s a little bit kitsch, dishonest even. Sure, I could apply all these restrictions in the name of some sort of ersatz theoretical purity, but digital allows us to improve how readers experience text without making things look overly ornate, or by sacrificing performance on low spec devices etc.
And you could replace “distinctive” with “ugly”.
I do find it pleasant to read, though, but that’s entirely subjective – it’d be interesting to dig out any research on the readability of monospace text. I think it does impart the idea that the text is a draft, rather than complete. Appropriate for an informal blog, I think.
Anyway, if you’re reading this and it’s still set in a monospace typeface, what do you reckon? Drop me a line.