Fork me on GitHub

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 page is styled with Oatcake, my universal typography theme. 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.

To style your own site with Oatcake, see the instructions in the README.

The rest of this tremendously long page will demo 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! Oatcake works with standard HTML elements, so every component comes with a semantic definition and usage guidelines, complete with examples, from the HTML Standard and MDN.

Fonts

Oatcake uses a system font stack based on the system-ui font-family: it chooses the default interface font from the user's OS.

For code blocks Oatcake uses a font stack based on the ui-monospace font-family which selects the operating system's default monospaced font.

Details: fonts

Design notes

Many themes use idiosyncratic fonts that distract from reading and writing. A system font stack follows Oatcake's philosophy of looking good without drawing attention to its design choices. It's fast (no fonts to download), readable (modern operating systems ship high-quality fonts adapted to today's screens and legible at small sizes), and feels native to the user's system (nothing too distinctive).

A system font stack also supports a wide range of weights: bold (font-weight: 700), bolder (font-weight: 900), light (font-weight: 300), lighter (font-weight: 100).

Customizing Oatcake's fonts

You can customize the fonts by setting some CSS variables in your own custom stylesheet:

<style>
  :root {
    --ok-font-family: 'ui-rounded, source-sans-pro, sans-serif';
    --ok-font-family-mono: '"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 {
    --ok-font-family: 'ui-rounded, source-sans-pro, sans-serif';
    --ok-font-family-mono: '"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:

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

Emoji

Oatcake's font stack also adds support for native emoji. Here's a bunch:

🫢 💀 🥄 🍴 🫜 😒 🤎 🔪 😨 💚 🧘 😴 🤗 😆 😼 😾 😰 🤪 🩵 😏 🤭 🫙 🌍 👽 🤫 🙀 🏺 💌 🍆 🛀 🥒 🍊 🤕 💜 🧄 😢 🌽 😗 💙 🌐 🌏 🥐 💛 🫣 🧡 👾 🙈 💝 🥹 🩷 🤍 💖 🫚 🌎 🤔 🖤 🩶 🫛 ☠ 😝 🤒 💢 🍞 😿 🥲 💯 🥰 🤬 🚴 💋 👋 🧭 🗾 🛌 🥑 🫰 🥥 ✌ 🧒 🧔 🙎 👦 😃 😍 🎨 🙃 🤩 🌸 😘 🎯 🌟 🎭 🐿

The monospaced font stack also adds the same emoji support:

# 🚀 Initialize the rocket launch sequence
status = "Ready for liftoff! 🌟"
countdown = [3, 2, 1]  # ⏰ T-minus...
print(f"{status} {'🔥' * len(countdown)}")
# 🎉 Mission success! 🛸

Colors

By default Oatcake uses black text on a white background, and the standard bright blue links. It sets a typical light-gray background and/or border for code, sample output, preformatted text blocks, block quotes, disclosure widgets and asides. A yellow background for highlights, and a muted text color for footers.

Details: colors

Design notes

Like its fonts, Oatcake's colors are also chosen to be readable and not to be noticed.

Dark purple is used to differentiate visited links from un-visited ones. Links also flash red while being activated to give visual feedback. The exact colors used for visited, un-visited and active links are those suggested in the HTML standard.

Customizing Oatcake's colors

As with the fonts, you can customize Oatcake's colors by setting some CSS variables in your own custom stylesheet:

<style>
  :root {
    --ok-color-bg: black;
    --ok-color-fg: white;
  }
</style>

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

<style>
  #myElement {
    --ok-color-bg: black;
    --ok-color-fg: white;
  }
</style>

For example, click this button to change this page to a dark mode color theme:

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

--ok-color-bg
The primary background color.
--ok-color-fg
The primary foreground color.
--ok-color-block-bg
The background-color of preformatted text blocks, code blocks, sample output blocks, disclosure widgets and asides.
--ok-color-block-fg
The foreground color of blocks.
--ok-color-code-bg
The background-color of inline <code> and <samp> elements.
--ok-color-code-fg
The foreground color of inline <code>'s and <samp>'s.
--ok-color-muted-fg
The foreground color of footers, and list item markers.
--ok-color-border
The border-color of block quotes, preformatted text blocks, code blocks, sample output blocks, disclosure widgets, asides, images, videos, iframes and horizontal rules.
--ok-color-highlight-bg
The background-color of highlighted text (<mark> elements).
--ok-color-highlight-fg
The foreground color of highlighted text.
--ok-color-link-fg
The foreground color of links.
--ok-color-link-visited-fg
The foreground color of visited links.
--ok-color-link-active-fg
The foreground color of links while they're being clicked on or otherwise activated. Provides visual feedback that the link was clicked.
--ok-color-summary-marker
The foreground color of the open/close triangles on disclosure widgets.

Rhythm

Oatcake picks a comfortable base line-height and sets all sizes, margins and paddings to multiples of that rhythm, like writing on a sheet of lined paper:

Lorem ipsum

Ut convallis nisl ac tempor molestie. Pellentesque consectetur mattis orci sit amet dignissim. Mauris in erat aliquam tellus efficitur.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed aliquam suscipit nisi lacinia aliquam. Proin at lacinia massa. Etiam blandit tortor nunc. Mauris ut porttitor elit. Nam massa nibh, ultrices a consectetur ut, blandit at orci.

Maecenas semper commodo venenatis

def main():
    print("Hello, world!")


if __name__ == "__main__":
    main()
Figure 1: “Hello world” in Python.

When the lines are hidden, the regularity makes pages more enjoyable to read: things flow like they belong together and everything feels calmer, more orderly and harmonious.

It's surprisingly difficult to get this comprehensively right, without some element or combination throwing off the rhythm. Click the button to toggle vertical rhythm lines for this entire page:

Horizontal alignment

Oatcake also aligns things horizontally, using consistent margins, borders and paddings:

This is a normal paragraph.

This is a block quote.

This is a description list:

Term
Description

Here's a code block:

print("Hello, world!")

Here's an <aside>:

Here's a disclosure widget:

This is the summary Here are the details.

Inline elements

All of HTML's inline elements work as you'd expect: links, code(), bold, italics, strikethroughs, underlines, highlights, (even mid-word highlights: unfriggingbelievable), small text, subscripts24 and superscripts42, abbreviations like HTML, quotes, and keyboard input: Ctrl + c.

The inline element styles are chosen so that they can be combined in many ways. For example you can combine two <strong>'s to make extra bold. You can also combine bold and italic; code spans can be italic, bold, struck-through or highlighted; links can be italic, bold, struck-through or highlighted; even <kbd>'s can contain italics, bold, highlights or strikethroughs: Ctrl + Shift + Alt + Del; you can put a link in a code span or in a <kbd>: Super; small text can contain bold, italics, code, highlights, links and strikethroughs, etc.

Details: inline elements

Here's a pocket guide to some of the more useful inline elements that Oatcake supports and the HTML Standard's advice for using them.

The <code> and <samp> elements: code and sample output

To represent code, filenames, the names of computer programs, etc, wrap them in <code> tags (HTML Standard, MDN). This: <code>this is code</code>, renders like this: this is code. This is what `backticks` do in Markdown. For multi-line code blocks see code blocks.

To represent sample output from a program wrap it in <samp> tags (HTML Standard, MDN). This: <samp>Keyboard not found. Press F1 to continue</samp>, renders like this: Keyboard not found. Press F1 to continue. For multi-line sample output see sample output blocks.

Design notes

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.

Customization: how to make <samp> and <code> look different from each other

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

The <kbd> element: text input

To represent user input from a keyboard or other text entry device wrap it in <kbd> tags (HTML Standard, MDN). This: <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Del</kbd>, renders like this: Ctrl + Alt + Del

Tip: representing multiple keystrokes

There are three different ways to represent multiple keystrokes that form a single input. All three ways are equally valid:

  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

Tip: avoid long <kbd>'s

Oatcake 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;"> also works.

You can also use either technique if you don't want a <code>, <samp>, <mark>, etc to be wrapped, for example: <code style="white-space: 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).

The <cite> element: marking the title of a work

Instead of <code>, you can also use <cite> (HTML standard, MDN) for the name or title of a computer program or any other work (book, research paper, poem, song, play, film, TV show, game, painting, website or web page, etc). Oatcake styles <cite> in italics, here's an example from the HTML Standard:

My favorite book is The Reality Dysfunction by Peter F. Hamilton. My favorite comic is Pearls Before Swine by Stephan Pastis. My favorite track is Jive Samba by the Cannonball Adderley Sextet.

You can use <cite> whenever mentioning the title of a work: you don't have to be quoting from or referencing the work. But <cite> is only for the titles of works: it's wrong to wrap a person's name (e.g. the author) in a <cite>.

Also, only the title of the work should go in a <cite>. This is wrong:

According to <cite>the Wikipedia article on HTML</cite>, [...]

Only the title should be in the <cite>:

According to the Wikipedia article on <cite>HTML</cite>, [...]

You can add the cite attribute to a <cite> element to give a URL for the work being cited. This isn't rendered, it's just for scripts:

<cite cite="https://www.w3.org/Consortium/">About W3C</cite>

The <var> element: variables

Instead of <code>, you can also use <var> (HTML standard, MDN) for variables, constants, symbols, quantities, parameters, and placeholders. Oatcake styles <var> in italics:

The variables minSpeed and maxSpeed control the minimum and maximum speed of the apparatus in revolutions per minute (RPM).

The <mark> element: highlighting for relevance

<mark> (HTML standard, MDN) highlights text: this is some text highlighted with <mark>.

<mark> is for denoting the relevance of a span of text to the current context. It can be used in a quote or block quote to add a highlight that was not present in the original source. 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. Here's an example from the HTML Standard:

Consider the following quote:

Look around and you will find, no-one's really colour blind.

As we can tell from the spelling of the word, the person writing this quote is clearly not American.

Another use for <mark> is to highlight parts of a code block that you want to refer to from the text. Again this is semantically correct and won't conflict with any syntax highlighting in the code block. Example from the standard:

The highlighted part below is where the error lies:

var i: Integer;
begin
i := 1.1;
end.

Finally, a third use for <mark> is to highlight the parts of a document that match a search string. Here's an example from MDN:

Search results for "salamander":


Several species of salamander inhabit the temperate rainforest of the Pacific Northwest.

Most salamanders are nocturnal, and hunt for insects, worms, and other small creatures.

The <dfn> element: defining terms

<dfn> (HTML standard, MDN) can be used to mark up the defining instance of a term. You wrap a term in <dfn> and then the definition of that term should be in the same paragraph, description list group, or <section> as the <dfn>. Oatcake styles <dfn>'s in italics. Here's an example from MDN:

A validator is a program that checks for syntax errors in code or documents.

You can give a <dfn> an id so that you can link to it. Then whenever using the term elsewhere in the document you can link the usages to the definition. Here's an example from MDN:

<p>
  The HTML Definition element
  (<dfn id="definition-dfn">DFN</dfn>) is used to indicate the term being defined within the context of a
  definition phrase or sentence.
</p>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  Graece donan, Latine voluptatem vocant. Confecta res esset.
  Duo Reges: constructio interrete. Scrupulum, inquam,
  abeunti;
</p>

<p>
  Because of all of that, we decided to use the
  <a href="#definition-dfn">DFN</a> element for this project.
</p>

A <dfn> can have a title attribute containing the exact value of the term being defined. This is only necessary if the <dfn>'s contents aren't already the exact value of the term. For example when using an abbreviation:

<p>The <dfn title="Garage Door Opener">GDO</dfn> is a device
that allows off-world teams to open the iris.</p>

The <abbr> element: abbreviations and acronyms

<abbr> (HTML standard, MDN) is for abbreviations and acronyms.

An <abbr> on its own has no visual effect with Oatcake: it's semantic only. But if you provide the expansion as the value of a title attribute on the <abbr> then Oatcake adds a dotted underline and makes the mouse cursor change to a "help" cursor when hovering over the <abbr>. The title appears in a tooltip on hover. For example, this:

<abbr title="HyperText Markup Language">HTML</abbr>

…renders like this:

HTML

You don't have to use <abbr>: the HTML Standard explicitly says that marking up abbreviations and acronyms with <abbr> is optional.

When using <abbr> you don't have to use the title attribute: it's just as good to put the expansion in parentheses following the first use of the abbreviation. Subsequent uses of the abbreviation don't need to repeat the expansion. This is probably better than the title attribute in most cases because some browsers (e.g. mobile browsers) don't support tooltips. Here's an example from MDN:

You can use <abbr>CSS</abbr> (Cascading Style Sheets) to
style your <abbr>HTML</abbr> (HyperText Markup Language).
Using style sheets, you can keep your <abbr>CSS</abbr>
presentation layer and <abbr>HTML</abbr> content layer
separate. This is called "separation of concerns."

You can use <abbr> and <dfn> together as in this example from MDN:

<p>
  The
  <dfn><abbr title="Hubble Space Telescope">HST</abbr></dfn>
  is among the most productive scientific instruments ever
  constructed. It has been in orbit for over 20 years,
  scanning the sky and returning data and photographs of
  unprecedented quality and detail.
</p>

<p>
  Indeed, the <abbr title="Hubble Space Telescope">HST</abbr>
  has arguably done more to advance science than any device
  ever built.
</p>

The <strong> element: importance

<strong> (HTML standard, MDN) is what **double asterisks** or __double underscores__ do in Markdown, it makes text bold: this is bold text with <strong>.

<strong> isn't a generic "bold" element (use CSS for that: font-weight: bold). <strong> is meant to be used to mark something as important. Examples from the HTML Standard and MDN:

Chapter 1: The Praxis
Figure 1. Ant colony dynamics. The ants in this colony are affected by the heat source (upper left) and the food source (lower right).
… the most important rule, the rule you can never forget, no matter how much he cries, no matter how much he begs: never feed him after midnight.
Important: Before proceeding, make sure you add plenty of butter.

Welcome to Remy, the reminder system.

Your tasks for today:

  • Turn off the oven.

  • Put out the trash.

  • Do the laundry.

Warning. This dungeon is dangerous. Avoid the ducks. Take any gold you find. Do not take any of the diamonds, they are explosive and will destroy anything within ten meters. You have been warned.

As you can see in that last example: you can nest <strong>'s to indicate increasing levels of importance. Oatcake styles nested <strong>'s even bolder: bold and bolder (whether this is visible may depend on your browser and font).

The <b> element: bring attention to

<b> (HTML standard, MDN) also styles text in bold but with a different semantic meaning: <b> is for text to which attention is being drawn for utilitarian purposes without conveying any extra importance and with no implication of an alternate voice or mood.

To make something bold for purely stylistic (rather than utilitarian) purposes use CSS (font-weight: bold), for importance use <strong>, for alternate voice or mood use <i>. If none of these apply and you still want to bring attention to some text by making it bold then fall back to <b>.

Some examples from the HTML Standard and MDN:

The <em> element: stress emphasis

<em> (HTML standard, MDN) is what *single asterisks* or _single underscores_ do in Markdown, it makes text italic: this is italic text with <em>.

<em> isn't a generic "italics" element (use CSS for that: font-style: italic): <em> is meant to be used for stress emphasis that changes the meaning of the sentence. Examples from the HTML standard:

Dogs are cute animals.

Cats are cute animals.

Cats are not cute animals.

Cats are cute animals.

Cats are mean animals.

Cats are cute animals.

Cats are cute vegetables.

Cats are cute animals.

Cats are cute animals!

The <i> element: alternate voice

<i> (HTML standard, MDN) also styles text in italics but with a different semantic meaning: <i> is for a span of text in an alternate voice or mood, or otherwise offset from the normal prose in a manner indicating a different quality of text.

To make something italic for purely stylistic purposes use CSS (font-style: italic), use <em> for stress emphasis, use <dfn> to mark the defining instance of a term, use <cite> for the titles of works, use <var> for variables, use <strong> for importance and use <b> to bring attention to something. If none of these apply and you still want to make something italic to indicate a different voice/mood/mode/quality/semantics from the surrounding text then fall back to <i>.

Some examples from the HTML Standard and MDN:

The <q> element: inline quotations

<q> (HTML standard, MDN) is for inline quotations: Whatever you lose, you've won. Whatever you win, you've lost. For long or multi-paragraph quotations use <blockquote> instead. Notes on <q>:

The <small> element: side-comments and small print

<small> (HTML standard, MDN) makes text smaller: this is some small text created with the <small> element.

<small> is meant to be used for side-comments and small print: disclaimers, caveats, legal restrictions, copyrights, attribution, and licensing requirements, etc. It's only meant for short runs of text, not multi-paragraph sections. Here's an example from MDN

MDN Web Docs is a learning platform for Web technologies and the software that powers the Web.


The content is licensed under a Creative Commons Attribution-ShareAlike 2.5 Generic License.

The <sub> and <sup> elements: subscript and superscript

<sub> and <sup> (HTML standard, MDN: sub, sup) are for subscriptssub and superscripts.sup

Superscripts can be used for ordinal numbers. Example from MDN:

The ordinal number "fifth" can be abbreviated in various languages as follows:

  • English: 5th
  • French: 5ème

Superscripts can also be used to create footnotes:

According to the computations by Nakamura, Johnson, and Mason1 this will result in the complete annihilation of both particles.

<sub> and <sup> can be used (perhaps inside a <var>) for mathematical expressions or chemical formulas:

Almost every developer's favorite molecule is C8H10N4O2, also known as "caffeine."
Then she turned to the blackboard and picked up the chalk. After a few moment's thought, she wrote E = mc2. The teacher looked pleased.

The <ins> and <del> elements: insertions and deletions

<ins> (HTML standard, MDN) represents text that has been inserted into the document. Oatcake styles <ins> with an underline: this is inserted text with <ins>.

<ins> goes with <del> (HTML standard, MDN) which represents text that has been deleted from the document. Oatcake styles <del> with a strikethrough: this is text that has been marked as deleted with <del>.

<ins> and <del> together can be used to create a diff, like this example from MDN:

There is nothing no code either good or bad, but thinking running it makes it so.

You can add a cite attribute to an <ins> or <del> to give the URL of a document that explains the change, for example: <del cite="/edits/r192">. (This won't be rendered: it's just for scripts.)

You can also add a datetime attribute to an <ins> or <del> to give the date and time at which the change was made, for example: <ins datetime="2008-02-12T15:20Z">. (This won't be rendered either: it's also just for scripts.)

The <s> element: no longer accurate or relevant

<s> (HTML standard, MDN) strikes though text: this is struck-through text with <s>. It looks the same as <del> but has a different semantic meaning: <s> is for text that is no longer accurate or no longer relevant rather than for text that has been removed from the document. Here's a couple of examples from the HTML standard and MDN:

Buy our Iced Tea and Lemonade!

Recommended retail price: $3.99 per bottle

Now selling for just $2.99 a bottle!

There will be a few tickets available at the box office tonight.

SOLD OUT!

The <u> element: spelling mistakes

Finally, <u> (HTML standard, MDN) underlines text: this is underlined text with <u>. It looks the same as <ins> but has a different semantic meaning: <u> is meant to be used as an unarticulated, though explicitly rendered, non-textual annotation, such as labelling a spelling mistake:

You could use this element to highlight speling mistakes, so the writer can corect them.

You could use CSS to give <u class="spelling"> elements a red wavy underline typical of spellcheckers (Oatcake doesn't do this for you):

This paragraph includes a wrnogly spelled word.

<u> is not meant to be used as a generic "underline" element (use CSS for that: text-decoration: underline;). The HTML Standard and MDN encourage you to avoid <u> in most cases and choose other elements such as <em>, <b>, <mark>, <strong>, <cite> and <i>.


  1. This is an example footnote.

Headings

Oatcake uses both the font-size and the amount of vertical space above and below to provide three visually distinct levels of headings: <h1>, <h2>, and <h3>. While you can also use <h4>'s, <h5>'s and <h6>'s, they look identical to <h3>'s. Here's what all six headings look like:

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.

Details: headings

Design notes

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: bottom-of-the-barrel tactics 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, meanwhile subheadings often come in smaller fonts than the main body text.

Just because HTML has six levels of headings doesn't mean you should use them all. Oatcake is opinionated about this and thinks that most pages shouldn't use more than three levels of headings, ideally not more than two: a single <h1> page title then <h2>'s to break up the document into sections and—only if really necessary—<h3>'s for subsections. More levels are confusing and make it difficult for readers to orient themselves within the document.

By restraining itself to just three visually distinct levels—using the smallest necessary increments in font size and space above and below to distinguish the levels from each other—Oatcake is able to make the levels distinct without gimmicks.

If you really do need to use more than three levels you can try hierarchically numbering your headings, see below.

Design notes: vertical alignment of headings

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 all levels of 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.a 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.a.i 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.a.ii 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.b 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.

Edge case: stacked headings

Sometimes a 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 with large unnecessary gaps between the headings. Oatcake avoids this by styling 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

Edge case: inline elements in headings

A lot of themes break or look weird if you try to use inline elements in a heading. Oatcake makes sure that all the inline elements work in headings:

A heading with bold in it

A heading with italics 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 mid-word emphasis in it

A heading withsuperscript andsubscript and small text in it

Edge case: <code> and <samp> in headings

<code> and <samp> elements in headings get a monospaced font but this can be quite subtle so Oatcake also surrounds the code in backticks (thanks to Tailwind CSS Typography for the idea). Oatcake also prevents line-wrapping within a <code> or <samp> in a heading.

An <h1> with code and sample output

An <h2> with code and sample output

An <h3> with code and sample output

Edge case: headings that wrap

Sometimes a heading wraps 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 <h1> heading:

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

This is a multi-line <h2> 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 <h3> 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 <h1> heading containing emphasis, <code>, a couple of <kbd>'s: Ctrl + c, underlined text, highlighted text, struck-through text, a link, a bold link, a code link and evensuperscript andsubscript and small text

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

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

Subheadings

You can add a subheading to an <h1><h6> heading by wrapping the <h1><h6> in an <hgroup> along with the subheading in a <p>. Oatcake will style the <p> in a larger font-size and/or lighter weight. Here's some examples from MDN and the HTML Standard, this <h1> with a subheading:

<hgroup>
  <h1>Frankenstein</h1>
  <p>Or: The Modern Prometheus</p>
</hgroup>

<p>
  Victor Frankenstein, a Swiss scientist, has a great ambition: to create
  intelligent life. But when his creature first stirs, he realizes he has made a
  monster. A monster which, abandoned by his master and shunned by everyone who
  sees it, follows Dr Frankenstein to the very ends of the earth.
</p>

…renders like this:

Frankenstein

Or: The Modern Prometheus

Victor Frankenstein, a Swiss scientist, has a great ambition: to create intelligent life. But when his creature first stirs, he realizes he has made a monster. A monster which, abandoned by his master and shunned by everyone who sees it, follows Dr Frankenstein to the very ends of the earth.

Here's what an <h2> with a subheading looks like:

The reality dysfunction

Space is not the only void

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et facilisis purus. Cras molestie tortor velit, interdum fringilla diam ornare vel. Nam quis venenatis nibh.

And an <h3>:

Dr. Strangelove

Or: How I Learned to Stop Worrying and Love the Bomb

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et facilisis purus. Cras molestie tortor velit, interdum fringilla diam ornare vel. Nam quis venenatis nibh.

Details: <hgroup> and subheadings

Usage

<hgroup> (HTML Standard, MDN) is a container for a single <h1><h6> heading and one or more <p>'s representing a subheading, alternative title or tagline. The <p>'s can come before and/or after the heading.

We've seen examples of a subheading and an alternative title, here's a third example from MDN that uses the <p> as a tagline containing related or secondary content. I've modified the example to put the tagline before the heading:

Last Updated 12 July 2022

HTML: Living Standard

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et facilisis purus. Cras molestie tortor velit, interdum fringilla diam ornare vel. Nam quis venenatis nibh.

Edge case: multi-paragraph subheadings

Subheadings can be as long as you want, even multiple <p>'s:

Lorem ipsum dolor sit amet

Consectetur adipiscing elit. Nam interdum, mi et iaculis laoreet, erat felis accumsan lorem, in cursus sem sem vitae quam. Integer aliquam ullamcorper feugiat.

Sed tellus velit, ultrices eu fermentum tincidunt, auctor maximus diam. Cras in erat nec elit aliquet auctor. Vivamus imperdiet nisl nec porttitor consequat.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et facilisis purus. Cras molestie tortor velit, interdum fringilla diam ornare vel. Nam quis venenatis nibh.

Edge case: inline elements in subheadings

All the inline elements work in subheadings:

Aenean lacinia porta ullamcorper

This is a subheading containing italics, bold, <code>, 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.

Lists

This simple unordered list with <ul>:

<ul>
  <li>Vivamus sit amet elit bibendum</li>
  <li>Aliquam ornare sapien ut nisl tristique</li>
  <li>Praesent aliquet erat eu felis</li>
</ul>

…renders like this with Oatcake:

The same thing but with <ol> creates an ordered list:

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

Some or all 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.
Details: lists

Edge case: nested lists

It's probably not great writing to use too many nested lists, but it happens. 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:

Edge case: 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:

Edge case: 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 description list in it:

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

Usage: <ul> or <ol>?

According to the HTML Standard and MDN <ul> (unordered list) is for where changing the order [of the list items] would not materially change the meaning of the document. If the order of the list items matters, use <ol>.

Tip: tricks with 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>?

  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

Description lists

You create a description list with <dl>, <dt>, and <dd>. This:

<dl>
  <dt>Oatcake</dt>
  <dd>Thin flat unleavened cake of baked oatmeal.</dd>
  <dt>Oatmeal</dt>
  <dd>Porridge made of rolled oats.</dd>
</dl>

…renders like this with Oatcake:

Oatcake
Thin flat unleavened cake of baked oatmeal.
Oatmeal
Porridge made of rolled oats.
Details: description lists

Description lists (HTML Standard, MDN) 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 description:

<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 (entirely optional) use of <dfn> to mark the terms being defined. 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

Use <blockquote> to create block quotes. This:

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

…renders like this:

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

If your block quote contains only a single paragraph you can omit the <p> and it'll look the same. This:

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

…renders like this:

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

Design notes

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

Oatcake uses indentation and a left border. This is a common, recognizable 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.

Customization

You can customize the style of block quotes with your own CSS. For example this will use a larger font-size and a thinner font-weight, and will use a "left double quotation mark" character rather than a left border to indicate the block quote:

<style>
  blockquote {
    border: none;
    font-size: 19px;
    font-weight: 300;
    position: relative;
  }
  blockquote::before {
    position: absolute;
    font-size: 3em;
    z-index: -1;
    color: var(--ok-color-border);
    content: "\201C";
    left: 0;
    top: 0;
  }
</style>

Now block quotes will look like this:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a turpis at lacus accumsan dignissim sed vitae diam. Nullam bibendum egestas libero, tincidunt tincidunt ex iaculis quis.

Maecenas eget velit luctus, maximus urna quis, condimentum odio. Curabitur ultrices nunc quis turpis ullamcorper rutrum quis sit amet massa. Sed vel odio vel massa rutrum scelerisque.

Edge case: 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.

Usage: 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.

Usage: 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).

Usage: 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 for an example.

Usage: the <cite> element

If the attribution contains the title of a work you can wrap it in a <cite>, 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>
  …

Usage: the cite attribute

You can add a cite attribute to a <blockquote> whose value is a URL for the quoted source. cite attributes aren't visible in the rendered HTML, they're meant to be read by scripts:

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

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, but just right. Images also get a very subtle border and rounded corners: it looks nicer and it's consistent with other elements in Oatcake that get the same borders and rounded corners:

A bowl of oats
Details: images

Customization: removing borders from images

You can remove the border from an image by adding the CSS border: none;. For example, this:

<img style="border: none;" src="…" alt="…" />

…renders like this:

A bowl of oats

To turn off borders for all images add this to your site's stylesheet:

img {
  border: none;
}

Customization: removing rounded corners from images

If you want to remove the rounded corners from images add border-radius: 0; to the <img>'s CSS. This:

<img style="border-radius: 0;" src="…" alt="…" />

…renders like this:

A bowl of oats

To turn off rounded corners for all images add this to your site's stylesheet:

img {
  border-radius: 0;
}

Videos

The same extra little bit of vertical space, borders and rounded corners are also applied to video players created using <video>:

Details: videos

Customization: removing borders from videos

As with images you can remove the border from a video by adding the CSS border: none;. This:

<video style="border: none;" src="…"></video>

…renders like this:

To turn off borders for all videos add this to your site's stylesheet:

video {
  border: none;
}

Customization: removing rounded corners from videos

To remove the rounded corners from a video add border-radius: 0; to the <video>'s CSS. This:

<video style="border-radius: 0;" src="…"></video>

…renders like this:

To turn off rounded corners for all videos add this to your site's stylesheet:

video {
  border-radius: 0;
}

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, borders and rounded corners are also applied to embedded pages created with <iframe>:

Details: iframes

Customization: removing borders from iframes

As with images and videos you can remove the border from an iframe by adding the CSS border: none;. This:

<iframe style="border: none;" src="…"></iframe>

…renders like this:

To turn off borders for all iframes add this to your site's stylesheet:

iframe {
  border: none;
}

Customization: removing rounded corners from iframes

To remove the rounded corners from an iframe add border-radius: 0; to the <iframe>'s CSS. This:

<iframe style="border-radius: 0;" src="…"></iframe>

…renders like this:

To turn off rounded corners for all iframes add this to your site's stylesheet:

iframe {
  border-radius: 0;
}

Figures and captions

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

<figure>
  <img src="media/spoon.jpg" alt="A wooden spoon full of oats" title="A wooden spoon full of oats">
  <figcaption><b>Figure 1:</b> a wooden spoon full of oats.</figcaption>
</figure>

…renders like this:

A wooden spoon full of oats
Figure 1: a wooden spoon full of oats.

You can also put the caption above the figure contents if you prefer:

Figure 2: Sea Oats by the shore.
Sea Oats by the shore
Details: figures and captions

Design notes

As with images, videos and audio players, figures have a little extra vertical breathing space above and below so they don't feel cramped. This applies even if the figure just contains text (e.g. a block quote or code block), not only when the figure contains an image or video.

Both top and bottom figure captions are placed slightly closer to the figure they belong to than to the other content before and after the figure.

Edge case: inline elements in figure captions

All the inline elements work in figure captions:

A bowl of oats
Laboris nisi ut aliquip ex ea commodo consequat. Ctrl + Alt + Del 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.

Usage: figure captions

Captions can be used for additional information about the figure content or its source, and/or to give a figure a number or other label 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.

If you add an id attribute to a <figure> then you can link to it when referring to it. Here's an example from the HTML Standard:

<p>In <a href="#l4">listing 4</a> we see the primary core
interface API declaration.</p>

<figure id="l4">
 <figcaption>Listing 4. The primary core interface API declaration.</figcaption>
 <pre><code>interface PrimaryCore {
 boolean verifyDataLine();
 undefined sendData(sequence<byte> data);
 undefined initSelfDestruct();
}</code></pre>
</figure>

Tip: left-aligned figure captions

Oatcake center-aligns figure captions by default. If you want to left-align a caption add style="text-align:left;" to the <figcaption>. This:

<figure>
<img src="media/oats.jpg" alt="A bowl of oats" title="A bowl of oats">
<figcaption style="text-align:left;">
  Lorem ipsum dolor sit amet […] Mauris rutrum aliquet libero
  vel tempor.
</figcaption>
</figure>

…renders like this:

A bowl of oats
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc convallis sollicitudin lectus, quis egestas felis vehicula ut. Duis at cursus nisi, non tincidunt nibh. Mauris rutrum aliquet libero vel tempor.

If you want to left-align all figure captions add this to your site's CSS:

figcaption {
  text-align: left;
}

Tip: small text figure captions

Small text can work well for figure captions: wrap the contents of the <figcaption> in a <small>. This:

<figure>
  <img src="media/oats.jpg" alt="A bowl of oats" title="A bowl of oats">
  <figcaption>
    <small>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</small>
  </figcaption>
</figure>

…renders like this:

A bowl of oats
Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Tip: anything can go in a figure

Figures aren't just for images. You can put anything in a figure. Here's an example from MDN with some code in a figure:

Get browser details using navigator.
function NavigatorExample() {
  let txt = `Browser CodeName: ${navigator.appCodeName};\n`;
  txt += `Browser Name: ${navigator.appName};\n`;
  txt += `Browser Version: ${navigator.appVersion};\n`;
  txt += `Cookies Enabled: ${navigator.cookieEnabled};\n`;
  txt += `Platform: ${navigator.platform};\n`;
  txt += `User-agent header: ${navigator.userAgent};`;
  console.log("NavigatorExample", txt);
}

Here's another example from MDN with a <blockquote> in a <figure> and the quote's attribution in the <figcaption>:

Edsger Dijkstra:
If debugging is the process of removing software bugs, then programming must be the process of putting them in.

Preformatted text

You can create a block of preformatted text—where whitespace, indentation and line breaks are rendered as-is, without compressing or re-wrapping—using the <pre> element. Preformatted text blocks 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

HTML code blocks are created by wrapping the entire contents of a <pre> in a <code>. 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. This is less distracting for readers and makes Oatcake easier to maintain:

#include <stdio.h>

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

You can use inline elements in preformatted text and code 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 highlight in a code block. */
    /* Here's a link. */
    printf("Hello World!\n");
}
Customization: code blocks

