Theme Settings

If you use the sbt plugin or the parsers, renderers or transformers from the laika-io module, each transformation is based on a theme that provides a set of default templates and styles for all output formats.

If you use a pure transformer from the laika-core module, there is no theme support as these transformers only process a single string as input and output.

This chapter documents Laika's only built-in theme, called Helium, and its configuration options.

The Helium Theme

The name of Laika's default theme reflects its lightweight nature as it is not based on any CSS or JavaScript libraries like Bootstrap, but instead only comes with a minimal set of hand-crafted CSS and JavaScript.

Helium includes default styles for web sites, EPUB and PDF documents, so you can generate a documentation site complete with a download page for e-book formats in one go.

The generated site is responsive and designed to work well on smaller devices.

Without any explicit theme configuration, Laika transformers run with the Helium theme and all its defaults, which is equivalent to the following configuration:

laikaTheme :=
val transformer = Transformer

If you are fine with your site and e-books looking exactly like Laika's documentation, including its choices for colors and fonts, you can skip the theme configuration step.

Otherwise you have the following options:

Helium Configuration API

Helium can be fully configured with its Scala API and does not require any configuration files.

The entry point for all configuration steps is always Helium.defaults to ensure there are sensible defaults in place for all the options you omit in your configuration.

For each configuration step you need to choose one of the four selectors, either all to specify options for all three output formats or site, epub or pdf to select a single format. Not all options are available for all formats, but the IDE's context help and the documentation below can guide you.

In the minimal example below we only specify some metadata for all formats as well as the navigation depth for EPUB and PDF:

val theme = Helium.defaults
    title = Some("Project Name"),
    language = Some("de"),

Laika also provides convenient constructors for some of the data types used frequently in its theme API. You can import laika.theme.Color._ for specifying colors with hex("ffaaff") or rgb(255, 0, 0) and laika.ast.LengthUnit._ for specifying sizes with px(12) or pt(9) or other available units. All configuration examples in this chapter assume these imports are in place.

The final call to build produces a ThemeProvider that can be passed to Laika's transformers or the laikaTheme sbt setting:

laikaTheme := theme
val transformer = Transformer


By default Laika includes three fonts in its published artifact so that they are ready to be embedded into EPUB or PDF documents. All these fonts are licensed under the Open Font License:

You can override these defaults by defining your own set of fonts.

This is an excerpt of Laika's default configuration as an example:

val latoURL = ",700"
val firaURL = 

      .embedResource(fontPath + "Lato/Lato-Regular.ttf")
    "Lato", FontWeight.Normal, FontStyle.Normal
      .embedResource(fontPath + "Lato/Lato-Bold.ttf"),
    "Lato", FontWeight.Bold, FontStyle.Normal
      .embedResource(fontPath + "FiraCode/FiraCode-Medium.otf")
    "Fira Code", FontWeight.Normal, FontStyle.Normal
      .embedResource(fontPath + "icofont/icofont.ttf")
    "IcoFont", FontWeight.Normal, FontStyle.Normal

The embedResource method picks the font to be embedded from the resource directory inside the jar, use emedFile to pick a font from the file system. Font embedding will be performed for EPUB and PDF output For the site you can use the webCSS method to link to the CSS containing the font-face definitions. It will automatically be included in the <head> sections of the generated HTML without the need to adjust the default templates.

Note that the use of the fontResources method replaces the defaults, it does not add them. If you want to use some of the built-in fonts you have to redefine them in this step. This ensures that no unused font resources will be embedded.

Additionally you can define the font families and font sizes for the site and e-books:

    body = "MyBodyFont",
    headlines = "MyHeadlineFont",
    code = "MyCodeFont"
    body = px(15),
    code = px(14),
    title = px(34),
    header2 = px(28),
    header3 = px(20),
    header4 = px(15),
    small = px(12)
    body = pt(10),
    code = pt(9),
    title = pt(24),
    header2 = pt(14),
    header3 = pt(12),
    header4 = pt(11),
    small = pt(8)

