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.
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.
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;
}
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
.
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;
}
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.
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.
:::
Inside the article body, you can write a few special 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}

:::
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())
```
:::
Whenever you find that you are on the side of the majority, it is time to pause and reflect.
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
:::
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()
.
The appendix starts with a heading that has the attribute .appendix
, e.g.,
## Appendix {.appendix}
.
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.
The package vignette: vignette("intro", package = "markdown")
↩
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. ↩
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
. ↩