# Authoring HTML Articles with the markdown Package

## Yihui Xie

### 2023-10-18

The R package markdown can be used to generate lightweight HTML documents with minimal default CSS styles. If you are not familiar with this package, you may read the introduction1 first to learn the basics. The HTML format is highly customizable if you know some CSS and JavaScript. This article demonstrates an HTML article format by introducing external CSS and JavaScript to the base format.

## 1. Get started

To write an HTML article, you may use the following metadata variables (`css` and `js`):2

    output:
      markdown::html_format:
        meta:
          css: ["default", "@xiee/utils/css/article.min.css"]
          js: ["@xiee/utils/js/sidenotes.min.js,appendix.min.js"]

The `default` CSS is the default style provided by this package. Beyond that, only the CSS file `article.css`3 is required.

- The JS file `sitenotes.js` is required only if you want to place certain elements on the left or right side, such as the table of contents (TOC), footnotes, and sidenotes.

- The JS file `appendix.js` is required only if you have an appendix in the article.

Since we are going to demonstrate all elements, we have loaded both JS files for this document.

## 2. The overall style

The maximum width of the article body is 800px. For larger screens, this means there will be extra space in the left/right margin, where we can place auxiliary information, such as the TOC and footnotes. On smaller screens, the side content will be collapsed into the body.

The article frontmatter, body, and optionally the appendix are placed in separate boxes.

The default typeface is sans-serif, and you can customize it by supplying an external CSS file (via the `css` meta variable) or just embedding CSS in the document body, e.g.,

    body {
      font-family: Palatino, "Book Antiqua", Georgia, serif;
      font-size: 1em;
    }

## 3. Side elements

The TOC and footnotes are automatically placed in the margin if space permits. You can also write arbitrary content in the margin via a fenced `Div`.

### 3.1 The TOC

The TOC is sticky on the left side as you scroll down the article. If you do not like this behavior, you may cancel it via CSS:

    #TOC {
      top: unset;
    }

### 3.2 Footnotes

Footnotes are moved to the right side. When you move your cursor over a footnote number in the body, the footnote will be moved next to your cursor. This can be convenient when you have multiple footnotes on a line, since you do not need to look for a specific footnote in the margin.

### 3.3 Arbitrary sidenotes

You can write anything in the margin by using a fenced `Div` with the classes `.side` and `.side-left` or `.side-right`.

Notice

Here is a note on the left side. Anything permitted by law is permitted here. Math? No problem!

$$e^{i\theta}=\sin{\theta}+i\cos{\theta}$$

When you have this sidenote “hammer”, I’m sure you will hit a lot of nails into the margin, even if you do not have to.

And here is a note on the right side. Seriously, we should let commonmark’s authors know that fenced `Div`s really deserve first-class support! They can make Markdown infinitely customizable.

    ::: {.side .side-left}
    **Anything** on the left.
    :::

    ::: {.side .side-right}
    _Anything_ on the right.
    :::

## 4. Body elements

Inside the article body, you can write a few special elements.

### 4.1 Full-width elements

When an element is wider than the article body, you can show it in its full width by enclosing the element in a fenced `Div` with the class `.fullwidth`, e.g.,

    ::: {.fullwidth}
    ![text](path/to/image)
    :::

If you use R Markdown, you can generate a wide plot or table from an R code chunk, e.g.,

    ::: {.fullwidth}
    ```{r}
    #| sunspots, echo=FALSE, fig.dim=c(14, 4),
    #| fig.cap='Monthly mean relative sunspot numbers from 1749 to 1983.'
    par(mar = c(4, 4, .1, .1), bg = 'lightgoldenrodyellow', fg = 'red', las = 1)
    plot(sunspots, col = 'red', panel.first = grid())
    ```
    :::

### 4.2 Left/right quotes

> Whenever you find that you are on the side of the majority, it is time to pause and reflect.

> —Mark Twain

Sometimes you may want to add a quote but do not want it to take the full width in the body. You may use a fenced `Div` with the class `.quote-left` or `.quote-right`.

Despite the class names, the content does not have to be a quote. If you do want a quote, just use the blockquote syntax `>`, e.g.,

    ::: {.quote-right}
    > This is a boring quote.
    >
    > ---Someone
    :::

### 4.3 Margin embedding

| mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1

You can embed elements on the left or right margin using a fenced `Div` with the class `.embed-left` or `.embed-right`. These elements will float to the left or right and exceed the margin by about 200px, which can save some space in the article body. You can use the extra space to explain the embedded element with text.

We have embedded a table of the first 4 rows of the `mtcars` data on the right margin. The table was generated via `knitr::kable()`.

## Appendix

The appendix starts with a heading that has the attribute `.appendix`, e.g., `## Appendix {.appendix}`.

## A. Technical notes

It’s quite simple to move an element into the margin using CSS. For example, the `.side-right` class in this article is roughly defined as:

    .side-right {
      width: 200px;
      float: right;
      margin-right: -200px
    }

That basically means the width of the element is 200px and it floats to the right. Now its right side will touch the right margin of its parent element (the article body). What we need to do next is move it further to the right by 200px (i.e., its width), which is done by the `-200px` right margin. Remember, a positive right margin in CSS moves an element to the left, and a negative right margin moves it to the right.

1. The package vignette: `vignette("intro", package = "markdown")` ↩

2. If you are curious about what the leading `@` characters mean in the values, please read the section “YAML metadata” in the introduction vignette of this package. ↩

3. The actual file extension is `.min.css`, which means a minified version of the `.css`. The CSS is minified to make it load faster. If you do not care, you can definitely use the `.css` extension. The same thing applies to `.min.js` vs `.js`. ↩