The example above specifies the three font families with the all selector, defining them for all output formats. Make sure the names match font resources defined in the previous step so that they are available for embedding.

The font sizes on the other hand will often be defined per format, the example above shows the definitions for the site and PDF output.


Helium let's you define two different color sets: The theme colors which are used for headlines, links, navigation and backgrounds as well as the syntax coloring scheme to be used for all code blocks.

Theme Colors

The following example overrides Laika's theme colors for all output formats:

    primary = hex("007c99"),
    primaryDark = hex("931813"),
    primaryLight = hex("095269"),
    primaryMedium = Color.hex("a7d4de"),
    primaryLight = Color.hex("ebf6f7"),
    text = Color.hex("5f5f5f")

The default theme colors, which are used for the documentation you are reading right now, are as follows:






In terms of getting the right contrast, the color combinations must support the following:

Syntax Highlighting

These settings are only relevant if you use Laika's built-in highlighters, in case you prefer to use a 3rd-party library like highlight.js you need to use their styling mechanism.

Laika's own syntax color scheme is built around sets of 10 colors, of which 5 are usually a set of grayish colors from light to dark with almost no saturation and a set of 5 colors which are supposed to be positioned around the color wheel.

The defaults for Laika's dark theme (as used on this site) are:











For the light scheme (used by default in EPUB and PDF output) they are:











They can be overridden per format or for all at once:

    base = ColorQuintet(
      hex("2a3236"), hex("8c878e"), hex("b2adb4"), 
      hex("bddcee"), hex("e8e8e8")
    wheel = ColorQuintet(
      hex("e28e93"), hex("ef9725"), hex("ffc66d"), 
      hex("7fb971"), hex("4dbed4")

For dark themes the base colors have to go from dark to light, for light themes the other way round.

The base colors are used as background color (the first), for comments, punctuation, identifiers and uncategorized spans, the wheel colors are used for the more significant types of code spans. Amongst others these are substitution references, annotations (1st color), keywords, escape sequences (2nd), attribute names, declaration names (3rd), all types of literals (4th), type names, tag names (5th), and several categories for other types of syntax, e.g. in text markup.


The configuration API allows to control a few aspects of the layout, like columns widths and line heights, that are the most like candidates for frequent adjustments.

These are the options for the site:

    contentWidth = px(860),
    navigationWidth = px(275),
    defaultBlockSpacing = px(10),
    defaultLineHeight = 1.5,
    anchorPlacement = AnchorPlacement.Left

The example shows the values for Helium's defaults. contentWidth is the maximum width of the main column, navigationWidth the width of the left navigation pane, defaultBlockSpacing the space between block elements in the main column and defaultLineHeight the line height of normal paragraphs.

anchorPlacement configures the little anchors for section headers that appear on mouse-over and allow to copy the URL. The default is Left, other options are Right or None.

If you need to tweak the layout beyond these options you can always include custom CSS files in your input directory that override additional styles.

For PDF output you can also define the page size and margins:

    pageWidth = cm(21),
    pageHeight = cm(29.7),
    marginTop = cm(1),
    marginRight = cm(2.5),
    marginBottom = cm(1),
    marginLeft = cm(2.5),
    defaultBlockSpacing = mm(3),
    defaultLineHeight = 1.5,
    keepTogetherDecoratedLines = 12

Again, the example shows the defaults. The properties for the page dimensions and margins should be self-explanatory, defaultBlockSpacing and defaultLineHeight are analogous to the site settings. Finally, keepTogetherDecoratedLines controls the number of lines for decorated blocks like code examples or callouts that should always be kept on the same page. With the above setting of 12 only blocks with more than 12 lines are allowed to be split across multiple pages.


Helium allows to define a small set of metadata that describes the output. In the generated site it will be used to populate the <head> section of the HTML output, for EPUB and PDF it will be used to embed the information into the generated files in a way that the respective readers understand.

Like many other options, you can specify metadata either with the all selector for all formats, or define them separately with the epub, pdf or site selectors.

    title = Some("Project Name"),
    description = Some("Fancy Hyperbole goes here"),
    identifier = Some("XSD-9876-XVT"),
    authors = Seq("Maria Green", "Helena Brown"),
    language = Some("de"),
    date = Some(,
    version = Some("2.3.4") 

When using the sbt plugin the title, description and version metadata will be pre-populated by the standard sbt settings name, description and version respectively. When using the library API no medata will be defined by default. It is recommended to always define the language and title as the minimum set of metadata.

This section describes the navigation options specific to the Helium theme. There are several other navigation features which are supported independent of the theme in use, like the option to centralize all definitions of external links. They are described in a dedicated Navigation chapter.

Top Navigation Bar

You can place a logo serving as home button into the middle of the top navigation bar, and a row of buttons or icons with links at the right corner. The left corner of the top bar is always reserved for the button to open or close the navigation.
    logo = Some(Logo.internal(
      path = Root / "image.png", 
      alt = Some("Homepage"), 
      title = Some("Home")
    links = Seq(
      IconLink.internal(Root / "",,
      ButtonLink.external("", "Text Link"),
      ButtonLink.external("", "Button Link")

The logo can be an external or internal link, in case of the latter, it is always a path from the perspective of Laika's virtual root, not a file system path. For the links to the right navigation bar you can choose between an IconLink with optional text, a ButtonLink with an optional icon, or a plain text link. Internal targets are again within the virtual path and will be validated.

With the default Helium settings the three link types from our code example render as shown below:

Screenshot of Helium Link Styles

Table of Contents

All three formats support an additional table of contents. This does not refer to the main navigation menu (the left pane of the Helium site and the respective reader's navigation bars in case of EPUB or PDF) which Helium will always produce. It is an optional, separate page that can be included in e-books or the site. For PDF format this is essential, as the reader's navigation would be lost if the user prints the PDF.

  .site.tableOfContent(title = "Contents", depth = 3)
  .pdf.tableOfContent(title = "Contents", depth = 4)
  .epub.tableOfContent(title = "Contents", depth = 4)

For all formats you can specify the title of the page and the navigation depth. The depth value includes all layers of the hierarchy, directories, documents and sections within documents.

In e-books the table of content will be inserted right after the (optional) cover image, for the site it will become a link at the top of the left navigation pane.

Finally, the navigation depth for the reader's navigation for EPUB and PDF can also be controlled:


The default for EPUB is just 2 levels as some readers like iBooks mess with the hierarchy of navigation items when using more than 2 levels. If you increase this setting make sure you verify it's looking good in the targeted readers.

A Helium site contains a page navigation pane on the right side on bigger screens. At the bottom of that pane a link to the source of the current page will be inserted if you provide the base URL to link to:

    text = "Source for this Page", 
    baseURL = ""


You can specify one or more favicons for your site:

    Favicon.internal(Root / "favicon32x32.png", sizes = "32x32"),
    Favicon.internal(Root / "favicon64x64.png", sizes = "64x64")

Download Page

A page offering generated EPUB and PDF files with the same content and structure as the site for download can be added via Helium configuration:

    title = "Documentation Downloads",
    description = Some("Optional Text Below Title"),
    downloadPath = Root / "downloads",
    includeEPUB = true,
    includePDF = true

The last three properties in the example above are equivalent to the defaults and can be omitted.

If you configure Cover Images for E-books they will be used to display thumbnails above the download links.

Website Landing Page

By default the generated site does not have a dedicated landing page. The site's entry point will simply be the or README.rst document (if present), rendered with the default template, meaning with the top and left navigation bars. If you don't mind that users arrive straight at the content pages, you can stick with the defaults.

Alternatively Helium offers a dedicated landing page tailored for software documentation sites. This is the full set of content options available:

    logo = Some(Image()),
    title = Some("Project Name"),
    subtitle = Some("Fancy Hyperbole Goes Here"),
    latestReleases = Seq(
      ReleaseInfo("Latest Stable Release", "2.3.5"),
      ReleaseInfo("Latest Milestone Release", "2.4.0-M2")
    license = Some("MIT"),
    documentationLinks = Seq(
      TextLink.internal(Root / "", "Doc 1"),
      TextLink.internal(Root / "", "Doc 2")
    projectLinks = Seq(
      IconLink.internal(Root / "", HeliumIcon.demo),
      ButtonLink.external("", "Somewhere")
    teasers = Seq(
      Teaser("Teaser 1", "Description 1"),
      Teaser("Teaser 2", "Description 2"),
      Teaser("Teaser 3", "Description 3")

Every single content item shown above is optional, but of course the page would look strange if you omit them all.

The diagram below shows the positions of these items on the page:

Configurable Areas on the Landing Page

The left side of the header introduces the project, ideally you would choose at least one of the three options (logo, title and subtitle). In the case of Laika's site for example, the title is omitted as the project name is already part of the logo.

On the right side, the latest release info usually points to one or two releases, the latter if there is also a milestone available. The panel for documentation links can be any links right into the content of your site, like Getting Started pages, tables of contents, and hopefully also a link to the API documentation.

The project links below can be any set of additional links, like to GitHub, Twitter or your chat. Like with the top navigation bar of the main page, you can choose between an IconLink with optional text, a ButtonLink with an optional icon, or a plain TextLink. Internal targets are again within the virtual path and will be validated.

The right side of the header is the only section of the landing page containing links. This is a deliberate departure from the often confusing entry points of other software documentations sites where relevant links are scattered all over the place.

Finally a set of teasers which are quite common on landing page can be defined for the white area below the header.

Additionally or alternatively you can also add a regular markup document called landing-page.<suffix> to one of your input directories and its content will be inserted at the bottom of this page. This is in case you want to stick with the traditional approach of some sites, which give you 'Getting Started' style content right on the start page. It can also be used to list adopters, provide a feature overview or links to presentations or videos.

Cover Images for E-books

You can include cover images for EPUB and PDF files. They will also be used to display little thumbnails on the download page.

  .epub.coverImages(CoverImage(Root / "cover.png"))
  .pdf.coverImages(CoverImage(Root / "cover.png"))

See Supported Document Types for a list of supported image formats.

Auto-Linking CSS & JS Files

If all the configuration options shown above don't give you enough flexibility, you can always include additional CSS and JavaScript files to tweak the site's look & feel.

You can examine the CSS generated by Helium and override individual style declarations by placing them anywhere in a CSS file inside one of your input directories. They will always be included in a way that they have higher precedence than the theme's styles.

If you want to prevent Helium from scanning all input directories for CSS files, you can alternatively specify one or more directories explicitly:

  .site.autoLinkCSS(Root / "my-css")
  .site.autoLinkJS(Root / "my-js")

Like everything in Laika, the paths are virtual and not file system paths, so they must point to somewhere within the configured inputs. .

The use of JavaScript in EPUB templates is not yet supported, but planned for version 0.17.

The reason is that EPUB requires that HTML pages containing scripts are marked as such in the metadata files that list the content of the EPUB, which means that Laika would first need to introduce configuration support for authors to specify which templates contain scripts.

Custom Templates

In cases where even custom CSS files do not give you the level of control you need, the final step (apart from creating your own theme), would be to create your own default templates.

As a starting point you can copy and modify Helium's default templates, which you can find here. Or you can start from scratch and only use the existing templates as an inspiration.

Any default templates placed into the user input directories will override the corresponding templates with the same path from a theme. This way you can always customize just one of the templates, while keeping the rest as provided by the theme.

For an introduction to the template syntax, template file names and more details see Creating Templates.