You can customize the fonts and colors of code blocks by setting a couple of CSS variables. For example:

<style>
  pre:has(> code:only-child),
  pre > code:only-child {
    --ok-color-block-bg: #282828;
    --ok-color-block-fg: #ebdbb2;
    --ok-color-border: #d65d03;
    --ok-font-family-mono: 'Nimbus Mono PS', 'Courier New', monospace;
  }
</style>

Now code blocks will look like this:

#include <stdio.h>

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

Sample output blocks

HTML sample output blocks are created by wrapping the contents of a <pre> in a <samp> instead of a <code>. Sample output blocks have a different semantic meaning than code blocks: they represent a block of computer output rather than input code.

As with inline <code> and <samp> elements, Oatcake styles sample output blocks the same as code blocks, letting the difference be semantic only. This is to avoid having too many distracting visual styles and because there's no obvious way to visually indicate the semantic difference between "code" and "output".

Here's what a sample output block looks like with Oatcake:

 _________________________________
/ You are taking yourself far too \
\ seriously.                      /
 ---------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Tip: using <pre>, <code>, <samp>, and <kbd> together

<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

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(--ok-color-muted-fg);
  }
<style>

Now the previous example will render like this:

> console.log(2.3 + 2.4) Enter
4.699999999999999

Disclosure widgets

