Elements

Elements are classes that correspond to specific HTML tags: Paragraph is <p>, UnorderedList is <ul>, Link is <a> and Image is <img>. All of them live in chimera.elements and are named after what the tag is rather than its abbreviation.

Content

An element's content can be a string, a number, another element or a list of any of those. When an item is optional, put none in its place:

Paragraph("Plain text")
Paragraph({ "Mixed ", Strong("content"), " and numbers: ", 42 })
Paragraph({ "Hello", if signed_in then Strong(" again") else none })

Text is always escaped: Paragraph("<b>") shows the characters instead of bold text.

Text

Release notes

Version 2 is twice as fast and much smaller. Run seal update or read the changelog.

Upgrading took me five minutes.

Released October 2026.
const text = Div {
    h3("Release notes"),
    Paragraph({
        "Version 2 is ", Strong("twice as fast"), " and ", Emphasis("much"), " smaller. Run ",
        Code("seal update", "bash"), " or read the ", Link("changelog", "https://example.com"):new_tab(), ".",
    }),
    BlockQuote(Paragraph("Upgrading took me five minutes.")),
    Small("Released October 2026."),
}

Headings have six levels, from Heading.h1 to Heading.h6. Most pages destructure the ones they use with const .{ h1, h2 } = Heading.

Lists

  • Milk
  • Eggs
  • Flour
  1. Preheat the oven
  2. Mix everything
  3. Bake for 25 minutes
const lists = Div {
    UnorderedList({ "Milk", "Eggs", "Flour" }),
    OrderedList({ "Preheat the oven", "Mix everything", "Bake for 25 minutes" }),
}

Lists take strings or ListItems, and a list item can hold any content. OrderedList:start(5) starts the count at 5.

Tables

A table's columns are part of its type, and the analyzer checks every row against them. A misspelled or missing column is an error. row_for makes a function that builds rows from values in column order:

Cat Age Favorite toy
Nyla 3 Feather wand
Taz 14 Cardboard box
Oreo 1 Your shoelaces
const header = Table.header()
    :column("Cat")
    :column("Age")
    :column("Favorite toy")
const cat = Table.row_for(header)

const cats = Table(header)
    :row(cat("Nyla", 3, "Feather wand"))
    :row(cat("Taz", 14, "Cardboard box"))
    :row({ Cat = "Oreo", Age = 1, ["Favorite toy"] = "Your shoelaces" })
    :table_style({ striped = true })

Besides stripes, table_style can highlight the row under the pointer with hover = true. Pass bold_header = false for plain headings.

Details

Details shows a summary that opens to reveal the rest without any JavaScript:

Does chimera need JavaScript?

Only for the theme switcher, tabs and toggles. Pages read fine without it.

const faq = Details(
    "Does chimera need JavaScript?",
    Paragraph("Only for the theme switcher, tabs and toggles. Pages read fine without it.")
)

Forms

const signup = Form(Column({
    Label("Email", "email"),
    Input("email", "email")
        :id("email")
        :placeholder("you@example.com")
        :required(),
    Label("Plan", "plan"),
    Select("plan", { "Free", "Pro", "Team" }):id("plan"),
    Button("Sign up", "submit"),
}):gap("0.5rem"), "/signup", "post")

A static site has no server of its own to receive forms. Point action at a form service, or handle the submit event in a script.

Attributes, classes and events

Every element shares the same chainable methods for attributes, classes and events:

Link("Docs", "/docs")
    :id("docs-link")
    :attr("title", "Read the docs")
    :data("section", "top")              -- data-section="top"
    :add_style_class("button", "large")
    :on("click", "console.log('clicked')")

hidden() hides an element until a script shows it. When a chain needs a step that isn't a method, tap(function(element) ... end) runs your function and carries on.

For a tag chimera has no class for, use Tag: Tag("dialog", Paragraph("Sure?")).

All elements

Class Tag
Div, Section, Article, Aside, Main div section article aside main
Header, Footer, Navigation header footer nav
Heading h1–h6
Paragraph, Span, Strong, Emphasis, Small p span strong em small
BlockQuote, Preformatted blockquote pre
Link, Image, Figure, FigureCaption a img figure figcaption
LineBreak, HorizontalRule br hr
UnorderedList, OrderedList, ListItem ul ol li
Table table
Details, Summary details summary
Form, Label, Input, TextArea, Select, Option, Button form label input textarea select option button