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.
Released October 2026.Upgrading took me five minutes.
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
- Preheat the oven
- Mix everything
- 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 |