I've already used these extensively in a desperate attempt to control the length of this page: you can create collapsible disclosure widgets with <details> and <summary>. This:

<details>
  <summary>Material</summary>
  <p>The picture frame is made of solid oak wood.</p>
</details>

…renders like this:

Material

The picture frame is made of solid oak wood.

Details: disclosure widgets

Design notes

To avoid distracting readers with too many different visual styles, Oatcake styles disclosure widgets similarly to preformatted text, code, and sample output blocks: the same background color, border, rounded corners, and padding. The difference is that instead of being preformatted or monospaced, disclosure widgets are collapsible.

For usability Oatcake gives a nice big click-target for opening and closing disclosure widgets (indicated by the background color) and changes the cursor to a "pointer" cursor when it's over this target area.

Tip: pre-opened disclosure widgets with the open attribute

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

Tip: mutually-exclusive disclosure widgets with the name attribute

You can create a mutually-exclusive group of disclosure widgets by giving them all the same name attribute. Only one disclosure widget with the same name can be open at the same time. If the user opens one of the named group of widgets it'll close any other that's already open. For example, this:

<details name="test">
  <summary>This is the first disclosure widget</summary>
  These are the first details.
</details>
<details name="test">
  <summary>This is the second disclosure widget</summary>
  These are the second details.
