Plain HTML with a few bureaucratic gestures

The modern web ain't so bad

My preference, since the late '90s, has been to write webpages as plain HTML in a text editor. This isn't because I'm a giant HTML fan or expert. I don't do anything fancy with it, just text with some links and images, which is part of why I prefer this approach. HTML is an acceptable markup language for hypertext documents. For a long time, this worked fine. And today it still works, but only with some tweaks, which is what this short article is about.

The classic hypertext philosophy says that HTML should define the semantic document structure (mark the headings, links, paragraphs, etc.), and leave it up to the browser to choose a suitable layout for its context. That matches how I'd like to use it. Alas, the browser flagrantly fails to do a decent default job of layout. Therefore even many people who might otherwise be inclined to write simple HTML reach immediately for a framework that provides better results out of the box, whether it's a content management system like Wordpress, or a web framework like Bootstrap — perhaps fearing (as I did) that the only alternative is to learn many arcane corners of the modern HTML/CSS/JS web stack in order to DIY it. Fortunately only a handful of arcane corners are really needed, and they can be handled by making a few boilerplate bureaucratic gestures to the browser.

What I really want to write

A skeleton for a simple 1990s webpage might have looked like this:

<html>
  <head>
    <title>Mark's Homepage</title>
  </head>
  <body>
    <h1>Mark's Homepage</h1>
    <p>Welcome to Mark's home on the WWW!
  </body>
</html>

Pretty simple! But looks pretty bad!

Four one-line additions to fix things up

The required changes to the above skeleton involve overriding a handful of unfortunate browser defaults (some there for historical reasons).

1. Set a mobile viewport

The simple skeleton above will render terribly on a mobile browser. Mobile devices typically have much narrower screens than desktop browser windows, requiring suitably narrower content reflowing. You might think this would happen automatically. It even seems like a perfect use-case for the semantic HTML idea, where a device with different properties from a traditional desktop browser can choose to reflow the page in a way that suits its display. Alas, that isn't what happens. But if you put this incantation into your document's <head> section, you'll get the expected behavior:

<meta name=viewport content="width=device-width, initial-scale=1">

The reason: Unfortunately, when mobile browsers were first being introduced, there were already a large number of websites out on the internet that assumed a reasonably wide browser window, of the kind you'd find on a desktop browser. Webmasters used (or abused) HTML features such as tables and frames to produce layouts that included aspects such as left navigation sidebars. If not rendered with a certain minimum width (nobody tested on desktop browsers resized to be ultra-skinny), such pages would be unusable, since the only thing visible would be the navigation sidebar. To accommodate such layouts, mobile browsers render the document to a wider virtual screen, which is then either scaled down to the device's actual size (producing unreadably small text), or displayed zoomed in, requiring horizontal scrolling to read (which makes paragraphs of text effectively unreadable as well).

The above viewport statement tells the mobile browser to render at the actual device width (not a larger virtual width), producing more sensible results.

2. Set the charset to UTF-8

Most text-editing software these days encodes non-ASCII characters in UTF-8. But there's a good chance that, at least in some circumstances, your HTML might default to being interpreted in an old encoding like windows-1252 or ISO 8859-1 for backwards compatibility reasons, giving you mojibake.

The most reliable way to fix this is to set an explicit UTF-8 character set in the document's <head> section:

<meta charset=utf-8>

There are other places this can be fixed, but they're less reliable than putting it in the document. One alternative is to configure your webserver to announce in the HTTP header that its documents are in UTF-8 (in Apache this can be done by adding the line AddCharset UTF-8 .html to your .htaccess). But that won't fix it everywhere; for example, if you preview a page on your local computer by opening the file with a file:// URL, it may default to an old charset again (on Firefox on Mac, it defaults to windows-1252, even in HTML5 standards mode). So I prefer to set the charset in the document.

3. Set HTML5 standards mode

Most browsers render HTML in something called quirks mode by default, which is a hodge-podge of old de-facto standards and expectations intended to avoid breaking existing pages. For simple pages this isn't really a problem, so setting this is optional. But you might as well put your page into HTML5 standards mode anyway, in order to avoid being befuddled down the line by something not working the way documentation says it should. To do so, put this as the very first line of your HTML file (before the opening <html>):

<!DOCTYPE html>

One caveat is that HTML5 standards mode deprecates a number of presentational HTML elements, such as <font> and <center>, so don't enable it if you use those. The way to set fonts, alignment, etc. in HTML5 is through CSS, not HTML tags.

4. Set a maximum content width

Much as the default rendering is hard to read on narrow mobile screens, it's also hard to read on wide desktop screens. Text will be flowed by default from edge to edge of even very wide browser windows, producing unreadably long lines. Fixing this requires a small bit of CSS. There are a variety of things you can do here, but one simple fix is to put the following in your <head> section:

<style type=text/css>body { max-width: 800px; margin: auto; }</style>

This sets the page body's maximum width to 800 pixels, so it will use the full browser's width for windows that are 800px or narrower, but will leave margins if the browser window is greater than 800px. Setting the margins to auto makes them symmetrical, so the column of text will be centered. You can vary the width and margins here, as well as do various other things with only a slightly larger amount of CSS (I prefer a more left-aligned text block personally), but this is a readable starting point that's easy to get to.

In summary

By adding just four lines of browser bureaucracy to a 1990s HTML skeleton, it's still possible to write basic HTML that renders pretty well on the modern web:

<!DOCTYPE html>
<html>
  <head>
    <meta name=viewport content="width=device-width, initial-scale=1">
    <meta charset=utf-8>
    <style type=text/css>body { max-width: 800px; margin: auto; }</style>
    <title>Mark's Internet Presence</title>
  </head>
  <body>
    <h1>Mark's Internet Presence</h1>
    <p>At Mark's Internet Presence, we leverage HTML5 technologies to...
  </body>
</html>

Update!

The nice folks at lobste.rs pointed out that the <html>, <head>, and <body> tags are actually optional, even in strictly validated, standards-compliant HTML5. If omitted, the browser will infer which part is the head and which is the body (and that the whole thing is HTML). This lets us atone for the four added lines of boilerplate by axing six of the existing lines, producing a nicely compact result, essentially the minimal document that renders well on modern browsers:

<!DOCTYPE html>
<meta name=viewport content="width=device-width, initial-scale=1">
<meta charset=utf-8>
<style type=text/css>body { max-width: 800px; margin: auto; }</style>
<title>Mark's Internet Presence</title>

<h1>Mark's Internet Presence</h1>
<p>At Mark's Internet Presence, we leverage HTML5 technologies to...