My Org CSS
A Demo
Table of Contents
This is my custom stylesheet for Org-exported HTML pages. It is built on top of Gong's Org CSS.
The goal is to create clean HTML pages for both screen viewing and PDF printing. Gong's CSS provides a great starting point, and I have been using it for over five years. Over time, however, I have developed several opinions on how to "improve" it in my preferred way, which then motivates this project.
Table of Contents
General Considerations
I have always appreciated the elegance of serif fonts, especially their exquisite details at larger sizes. I also value the clean look and excellent readability of sans-serif fonts, particularly in smaller text. Considering these preferences, I use the following font settings:
- Lora (a serif font) for titles and headlines.
- Fira Sans (a sans-serif font) for the main text[1].
- Fira Code (a monospace font) for code and code-like elements.
I also use a variety of colors to make the page look vivid and fresh:
- Black
#00000
for the title and subtitle. - Blue
#527d9a
for headlines, matching the color of hyperlinks. - Magenta
#d33682
for inline code, consistent with the Solarized palette I use in Org mode.
In the next section, I will provide CSS snippets to achieve these effects, along with a few other specific tweaks.
CSS Snippets
Grouped by elements or topics.
Blockquote
Use italic style.
blockquote { font-style: italic; }
Body
Set font; set body width to 950 px if possible.
body { font-family: Fira Sans, sans-serif; } @media screen and (min-width: 960px) { body { width: 950px; } }
Code
Set color for inline code; remove the border and padding for inline code; Set font for all code-like elements[2].
:not(pre) > code { color: #d33682; border: initial; padding: initial; } code, kbd, pre, samp { font-family: Fira Code, monospace; }
Headlines
Set font; set color.
h1, h2, h3, h4, h5, h6 { font-family: Lora, serif; color: #527d9a; }
Home and up links
Align left.
#org-div-home-and-up { text-align: left; }
Preamble and Postamble
Gray out.
.status { color: #888888; }
Reference list
Increase the lineskip to match normal text[3].
.csl-entry { margin: 1em auto; }
Section symbol
Add the section sign "ยง".
h2::before, h3::before, h4::before, h5::before, h6::before { content: "§ "; margin-right: 0.4em; font-size: 70%; vertical-align: top; }
Summary
Set cursor.
summary { cursor: pointer; }
Table of Contents
Set font to match headlines.
#table-of-contents { font-family: Lora, serif; }
Title and subtitle
Use small caps; align left; smaller size for the subtitle.
.title { font-variant-caps: small-caps; text-align: left; } .subtitle { font-size: 60%; }
To-do keywords
Consistent with the appearance in my Org mode.
.todo { background-color: inherit; /* disable default background-color */ } .done { background-color: inherit; /* disable default background-color */ } .todo.TODO { color: #dc322f; /* solarized red */ } .todo.NEXT{ color: #d33682; /* solarized magenta */ } .todo.FOLLOW{ color: #268bd2; /* solarized blue */ } .todo.WAITING{ color: #2aa198; /* solarized cyan */ } .todo.INACTIVE{ color: #6c71c4; /* solarized violet */ } .done.CANCELLED{ color: #859900; /* solarized green */ } .done.DONE{ color: #859900; /* solarized green */ }
TODO Appendix: Animate the Details Element
Add smooth transitions for collapsing and expanding of <details>
and
<summary>
elements.
CANCELLED Appendix: Copy Button for Code Blocks
Add a button for copying the content of code blocks.
DONE Appendix: Display Language Name in Source Blocks
Extend Gong's CSS to support more lanauges.
.org-src-container>pre.src-conf:before { content: "Conf" } .org-src-container>pre.src-elisp:before { content: "Emacs Lisp" } .org-src-container>pre.src-toml:before { content: "TOML" }
DONE Appendix: Hide the Table of Contents
Use JS to hide the default TOC in the title. In particular, wrap the whole TOC (if persent) within the title via a detail/summary pair.
// Hide TOC document.addEventListener('DOMContentLoaded', function () { // Get the title and TOC elements const title = document.querySelector('h1.title'); const toc = document.querySelector('#table-of-contents'); const titleParent = title.parentNode // Only proceed if both elements are found if (title && toc) { // Create the needed elements const details = document.createElement('details'); const summary = document.createElement('summary'); // Move the title inside the summary (preserving events, properties etc.) summary.appendChild(title); // Assemble the structure details.appendChild(summary); details.appendChild(toc); // Insert details as the first child of the original parent of title. titleParent.insertBefore(details, titleParent.firstChild); // title and toc have now been moved into 'details', no need to remove originals } });
Usage. Save the above snippet as ./hide-toc.js
, and insert it in the
exported HTML head via adding a line
#+HTML_HEAD_EXTRA: <script defer src="hide-toc.js"></script>
DONE Appendix: Related Emacs Settings
Below is my configuring snippet related to org exporting for this project.
(use-package org ;; org export general options :config (setq org-export-default-language "en") (setq org-export-with-section-numbers nil) (setq org-export-with-sub-superscripts '{}) (setq org-export-with-toc 4) ) (use-package org ;; org HTML export options :config (setq org-html-checkbox-type 'unicode) (setq org-html-doctype "html5") (setq org-html-footnote-format "<sup>[%s]</sup>") (setq org-html-head-include-default-style nil) (setq org-html-htmlize-output-type 'inline-css) (setq org-html-metadata-timestamp-format "%b %d, %a, %Y") (setq org-html-postamble "\ <p class=\"author\">Author: %a</p> <p class=\"date\">Exported: %T</p>") (setq org-html-preamble "\ <p class=\"date\">Created: %d</p> <p class=\"date\">Modified: %C</p>") (setq org-html-self-link-headlines t) (setq org-html5-fancy t) )
Footnotes:
For specific pages (e.g., math-related posts), I may use Lora for the main text to enhance the professional feelings. This can be done by setting export options on a per-file basis by adding a line
#+HTML_HEAD_EXTRA: <style>body {font-family: Lora, serif;}</style>