</details>
<details name="test">
  <summary>This is the third disclosure widget</summary>
  These are the third details.
</details>

…creates these:

This is the first disclosure widget These are the first details.
This is the second disclosure widget These are the second details.
This is the third disclosure widget These are the third details.

Edge case: raw text nodes in disclosure widgets

If your <details> contains only a single paragraph you can omit the <p> and it'll look the same. This:

<details>
  <summary>Material</summary>
  The picture frame is made of solid oak wood.
</details>

…renders like this:

Material The picture frame is made of solid oak wood.

Asides

You can create pull-quotes and call-out boxes with <aside>.

In-line with Oatcake's consistently unshowy nature, asides are styled the same as preformatted text blocks, code blocks and sample output blocks, and very similarly to disclosure widgets. The difference is that an aside's contents aren't preformatted, monospaced, or collapsible. It's just a box!

This:

<aside>
  <p>
    People ask me what I do for fun when I'm not at work.
    But I'm paid to do my hobby, so I never know what to answer.
  </p>
</aside>

…renders like this:

If your <aside> contains only a single paragraph you can omit the <p> and it'll look the same. This:

<aside>
  People ask me what I do for fun when I'm not at work.
  But I'm paid to do my hobby, so I never know what to answer.
</aside>

…renders like this:

Details: asides

