Fork me on GitHub
Oatcake banner image

Oatcake: Plain Web Typography

A drop-in CSS stylesheet that makes pages attractive and readable. Looks good without drawing attention to the design. Works great on both mobile and desktop.

This is the demo page for Oatcake, a universal typography stylesheet. Possibly the world's most deadpan stylesheet, Oatcake aims to look good without being distracting or drawing too much attention to itself. Plain but pretty.

Usage

To style your own page with Oatcake just add this link to your HTML file's <head>:

<link rel="stylesheet" href="https://www.seanh.cc/oatcake/oatcake.min.css">
Complete example HTML

Here's a complete example HTML page that you can copy and paste to get started with Oatcake:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Page title</title>
    <link rel="stylesheet" href="https://www.seanh.cc/oatcake/oatcake.min.css">
  </head>
  <body style="max-width:50em; margin:0 auto; padding:0 .5em;">
    <h1>Page Title</h1>
    <p>Page content goes here…</p>
  </body>
</html>

The rest of this tremendously long page will demonstrate Oatcake's features, show you how to use them, and explain some of the design choices. You might even learn something about HTML along the way!

Contents

Tip: how to generate a table of contents

The table of contents is generated by Tocbot. If you hover over the headings on this page you'll see that they have clickable #anchor links, those are generated by AnchorJS.

Fonts

Many themes use idiosyncratic fonts that distract from reading and writing (constantly noticing and fiddling with your font choices instead of actually writing). Following its philosophy of looking good without drawing attention to its design choices, Oatcake uses a system font stack based on the system-ui font-family: it chooses the default interface font from the user's OS.

This is fast (no fonts to download), readable (modern operating systems ship high-quality fonts adapted to today's screens), and feels native to the user's system (nothing too distinctive).

Similarly, code blocks have a font stack based on the ui-monospace font-family which selects the operating system's default monospaced font.

Customising the fonts

You can customise the fonts by setting some CSS variables in your own custom stylesheet that follows oatcake.min.css:

<style>
  :root {
    --oatcake-font-family: 'ui-rounded, source-sans-pro, sans-serif';
    --oatcake-monospaced-font-family: '"Nimbus Mono PS", "Courier New", monospace';
  }
</style>

Or to change the fonts only within certain elements set the variables only on those elements, for example:

<style>
  #myElement {
    --oatcake-font-family: 'ui-rounded, source-sans-pro, sans-serif';
    --oatcake-monospaced-font-family: '"Nimbus Mono PS", "Courier New", monospace';
  }
</style>

For example click this button to change this page to a handwritten font stack:

Here's the full list of font variables you can change:

--oatcake-font-family
The font-family for the main <body> text.
--oatcake-font-size
The font-size for the main <body> text.
--oatcake-line-height
The line-height for the main <body> text.
--oatcake-small-font-size
The font-size for small text: <small> elements, the CSS class small, subscripts (<sub>) and superscripts (<sup>), and badges.
--oatcake-monospaced-font-family
The font-family for monospaced text.

Colours

Like its fonts, Oatcake's colours are also chosen to be readable and not to be noticed: black text on a white background, and the browser's default purple and underline for links. Code and preformatted text blocks have a typical light-grey background.

Customising the colours

As with the fonts, you can customise Oatcake's colours by setting some CSS variables in your own custom stylesheet that follows oatcake.min.css:

<style>
  :root {
    --oatcake-background-color: black;
    --oatcake-color: white;
  }
</style>

Or to change the colours only within certain elements set the variables only on those elements, for example:

<style>
  #myElement {
    --oatcake-background-color: black;
    --oatcake-color: white;
  }
</style>

Here's the full list of colour variables you can change:

--oatcake-background-color
The background-color of the page <body>.
--oatcake-color
The foreground color of the page <body> text.
--oatcake-secondary-color
The foreground color of secondary text and figure captions.
--oatcake-code-background-color
The background-color of inline <code> and <samp> elements.
--oatcake-block-background-color
The background-color of preformatted text blocks, code blocks, disclosure widgets and note boxes.
--oatcake-border-color
The border-color of block quotes, preformatted text blocks, code blocks, disclosure widgets, note boxes, images, videos and horizontal rules.
--oatcake-highlight-background-color
The background-color of highlighted text (<mark> elements).
--oatcake-kbd-background-color
The background-color of <kbd> elements.
--oatcake-kbd-color
The foreground color of <kbd> elements.
--oatcake-kbd-border-color
The border-color of <kbd> elements.
--oatcake-kbd-border-bottom-color
The border-bottom-color of <kbd> elements.
--oatcake-badge-background-color
The background-color of badges.
--oatcake-badge-color
The foreground color of badges.
--oatcake-badge-focus-border-color
The focus border colour of badges.

Vertical rhythm

Oatcake sets a comfortable base font-size and line-height and aligns all the other sizes, margins, paddings and borders with that vertical rhythm, like writing on a sheet of lined paper. This just makes the page feel nicer, more harmonious and pleasant to read. It's surprisingly difficult to get this comprehensively right, without some HTML element or combination of elements throwing off the rhythm.

Inline elements

All the usual inline elements work as you'd expect, for example: links, code() and sample output, emphasis, bold, strike-throughs, underlines, highlights, (even mid-word highlights: unfriggingbelievable), small text, subscriptssub and superscripts.sup

Tip: inline HTML elements you can use

Here's a pocket guide to some of the more useful inline elements you can use with Oatcake:

Combining inline elements

All sorts of combinations of inline elements also work. These break in many themes. After all, who would take the time to test them all? ;) Here's some examples:

Tip: quotes, ellipses and dashes

As well as its inline elements HTML also provides a few handy special characters for doing different types of quotes, dots and dashes:

Headings

Here's what all six levels of HTML headings <h1>–<h6> look like with Oatcake:

Page title (level 1 heading)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

Level 2 heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

Level 3 heading

Suspendisse vitae bibendum libero. In in lorem lacus. Proin pharetra neque venenatis, fringilla justo id, elementum magna. Maecenas vestibulum tortor urna, vel pharetra nisi commodo vel.

Level 4 heading

Suspendisse dignissim tempor ultricies. Phasellus in sollicitudin felis, eget fringilla quam. Vestibulum suscipit arcu dapibus placerat cursus. Suspendisse dignissim orci in nibh convallis, sit amet tempus dui tincidunt.

Level 5 heading

Suspendisse dignissim tempor ultricies. Phasellus in sollicitudin felis, eget fringilla quam. Vestibulum suscipit arcu dapibus placerat cursus.

Level 6 heading

Suspendisse dignissim tempor ultricies.

Oatcake's <h1>'s and <h2>'s are the same size (other than a bit more vertical space above an <h1>). The intention is that documents will start with a single <h1> whose position at the top of the document makes it clear that it's the top-level title, and then <h2>'s will be used for any mid-document headings. This prevents <h1>'s from having to be too large.

If you need sub-headings and sub-sub-headings use <h3>'s and <h4>'s.

You can also use <h5>'s and <h6>'s but they look the same as <h4>'s.

Design notes: headings

Headings are one of the hardest things to get right and one of the parts of Oatcake that I'm most happy with. HTML's six levels of headings are more than most documents need. Themes often resort to desperate measures to try to make all six levels visually distinct: distractions like overlarge font sizes, excessively heavy weights, ALL CAPS, underlines, centered text, too many font faces, too much indentation, etc. Most themes make <h1>'s too big for my taste (for the types of documents and titles that I tend to write anyway), meanwhile subheadings often come in smaller fonts than the main body text.

Oatcake's opinion is that most pages shouldn't use more than three levels of headings, preferably two. More levels are confusing and make it difficult for readers to orient themselves within the document.

So Oatcake deliberately restrains itself to just three visually distinct levels of headings, using the smallest necessary increments in font size and space above and below to distinguish the three levels of headings from each other. Sticking to just three visually distinct levels enables them to be distinct enough from each other without resorting to desperate measures.


A common mistake is to vertically align headings closer to the paragraph above than to the one below, or evenly mid-way between them. Oatcake gives headings a little more vertical space above than below so they're visually related more with the text below (that belongs to the heading) than to the unrelated text above.

Tip: hierarchical headings

