---
title: Turn an Ordered List on an HTML Page into a Collapsible FAQ List
date: '2021-10-28'
slug: faq-list
customCSS: ["utils@latest/faq.css"]
customJS: ["utils@latest/faq.js"]
---

Last year my colleague Christophe suggested that I add a table of contents and
anchor links on [the FAQ page of **tinytex**](https://yihui.org/tinytex/faq/)
([#94](https://github.com/yihui/yihui.org/issues/94),
[#95](https://github.com/yihui/yihui.org/issues/95)), which were definitely good
ideas. This week I took some time to reorganize my [miscellaneous JavaScript
code](https://github.com/yihui/misc.js), learned a little bit about NPM, and
published my scripts as [a Node
package](https://www.npmjs.com/package/@xiee/utils).[^1]

[^1]: This is not really a normal Node.js package. Most scripts are
    self-contained and are for side-effects in browser only. My motivation of
    publishing them anyway is to be able to use jsdelivr.com.

During this process, I wrote another little script to convert an ordered list on
an HTML page into a collapsible FAQ list. Basically, all you need to do is load
the script and stylesheet in your HTML or (R) Markdown document:

``` html
<link href="https://cdn.jsdelivr.net/npm/@xiee/utils/css/faq.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/@xiee/utils/js/faq.min.js" defer></script>
```

## Demo

Below is a quick demo:

1.  **What's the answer to life, the universe, and everything?**

    [42.](https://en.wikipedia.org/wiki/42_(number)#The_Hitchhiker's_Guide_to_the_Galaxy)

2.  **Who is Frida Gomam?**

    This clever lady:
    <https://www.reddit.com/r/funny/comments/9u22lb/frida_gomam/>

3.  **How to quit vim?**

    But why?

You can click on each question to reveal or hide its answer. Or click on the ⊕
button at the top-right to expand/collapse all answers. When you mouse over a
question, its anchor link (denoted by the `#` symbol) will become visible at the
end. You can use the link to point to a specific FAQ item, e.g.,
<https://yihui.org/tinytex/faq/#faq-3>.

## Selection of ordered lists

This JS program looks for all ordered lists (`<ol>`) on a page, and turns a list
into an FAQ list if it satisfies the following conditions:

1.  It either has no `class` attribute, or contains an `faq-list` class;
2.  Each of its child element contains at least two child elements (the first
    one is the question, and the rest is the answer);
3.  It is a direct child of `<div>`, `<main>`, `<section>`, or `<article>`, and
    the container does not have the `footnotes` class (to avoid accidentally
    converting footnote items into FAQ lists).

For example, the above ordered list was ignored by this program because its
child items only contain one child.

## Styling

A class `faq-list` will be added onto the `<ol>` element, and you can style the
list using CSS rules if you are not satisfied with the default minimal styling.
For example, since it is Halloween, let's make the list a little spooky:

``` css
<style type="text/css">
.faq-list > li {
  border-color: ghostwhite;
}
.faq-list > li > :first-child, .faq-button {
  background: darkorange;
  color: ghostwhite;
  font-family: Papyrus, fantasy;
}
</style>
```

<script>
(() => {
  const s = document.currentScript;
  s.insertAdjacentHTML('afterend', s.previousElementSibling.innerText);
})();
</script>

Then you get an orange theme like this:

![A spooky FAQ list](https://user-images.githubusercontent.com/163582/139451452-255564fa-78a1-4403-ad61-d869960f0807.png)

## Related work

This JS application was inspired by [Jiena's awesome **faq**
package](https://github.com/jienagu/faq), which is an HTML widget package that
allows you to create an FAQ list from a data frame in R. You can use it in
either R Markdown or Shiny apps. Thanks Jiena![^2]

[^2]: Please feel free to visit Omaha again, and I'm ready to cook at any time!

Please feel free to let me know if you have any suggestions or feedback. You can
either leave a comment below or [file an issue to
GitHub](https://github.com/yihui/misc.js).