Usage

<aside> (HTML Standard, MDN) is for content that is tangentially related to the content around the aside element, and which could be considered separate from that content. MDN defines them as for content that is only indirectly related to the document's main content.

The HTML standard mentions typographical effects like pull quotes as an example use-case for asides. These can be achieved by putting a <q> or <blockquote> in an <aside>. Here's the example that the standard gives:

He later joined a large company, continuing on the same work. I love my job. People ask me what I do for fun when I'm not at work. But I'm paid to do my hobby, so I never know what to answer. Some people wonder what they would do if they didn't have to work... but I know what I would do, because I was unemployed for a year, and I filled that time doing exactly what I do now.

Of course his work — or should that be hobby? — isn't his only passion. He also enjoys other pleasures.

MDN gives two examples of asides used for call-out boxes containing facts related to the main content:

Salamanders are a group of amphibians with a lizard-like appearance, including short legs and a tail in both larval and adult forms.

Several species of salamander inhabit the temperate rainforest of the Pacific Northwest, including the Ensatina, the Northwestern Salamander and the Rough-skinned Newt. Most salamanders are nocturnal, and hunt for insects, worms and other small creatures.

The Disney movie The Little Mermaid was first released to theatres in 1989.

More info about the movie…

The HTML standard gives a similar fact-box example with an <aside> containing an <h2> and a <p>background material on Switzerland in a much longer news story on Europe:

Tip: begin an aside with a text label

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

Tip: you can use an <hr> to split an aside into segments

Customization: aside colors

It was tempting to provide a variety of different colors for asides like other frameworks do. But documents with lots of different-colored 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 color schemes in future.

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

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

Now this:

<aside class="warning">
  <strong>Warning!</strong>
  Too many asides can overwhelm the reader.
</aside>

…will render like this:

Customization: aside design

You can change the design of asides by adding your own CSS. For example:

<style>
  aside {
    border-left: none;
    border-right: none;
    border-radius: 0;
    background-color: inherit;
    font-weight: 300;
  }
</style>

Now <aside>'s will look like this:

Oatcake styles <footer> elements with text in a muted color. This:

<footer>
  <strong>Posted:</strong> Wed 14 August 2019 ·
  <strong>Tags:</strong> <a href="#">HTML</a>,
  <a href="#">CSS</a>
</footer>

…renders like this:

All the inline elements work in footers, but elements that would normally stand out like links, highlights and code have a more muted style:

You can wrap the contents of a <footer> in a <small> to create a small-text footer:

Usage: footers

A <footer> (HTML Standard, MDN) represents a footer for its nearest containing <article>, <aside>, <nav>, <section> or the <body>. The HTML standard describes footers as typically containing information about the author, links to related documents, copyright data, etc. Examples given in the standard include navigation links, publication dates, author credits and contact information, links for editing, deleting and renaming an article, etc.