If you really need several levels of headings I recommend making the structure explicit by hierarchically numbering the headings as the HTML standard itself does (you have to do this yourself, Oatcake won't do it for you):

Document title (first-level heading)

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1. Second-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1.1 Third-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1.1.1 Fourth-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1.1.1.1 Fifth-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1.1.1.2 Another fifth-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1.1.2 Another fourth-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

1.2 Another third-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

2. Another second-level heading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer malesuada, justo tincidunt mattis gravida, velit orci facilisis nibh, at hendrerit risus sem eu arcu.

Stacked headings

Sometimes one heading directly follows another heading, without any other text between them. Themes often mess this up by allowing the vertical space between stacked headings to look weird: large unnecessary gaps between the headings. Oatcake styles headings that immediately follow other headings with less vertical space than they would have otherwise:

First-level heading

Second-level heading

Third-level heading

Fourth-level heading

Fifth-level heading
Sixth-level heading

Inline elements in headings

A lot of themes break or look weird if you try to use emphasis, code, etc in a heading. Oatcake makes sure that common inline elements work in headings:

A heading with italics in it

A heading with code() in it

A heading with sample output in it

A heading with a kbd in it

A heading with underlined text in it

A heading with highlighted text in it

A heading with deleted text in it

A heading with a link in it

A heading with code link in it

A heading with mid-word emphasis in it

an_all_code_heading()

code() at the start of a heading

A heading withsuperscript andsubscript and small text in it

Headings that wrap onto multiple lines

Sometimes a heading runs onto multiple lines, especially on small screens. Many themes fail to account for this and the multiple lines of a heading either have too much space between them or too little, often actually overlapping. With Oatcake multi-line headings wrap well, this is a multi-line <h2> heading:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore

This is a multi-line <h3> heading:

Lorem ipsum dolgor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam

This is a multi-line <h4> heading:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco

Multi-line headings can even contain inline elements. This is where things go wrong in many themes:

This is a long multi-line <h2> heading containing emphasis, <code tags>, some sample output, a couple of <kbd>'s: Ctrl + c, underlined text, highlighted text, struck-through text, a link, a code link and evensuperscript andsubscript and small text in it

This is a long multi-line <h3> heading containing emphasis, <code tags>, some sample output, a couple of <kbd>'s: Ctrl + c, underlined text, highlighted text, struck-through text, a link, a code link and evensuperscript andsubscript and small text in it

This is a long multi-line <h4> heading containing emphasis, <code tags>, some sample output, a couple of <kbd>'s: Ctrl + c, underlined text, highlighted text, struck-through text, a link, a code link and evensuperscript andsubscript and small text in it

Lists

Here's what a simple unordered list (<ul>) looks like:

And an ordered list (<ol>):

  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis

Some or all of the items in a list can wrap over multiple lines and it'll work nicely:

  1. Vivamus sit amet elit bibendum.
  2. Morbi tempor sit amet mi nec auctor. Nulla metus purus, pulvinar sed eros non, ornare hendrerit lacus. Nullam rhoncus pretium turpis iaculis sollicitudin. Mauris ligula velit, ullamcorper a luctus sed, gravida vitae leo.
  3. Praesent aliquet erat eu felis.
  4. Duis finibus commodo velit, ac aliquam nibh interdum vitae. Sed luctus vel dolor vel fringilla. Cras bibendum, turpis nec vestibulum vestibulum, augue sem ultricies urna, eu condimentum libero sapien eget nisi.
Tip: tricks with HTML ordered lists

Did you know that you can reverse the order of the numbers in a numbered list by adding a reversed attribute to an <ol>? (<ol reversed>)

  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis

Or you can change the list starting number by adding a start="n" attribute:

  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis

reversed and start can be used together on the same list:

  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis

You can change the type of list markers using the type attribute: type="1" for numbers (the default), type="a" for lower-case letters, type="A" for upper-case letters, type="i" for lower-case roman numerals, or type="I" for upper-case roman numerals:

  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis
  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis
  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis
  1. Vivamus sit amet elit bibendum
  2. Aliquam ornare sapien ut nisl tristique
  3. Praesent aliquet erat eu felis

Nested lists

Themes often mess up nested lists: erasing the nested structure by collapsing the indentation, putting incorrect vertical space before or after a nested list, or otherwise making it look bad. Oatcake doesn't mess it up and allows indentation to show the nested structure:

Paragraph list items

If you leave blank lines between a list's items Markdown renders them as <li><p>'s rather than just <li>'s, which results in the list being rendered with some vertical space between items. Here's what a list of <li><p>'s looks like with Oatcake:

Nested lists also work inside paragraph lists (a common source of bugs in other themes). The nested list can itself be a paragraph list, or not:

Other block elements inside lists

Block elements like block quotes, code blocks, etc inside lists are another common source of breakage that works fine with Oatcake:

  1. A list item with a block quote:

    This is a block quote inside a list item.

  2. A list item with a code block:

    <code goes here>

    And an image:

    A bowl of oats
  3. A list item with a definition list in it:

    Term
    Description
    Term
    Description
  4. A normal list item to end the list.

Definition lists

Here's a definition list (<dl>) with Oatcake:

Oatcake
Thin flat unleavened cake of baked oatmeal.
Oatmeal
Porridge made of rolled oats.

Definition lists can be lists of …terms and definitions, metadata topics and values, questions and answers, or any other groups of name-value data.

Within a <dl> you use pairs of <dt>'s for the names ("terms") and <dd>'s for the values ("descriptions" or "definitions"). You can have multiple <dt>'s in a row if an item has more than one name and/or multiple <dd>'s in a row if an item has more than one value. Here's a couple of examples from the HTML standard, this:

<dl>
 <dt> Authors
 <dd> John
 <dd> Luke
 <dt> Editor
 <dd> Frank
</dl>

…renders like this:

Authors
John
Luke
Editor
Frank

Here's an example of multiple terms with a single definition:

<dl>
 <dt lang="en-US"><dfn>color</dfn></dt>
 <dt lang="en-GB"><dfn>colour</dfn></dt>
 <dd>A sensation which (in humans) derives from the ability of
 the fine structure of the eye to distinguish three differently
 filtered analyses of a view.</dd>
</dl>

Note the use of <dfn> to mark the word(s) being defined. <dfn> is purely semantic in Oatcake, it has no visible effect. Anyway, the whole example renders like this:

color
colour
A sensation which (in humans) derives from the ability of the fine structure of the eye to distinguish three differently filtered analyses of a view.

The contents of a <dd> can be wrapped in a <p> and a <dd> can contain multiple <p>'s if it's a multi-paragraph description. Oatcake handles <dd>'s containing either a single or multiple <p>'s just fine:

Pancake

A flat cake of thin batter fried on both sides on a griddle.

Pancake turtle

Voracious aquatic turtle with a flat flexible shell covered by a leathery skin; can inflict painful bites.

Synonym: soft-shelled turtle.

Tortoise
Tortoises

Usually herbivorous land turtles having clawed elephant-like limbs.

Etymology: Old English tortuce, from Old French tortis crooked, from Latin tortus twisted, crooked, contorted, past participle of torquere, tortum, to wind.

Block quotes

Here's what a <blockquote>, looks like with Oatcake:

Ut fermentum turpis quis ligula sagittis, a fringilla orci ultrices. Nam fringilla erat ac bibendum tristique. Morbi nec maximus augue. Donec in justo semper, convallis ante et, laoreet nibh.

Single-line block quotes also work:

Ut fermentum turpis quis ligula sagittis.

You can optionally wrap the contents of a <blockquote> in a <p>, it looks the same:

Ut fermentum turpis quis ligula sagittis, a fringilla orci ultrices. Nam fringilla erat ac bibendum tristique. Morbi nec maximus augue.

Design notes: block quotes

Many themes style <blockquote>'s in italics but this is problematic when the quoted text itself contains italics. Another common choice is to use a different font for block quotes, but that can be distracting.

Oatcake uses indentation and a left border. This is a common, recognisable style for block quotes, it makes block quotes distinct from any other element in Oatcake, it works well with nested block quotes (see below), and the left border makes it extra clear where the block quote starts and ends which is helpful with long block quotes (see below).

Tip: don't put quotation marks inside quotes or block quotes

You shouldn't put quotation marks around the text inside a block quote: putting the text in a <blockquote> is enough to show that it's a quotation, and the quotation marks aren't part of the quoted text.

You don't put quotation marks inside an inline <q> either, just wrap the text in a <q> and the browser will add the quotation marks for you.

Tip: how to mark up abbreviations and additions to quotes and block quotes

In English it's traditional to use square brackets if abbreviating or adding context to a block or inline quote, as in this example from the HTML standard (Jane has been added and something has been removed between liked and fish):

[Jane] then said she liked […] fish.

(If you want to be fancy you can use an ellipsis—&hellip;—instead of typing three dots).

Tip: highlights in quotes and block quotes

You can use <mark>'s inside quotes to draw attention to something that wasn't highlighted in the original quote. This is better than using italics or bold: it's both semantically correct and visually distinct from any italics or bold that might be in the original text:

Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC.
Tip: attributions and citations

Any attribution for the quotation is supposed to go before or after the <q> or <blockquote>, not inside it, because the attribution isn't part of the quoted text. For example the attribution could go in a following <p>, as in this example from the HTML standard:

<blockquote>
 <p>I contend that we are both atheists. I just believe in one
 fewer god than you do. When you understand why you dismiss
 all the other possible gods, you will understand why I
 dismiss yours.</p>
</blockquote>
<p>&mdash; Stephen Roberts</p>

Alternatively you can put a <blockquote> in a <figure> and the attribution in the <figure>'s <figcaption>, see the section on figures below for an example.

If the attribution contains the title of a work you can wrap it in a <cite> element, as in this example also from the HTML standard:

<p>His next piece was the aptly named <cite>Sonnet 130</cite>:</p>
<blockquote>
  <p>My mistress' eyes are nothing like the sun,<br>
  Coral is far more red, than her lips red,<br>
  …

<cite> elements aren't styled any differently from normal text, they're semantic markup only.

Only the title of the work should go inside the <cite>, not an entire phrase or sentence.

You shouldn't wrap an author's name in a <cite> because it's not the title of a work.

<cite> can be used whenever you're mentioning the title of a work and want to mark it up semantically, even if you're not quoting from the work.

You can add a cite attribute to a <blockquote> whose value is a URL for the quoted source:

<blockquote cite="https://quotes.example.org/s/sonnet130.html">

cite attributes aren't visible in the rendered HTML, they're meant to be read by scripts.

Nested block quotes

Sometimes a quoted section itself contains another quoted section. You can nest <blockquote>'s to an arbitrary depth and Oatcake will show the nested structure. A lot of themes get this wrong:

Fusce porta quam non varius viverra.

Vestibulum molestie nec massa et porta.

Donec imperdiet pretium luctus.

Etiam in malesuada lacus. Suspendisse eget velit lacinia, hendrerit lorem nec, pretium urna.

Morbi tempor luctus sodales. Vitae vehicula lorem gravida nec.

Nam commodo felis at tortor tempor, sit amet vestibulum lorem gravida. Suspendisse dignissim felis velit.

Other block elements inside block quotes

Block quotes can contain other block-level elements: multiple paragraphs, lists, code blocks, and even images. This is where the left border becomes particularly useful to make it clear where the block quote starts and ends:

Aliquam a faucibus dui. Donec a diam a odio dapibus varius. Nulla sagittis in lacus in dictum. Aliquam eu purus non risus facilisis dapibus.

Praesent porttitor cursus diam, at porta massa suscipit nec. Duis eu leo ut justo vestibulum pellentesque eget quis magna.

A bowl of oats
code block

Headings in block quotes

Sometimes a quoted section contains a heading. A lot of themes get this wrong, especially if the heading starts the block quote, often by introducing a weirdly large vertical space at the top of the block quote. Oatcake styles headings that begin block quotes without the preceding vertical space that the heading would normally have:

An <h1> at the start of a <blockquote>

Pellentesque sit amet leo nec tortor condimentum vestibulum quis ut sapien. Nulla a volutpat orci. Phasellus ac odio commodo, commodo erat ac, porta turpis.

An <h2> within a <blockquote>

Phasellus ac odio commodo, commodo erat ac, porta turpis.

An <h3> within a <blockquote>

Quisque auctor gravida massa sed tincidunt.

An <h4> within a <blockquote>

Quisque auctor gravida massa sed tincidunt. Phasellus mollis turpis ac nisi mollis, vel laoreet turpis malesuada.

An <h2> at the start of a <blockquote>

Phasellus mollis turpis ac.

An <h3> at the start of a <blockquote>

Phasellus mollis turpis ac.

An <h4> at the start of a <blockquote>

Quisque auctor gravida massa sed tincidunt.

Images

Images need a little more space above and below them than paragraphs do, otherwise they feel cramped. Oatcake gives images just enough space–not too much, not too little, and sticking to the vertical rhythm:

A bowl of oats
Embedded media and vertical rhythm

An image or video's height will upset the vertical rhythm unless it's an even multiple of Oatcake's line height of 24px. Correcting this isn't as simple as resizing the image or video file: on smaller displays browsers will shrink an image or video's width and height to fit it into the available screen width while maintaining its aspect ratio, so the element's height will no longer be a multiple of 24px. If you force the element's width and height with CSS then it'll overflow the screen width on smaller screens (since the browser can no longer shrink the element) and cause a horizontal scrollbar. If you force just the height and allow the width to change then the browser will horizontally squash the video (changing its aspect ratio) on smaller screens.

This page contains a snippet of JavaScript that you can copy that keeps the heights of images and videos snapped to the vertical rhythm while maintaining their original aspect ratio, regardless of the original file size and even as the browser resizes the window. Alternatively, just don't worry about it!

If you don't want an iframe to upset the vertical rhythm you can just use HTML or CSS to make its height a multiple of 24px. You can do this with an HTML attribute like height="168" or with some inline CSS: style="height:168px;". Unlike with images and videos, browsers don't shrink the heights of iframes to maintain the element's aspect ratio when shrinking their widths to fit them onto a smaller screen, so the JavaScript vertical rhythm fix isn't needed for iframes.

It looks the same if your <img>'s are wrapped in <p>'s, this:

<p><img src="media/oats.jpg"></p>

renders like this:

A bowl of oats

You can make an image's corners rounded by adding the CSS class rounded to the image - <img class="rounded" src="…" alt="…">:

A bowl of oats

Sometimes you want to add a border to an image, for example if the background colour of the image is the same as the background colour of your site and you want to show where the edges of the image are. You can add a border by adding the CSS class border to an image - <img class="border" src="…" alt="…">:

A bowl of oats

Videos

The same extra little bit of vertical space is also applied to video players created using <video>:

As with images, you can also make a video's corners rounded by adding the CSS class rounded to the video - <video class="rounded" src="…">:

Also as with images you can add a border to a video by adding the CSS class border to the video - <video class="border" src="…">, useful if the background colour of the video is similar to the background colour of your site and you want to show where the edges of the video are:

Audio

Oatcake also supports audio players with <audio>, again giving them a little more vertical space to breathe in, aligning them with the vertical rhythm and making sure that the player controls use all the horizontal width available for easier scrubbing:

iframes

Finally, the same extra vertical breathing room is also applied to embedded pages created with <iframe> (the background color here is part of the embedded page, not Oatcake's styling):

As with images and videos you can add the CSS class rounded to an iframe to give it rounded corners:

Or you can add the CSS class border to an iframe to give it a border, which might be useful if the embedded page has the same background colour as the parent page and you want to show where the edges of the embedded page are:

Sample output with <samp>

To represent sample output from a program wrap it in <samp> tags: Keyboard not found. Press F1 to continue.

Oatcake styles <samp> the same as <code>, making the difference only semantic. I didn't think two different styles for these would be likely to clearly say "this is code" whereas "this is output" to the reader, and too many different styles would only be distracting and make more design work and CSS.

How to make <samp> and <code> look different

If you want <samp>'s and <code>'s to look different you can easily get that by adding a little custom CSS on top of Oatcake. For example:

<style>
  samp {
    border: 1px dashed #999;
  }
</style>

Now <samp>sample output</samp> renders like this: sample output

User input with <kbd>

To represent user input from a keyboard or any other text entry device wrap it in <kbd> tags: help mycommand

There are three different ways to represent multiple keystrokes that form a single input:

  1. You can just write the whole sequence as a single <kbd>. This:

    <kbd>Ctrl + c</kbd>

    …will render like this: Ctrl + c

  2. Alternatively you can wrap each keystroke in its own separate <kbd>. This:

    <kbd>Ctrl</kbd> + <kbd>c</kbd>

    …will render like this: Ctrl + c

  3. Finally, you can use an outer <kbd> containing nested <kbd>'s for each of the individual keystrokes. Many themes try to show the nested structure visually but it doesn't work very well: there isn't enough space to make it look good. In Oatcake nested <kbd>'s are semantic only: they look the same as a single <kbd>. This:

    <kbd><kbd>Ctrl</kbd> + <kbd>c</kbd></kbd>

    …will render like this: Ctrl + c

All three ways are equally valid.

Tip: avoid long <kbd>'s

Oatcake's CSS prevents line-wrapping within a <kbd> (even if there are spaces) so don't make <kbd>'s too long or they'll overflow their container and break the layout.

Tip: use non-breaking spaces between <kbd>'s

Oatcake prevents browsers from wrapping a <kbd> over multiple lines even if the <kbd> contains multiple words separated by spaces, but if you're using a chain of separate <kbd>'s (as in Ctrl + c) you must use non-breaking spaces (&nbsp;) instead of normal spaces around the + if you want to prevent line breaks from being inserted in-between the <kbd>'s.

Wrapping the whole sequence of <kbd>'s in a <span style="white-space: nowrap;"> should also work and Oatcake provides a nowrap utility class for this so you can just do <span class="nowrap">.

You can also use either technique if you don't want a <code>, <samp>, <mark>, etc to be wrapped, for example: <code class="nowrap"> (Oatcake doesn't prevent wrapping within these elements by default because often you do want them to wrap, especially if they contain long strings that might otherwise overflow the container).

Preformatted text

Preformatted text blocks (created with the <pre> element) look like this in Oatcake:

Heaven and earth aren't humane.

To them the thousand things
are straw dogs.

Wise souls aren't humane.
To them the thousand families
are straw dogs.

Heaven and earth
act as a bellows:

Empty yet structured,
it moves, inexhaustibly giving.

Code blocks

Code blocks can be created with <pre><code> tags. This is what indenting a block of text by four spaces or one tab does in Markdown (or "fenced code blocks" with ``` in many versions of Markdown). Oatcake aims to do more with fewer visual styles, so code blocks look the same as preformatted text blocks but with a monospaced font:

#include <stdio.h>

int main()
{
    printf("Hello World!\n");
}

A common bug in themes is for long lines in code blocks to stretch out the width of the entire page which looks weird and breaks the layout on mobile screens. Oatcake fixes this by giving wide code blocks a horizontal scrollbar:

def test_validate_url_returns_an_http_url_unmodified():
    assert validate_url('https://github.com/jimsmith') == 'https://github.com/jimsmith'

Sample output blocks

Oatcake also supports <pre><samp> blocks. These have a different semantic meaning in HTML: they represent a block of computer output rather than input code. Again trying to avoid having too many different visual styles Oatcake styles <pre><samp> the same as <pre><code>, letting the difference be semantic only:

 _________________________________
/ You are taking yourself far too \
\ seriously.                      /
 ---------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Combining <pre>, <code>, <samp> and <kbd>

<code>, <samp> and <kbd> can be mixed together in a single <pre> block, with different semantic meanings. For example here the prompt output by the terminal (> ) is a <samp>, the code entered by the user (console.log(2.3 + 2.4)) is a <code> element, the Enter key clicked by the user to submit the code is a <kbd>, and finally the result output by the terminal (4.699999999999999) is another <samp>. <code> and <samp> look the same in Oatcake so the difference is mostly only semantic, except for the <kbd>.

> console.log(2.3 + 2.4) Enter
4.699999999999999
How to make <samp> and <code> look different in preformatted blocks

If you want <samp>'s and <code>'s to look different in a preformatted text block you can easily get that by adding a little custom CSS on top of Oatcake. For example:

<style>
  pre code {
    font-weight: bold;
  }
  pre samp {
    color: var(--oatcake-secondary-color);
  }
<style>

Now the previous example will render like this:

> console.log(2.3 + 2.4) Enter
4.699999999999999

Other inline elements in preformatted blocks

You can use links and other inline elements in preformatted, code and sample output blocks: bold, italics, underline, strikethrough, small text. Here's one with a bunch:

#include <stdio.h>

int main()
{
    /* Here's a code comment withsubscript and.superscript */
    /* Here's a code comment in small text. */
    /* Here's an inline quote in a code block. */
    /* Here's a link. */
    printf("Hello World!\n");
}

A useful application of inline elements in code blocks, from the HTML standard, is using <mark> to highlight part of the code, perhaps a part that is referred to from elsewhere in the text. For example here's a code block with a bug highlighted:

def whats_on_the_telly(penguin=[]):
    penguin.append("property of the zoo")
    return penguin

Horizontal rules

The <hr> element is used for "thematic breaks" like a change of scene or topic. Here's what <hr>'s look like with Oatcake:


Disclosure widgets: <details> and <summary>

We've already seen lots of these in this document—you can create a disclosure widget with <details> and <summary>. Oatcake deliberately gives disclosure widgets a similar style to preformatted text and other blocks, with the same background color, border and padding. This:

<details>
  <summary>This is the summary</summary>
  <p>And here are the details:</p>
  <ol>
    <li>Cash on hand: $500.00</li>
    <li>Current invoice: $75.30</li>
    <li>Due date: 5/6/19</li>
  </ol>
</details>

…renders like this:

This is the summary

And here are the details:

  1. Cash on hand: $500.00
  2. Current invoice: $75.30
  3. Due date: 5/6/19

Adding the open attribute to a <details> makes it already be open when the page loads:

This is the summary

And here are the details:

  1. Cash on hand: $500.00
  2. Current invoice: $75.30
  3. Due date: 5/6/19

You can nest disclosure widgets:

Outer widget

Details…

Inner widget

Details…

Headings in disclosure widgets

Oatcake makes sure that headings don't have too much vertical space before them when they're used to start the hidden contents of a disclosure widget:

A <details> starting with an <h1>

<h1> heading

Nam sodales magna nec leo blandit convallis. Vivamus interdum leo nec ligula laoreet elementum. Phasellus ut odio tortor. Nam semper tincidunt varius.

<h2> heading

Nullam quis arcu id erat suscipit tincidunt. Vestibulum viverra laoreet elit ac tempor.

<h3> heading

Sed sit amet velit mattis, ultricies nisi ut, lobortis lacus.

<h4> heading

Aliquam luctus elit a urna molestie, eget fermentum magna vehicula. Fusce sit amet orci et arcu fringilla pulvinar a ac nulla.

A <details> starting with an <h2>

<h2> heading

Here are the details…

A <details> starting with an <h3>

<h3> heading

Here are the details…

A <details> starting with an <h4>

<h4> heading

Here are the details…

Figures and figure captions

Oatcake supports figures and captions with <figure> and <figcaption>. For example this:

<figure>
  <img src="media/oats.jpg" alt="A bowl of oats" title="A bowl of oats">
  <figcaption>A bowl of oats</figcaption>
</figure>

…renders like this:

A bowl of oats
A bowl of oats

Captions can be used for additonal information about the figure content or its source, and to give a figure a number so it can be moved away from the primary content (e.g. to a dedicated figures section or appendix) and referred to from the primary content by its number.

Multi-line captions work fine, as do inline elements within captions:

A bowl of oats
Laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Creative ways to use figures

Figures aren't just for images. You can put anything in a figure. For example here’s a code figure:

# Public: Fetch the logger instance for this Jekyll process.
#
# Returns the LogAdapter instance.
def logger
  @logger ||= LogAdapter.new(Stevenson.new, (ENV["JEKYLL_LOG_LEVEL"] || :info).to_sym)
end
A method from the Jekyll source code

Here's an example from the HTML standard with a <blockquote> in a <figure> and the quote's attribution in the <figcaption>:

The truth may be puzzling. It may take some work to grapple with. It may be counterintuitive. It may contradict deeply held prejudices. It may not be consonant with what we desperately want to be true. But our preferences do not determine what's true. We have a method, and that method helps us to reach not absolute truth, only asymptotic approaches to the truth — never there, just closer and closer, always finding vast new oceans of undiscovered possibilities. Cleverly designed experiments are the key.

Carl Sagan, in "Wonder and Skepticism"

Preventing really long words from overflowing

Long unbroken words or other strings (such as URLs) that are too long to fit on one line (even with a whole line to themselves) can overflow their containers, especially on mobile, causing unwanted horizontal scrollbars or other layout breakage. Oatcake fixes this by wrapping long words over multiple lines if necessary to prevent overflow.

For example this really long Sanskrit word will get wrapped: िरन्तरान्धकारित-दिगन्तर-कन्दलदमन्द-सुधारस-बिन्दु-सान्द्रतर-घनाघन-वृन्द-सन्देहकर-स्यन्दमान-मकरन्द-बिन्दु-बन्धुरतर-माकन्द-तरु-कुल-तल्प-कल्प-मृदुल-सिकता-जाल-जटिल-मूल-तल-मरुवक-मिलदलघु-लघु-लय-कलित-रमणीय-पानीय-शालिका-बालिका-करार-विन्द-गलन्तिका-गलदेला-लवङ्ग-पाटल-घनसार-कस्तूरिकातिसौरभ-मेदुर-लघुतर-मधुर-शीतलतर-सलिलधारा-निराकरिष्णु-तदीय-विमल-विलोचन-मयूख-रेखापसारित-पिपासायास-पथिक-लोकान्.

So will this really long URL in a <code> tag: https://github.com/seanh/oatcake/commit/8675ffcb168b1d76d708c84a2821c20a3f99e86d.

Oatcake doesn't wrap long words inside preformatted text (<pre>) blocks—you don't want your code being wrapped for you, these use a horizontal scrollbar instead:

url = 'https://github.com/seanh/oatcake/commit/8675ffcb168b1d76d708c84a2821c20a3f99e86d'

CSS classes

Oatcake mostly styles plain HTML, no CSS classes needed. But I bent this rule for a handful of optional extras that're used by adding CSS classes to your HTML.

We've already seen the utility classes small (for small text, the same as the <small> element), rounded (for adding rounded corners to images, videos and iframes), border (for adding borders to images, videos and iframes), and nowrap (for preventing the browser from wrapping the text within an element).

Below are a few more. These are things that I frequently find useful in documents, but that plain HTML lacks the elements for.

Subheadings and lead paragraphs

"Lead" paragraphs use a larger text style but not quite as large or bold as headings. To create a lead paragraph just add class="lead" to a <p>. For example this:

<p class="lead">
  This is a "lead" paragraph. It stands out more than other paragraphs. These
  can be used anywhere in a document.
</p>

will render like this:

This is a "lead" paragraph. It stands out more than other paragraphs. These can be used anywhere in a document.

You can use a lead paragraph as a subheading by putting it together with a heading in an <hgroup>. This:

<hgroup>
  <h1>This is the heading</h1>
  <p class="lead">This is the subheading, it appears in large text beneath the heading.</p>
</hgroup>

will render like this:

This is the heading

This is the subheading, it appears in large text beneath the heading.

Inline elements like <code> and <samp> also work in subheadings and lead paragraphs:

This is a <lead> paragraph containing emphasis, <code tags>, some sample output, a couple of <kbd>'s: Ctrl + c, underlined text, highlighted text, struck-through text, a link, a code link. and evensuperscript andsubscript and small text in it

Creative ways to use lead paragraphs

You can also add the lead class to other elements, for example a <blockquote>:

This is a "lead" block quote.

These are created by adding the lead class to a <blockquote> element like this: <blockquote class="lead">

Or add lead to a <ul> or <ol> to create a large-text list:

  1. Three…

  2. Two…

  3. One…

Here's a definition list with the lead class:

Wild oat
Avena fatua
Common in meadows and pastures.
Synonyms: wild oat grass.

You can add lead to a <pre> to create a large-text preformatted block:

Returning is the motion of the Tao.

Yielding is the way of the Tao.

The ten thousand things are born of being.

Being is born of not being.

You can add lead to a disclosure widget's <summary> element to create one with a large label:

A large-text disclosure widget

Here are the details. These would also be in large text if you put the lead class on the <details> element or on the <p>'s or other elements inside.

Secondary text

You can put text in a dimmed colour by adding the CSS class secondary to any element. For example: <p class="secondary">dimmed text</p>. Secondary text is meant for metadata like authorship, publication dates, tags, copyright notices, that sort of thing. It looks like this:

Posted: Wed 14 August 2019 · Tags: HTML, CSS

All the inline elements also work as you'd expect in secondary text: bold, italics, code, sample output, underlines, highlights, strike-throughs, and links.

Note boxes

You can create a note box by adding the CSS class note to a paragraph:

<p class="note">This is a paragraph that stands out as a note.</p>

It'll look like this:

This is a paragraph that stands out as a note.

<aside class="note">note text</aside> also works and <aside> has semantic meaning in HTML: it's for content that is separate from the main content of the page and not part of the main flow of the document:

A multi-line note will also work nicely:

Morbi sed facilisis nunc. Quisque dictum lectus vitae purus lobortis, dapibus malesuada sapien imperdiet. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae.

Oatcake doesn't attach any particular semantics to note boxes. You can use them for things like alerts, warnings, asides, important information, tips, or just to draw attention to something.

It's best not to overuse note boxes as they can overload the reader, try to stick to no more than one or two per article.

Don't rely on the CSS to convey the meaning of a note box, the contents should make the semantics clear. Beginning a note with a label in bold can help:

Hint: beginning a note with a label can help convey its semantics.

Note box colours

In-line with Oatcake's consistently unshowy nature note boxes are styled the same as preformatted text blocks, code blocks, and disclosure widgets. The difference is that a note box's contents aren't preformatted, monospaced, or collapsible.

It was tempting to provide a variety of different colours for note boxes like other frameworks do. But documents with lots of different-coloured boxes would distract from both reading and writing (always having to remember all the different types of boxes and choose which one to use) and would make it harder to add support for dark mode and for different colour schemes in future.

If you do want to make notes in more interesting colours you can add your own CSS classes to do so. For example:

<style>
  .warning.note {
    background-color: rgb(248, 215, 218);
    border-color: #f1aeb5;
  }
</style>

Now this:

<p class="warning note">
  <strong>Warning!</strong>
  Too many note boxes can overwhelm the reader.
</p>

…will render like this:

Warning! Too many note boxes can overwhelm the reader.

Creative ways to use note boxes

You can put the note class directly on an <ol> or <ul> to style a list as a note:

You can use lead and note together:

This is a "lead note" created by applying both the lead and the note classes to a <p> like this: <p class="lead note">

You can put multiple paragraphs and other arbitrary content (headings, block quotes, lists, code blocks, images…) in a note by putting the note class on a containing <div> or <aside>. Here's some examples:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris aliquam justo erat, sed consequat sem commodo nec. Aenean blandit non lectus id rutrum.

Pellentesque non lacus vel quam lobortis tincidunt. In dignissim arcu eu purus porta finibus. Quisque bibendum erat nec porttitor tincidunt.

In egestas vel enim non interdum. Curabitur sed nisi scelerisque, suscipit velit in, ornare velit. Praesent laoreet bibendum ipsum nec elementum.

<h4> headings work well in notes:

Note

Sed porta at quam id lacinia. Pellentesque sem odio, dignissim et ultrices at, pharetra id magna. Praesent auctor bibendum ante non faucibus.

So do <h3>'s:

Important

Sed porta at quam id lacinia. Pellentesque sem odio, dignissim et ultrices at, pharetra id magna. Praesent auctor bibendum ante non faucibus.

Sed porta at quam id lacinia. Pellentesque sem odio, dignissim et ultrices at, pharetra id magna. Praesent auctor bibendum ante non faucibus.

You can use a horizontal rule to split a note into segments:

Tip

Sed porta at quam id lacinia. Pellentesque sem odio, dignissim et ultrices at, pharetra id magna. Praesent auctor bibendum ante non faucibus.


Proin tortor libero, lobortis id nulla eget, laoreet malesuada arcu.

You can put a block quote in a note box. All the inline elements also work:

Duis efficitur justo semper mauris tempor:

  • Eget hendrerit diam
  • Nunc feugiat congue dictum, nullam auctor in dui
  • a tempus nunc elementum
  • Pellentesque velit felis bibendum ac quis euismod

An image in a note block:

A bowl of oats

Of course videos also work:

And audio:

You can even put code blocks in notes:

tell application "Foo"
    beep
end tell

Even disclosure widgets work inside note boxes:

This is the summary

Here are the details…

Headings in note boxes

Like with block quotes and disclosure widgets, Oatcake also makes sure that the vertical spacing is right for headings in note boxes:

An <h1> in a note

Curabitur neque tortor, sollicitudin non tincidunt et, feugiat sit amet quam.

An <h2> in a note

Aliquam erat volutpat. Curabitur fringilla arcu velit, non rutrum massa dapibus sed.

An <h3> in a note

Phasellus vehicula risus mauris, sagittis commodo nisi vulputate eu.

An <h4> in a note

Phasellus id diam turpis. Donec in enim suscipit, aliquet turpis nec, vulputate nisi.

An <h2> in a note

This is the body of the note.

An <h3> in a note

This is the body of the note.

An <h4> in a note

This is the body of the note

Badges

Oatcake provides badges that you can use for things like counts, labels and tags. Just add the CSS class badge to a <span>, like this: <span class="badge">Badge text</span>:

Badge

You can also put the badge class on an <a> or <button> to create a badge with hover and focus states:

An <a> badge

As with <kbd>'s, if your badge contains more than one word Oatcake prevents browsers from wrapping it over multiple lines (so don't make badges too long).

Badge colours

As with note boxes, it was tempting to add a variety of different colour choices for badges but this would be distracting and would make it harder to add dark mode and multiple colour schemes in future.

If you do want to make badges in more interesting colours you can add your own CSS classes to do so. For example:

<style>
  .primary.badge {
    background-color: rgb(13, 110, 253);
    color: white;
  }
</style>

Now this:

<span class="primary badge">Primary Badge</span>

…will render like this:

Primary Badge

Creative ways to use badges

Badges can be used in headings:

Heading New

Badges can be used inline in paragraphs:

This is a paragraph with an inline badge in it.

Badges can be used in list items:

Badges can be used in code blocks, for example to annotate lines:

class MyError(Exception): 1
    def __init__(self, status_code, reason):
        super().__init__(status_code, reason) 2
        self.status_code = status_code
        self.reason = reason
1

In Python, all custom exception classes should inherit from the built-in Exception class (or one of its subclasses).

2

When inheriting from Exception, if you've written your own __init__() method, you should always call super().__init__().

Footnotes

  1. This is an example footnote.