Footers don't need to be at the end of a section.

Horizontal rules

Finally, here's what an <hr> (a horizontal rule representing a thematic break like a change of scene or topic) looks like with Oatcake:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean condimentum vulputate turpis, in congue nisl tempor a.


Suspendisse potenti. Aliquam erat volutpat. Sed luctus felis et metus viverra eleifend.

Wrapping and horizontal scrollbars

Oatcake forces long words to wrap if necessary

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.

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.

You can insert <wbr> elements into words to tell the browser about good points to wrap the word. This example from the HTML Standard:

<p>So then she pointed at the tiger and screamed
"there<wbr>is<wbr>no<wbr>way<wbr>you<wbr>are<wbr>ever<wbr>going<wbr>to<wbr>catch<wbr>me"!</p>

…renders like this:

So then she pointed at the tiger and screamed "thereisnowayyouareevergoingtocatchme"!

Oatcake prevents wrapping within certain elements

Oatcake prevents any wrapping inside preformatted text (<pre>) blocks (including code and sample output blocks)—you don't want your code or other preformatted text being wrapped for you. So to prevent them from stretching out the width of the page or causing a page-level horizontal scrollbar, preformatted blocks get their own internal horizontal scrollbar if necessary:

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

A horizontal scrollbar is also used to prevent wrapping in long <summary>'s:

This is a really long <summary> element that will get a horizontal scrollbar rather than wrapping. These are the details.

Oatcake also prevents wrapping within certain inline elements: <kbd>'s, and within headings: <code> and <samp>. To avoid horizontal scrollbars don't put anything too long in any of these elements.

Tables

Tables get a pared-down look and the same colors and vertical rhythm as Oatcake uses for other elements. The design is blatantly appropriated from the tables in Tailwind CSS Typography, with added support for the <caption> element for table captions:

Table 1: an example table lifted from Tailwind CSS Typography, as styled by Oatcake.
Wrestler Origin Finisher
Bret "The Hitman" Hart Calgary, AB Sharpshooter
Stone Cold Steve Austin Austin, TX Stone Cold Stunner
Randy Savage Sarasota, FL Elbow Drop
Vader Boulder, CO Vader Bomb
Razor Ramon Chuluota, FL Razor's Edge

Forms

Won't fix! Oatcake is for styling articles, posts, etc: think Markdown files. It's not meant for creating apps, UIs, forms, etc.