Skip to content

Markout Reference

Complete syntax reference for the Markout markup language.

Content Rows

Lines starting with | define UI rows:

| Plain text
| Text with {input:binding}
| {button:action "Label" style}

Component Syntax

{type:binding "label" style attribute1 attribute2}
PartRequiredDescription
typeYesComponent type (input, button, label, etc.)
bindingNoState key (after :)
"label"NoDisplay text (quoted)
styleNoVisual style keyword
AttributesNocol-N, validate:, animate:, route:, fetch:, popover:

Component Types

TypeHTML OutputState Binding
input<input type="text">Read/write text
password<input type="password">Read/write text
button<button>Action name (click)
checkbox<input type="checkbox">Boolean toggle
radio<input type="radio">Boolean
select<select>Read/write text
textarea<textarea>Read/write text
label<span>Read-only display
pill<span class="mc-pill">Read-only display (rounded tag)
badge<span class="mc-badge">Read-only display (counter)
progress<div class="mc-progress">Numeric 0-100 (bar width)
sparkline<svg>Comma-separated values (chart)
spacer<span>Layout mode (end, evenly, col-N-end)
link<a>Navigation
image<img>Display
divider<hr>None

Containers

@tag config
| content...
@end tag
DirectiveRenders As
@card<div class="mc-card">
@form<form>
@section<section>
@nav<nav>
@header<header>
@footer<footer>
@main<main>
@aside<aside>
@columns<div> with CSS columns
@editorRich text editor (WASM-powered)

Editor

@editor feature1 feature2 ... bind:stateKey
@end editor

Features are opt-in. Only declared features are available in the toolbar, keyboard shortcuts, and content. Undeclared formatting is stripped from pasted text.

FeatureToolbarShortcut
boldBCtrl+B
italicICtrl+I
underlineUCtrl+U
strikethroughS
code<>Ctrl+`
headingH
list
ordered-list1.
quote"
code-block{}
link🔗Ctrl+K
hr

bind:key syncs the editor's markdown content to an Outconceive state key.

Container Config

Key-value pairs separated by spaces:

KeyExampleCSS Output
paddingpadding:24padding: 24px
max-widthmax-width:600pxmax-width: 600px
widthwidth:50%width: 50%
heightheight:400pxheight: 400px; overflow: hidden
colscols:3column-count: 3
gapgap:16column-gap: 16px; gap: 16px

Styles

KeywordCSS Class
primarymc-primary
secondarymc-secondary
dangermc-danger
warningmc-warning
infomc-info
outlinemc-outline
ghostmc-ghost
darkmc-dark
lightmc-light

Column Sizing

SyntaxWidth
col-650% (6/12)
col-433.3% (4/12)
col-3[5]60% (3/5)
sm:col-650% at 576px+
md:col-433.3% at 768px+
lg:col-325% at 992px+
xl:col-216.7% at 1200px+

Validation Rules

RuleDescription
requiredNon-empty
emailValid email format
numberNumeric value
urlValid URL
min:NMinimum N characters
max:NMaximum N characters
pattern:regexCustom regex match

Animations

NameEffect
fadeOpacity 0→1
slideSlide from left
slide-upSlide from bottom
scaleScale 0.9→1
bounceElastic scale
pulseContinuous opacity pulse
shakeHorizontal shake
glowContinuous shadow pulse

Spacer Modes

SyntaxEffect
{spacer:end}flex:1 — push remaining items to the right
{spacer:evenly}flex:1 — equal distribution (place between items)
{spacer:col-N}Fixed N/12 width gap
{spacer:col-N-end}Fill up to end of column N (tab stop alignment)

Popover

Add to any component for a hover tooltip:

{button:info "Help" popover:"Detailed help text"}

Parametric Layout

@parametric is a constraint-based layout container. Components position themselves relative to each other by name instead of grid columns.

@parametric
| {label:title "Dashboard"}
| {input:search center-x:title gap-y:16}
| {button:go "Search" primary right:search gap-x:8 center-y:search}
| {divider:line left:title right:go gap-y:24:go}
@end parametric

Each component's binding name (e.g., search) becomes its identity for constraint references.

Edge Alignment

ConstraintMeaning
left:refMy left edge = ref's left edge
right:refMy right edge = ref's right edge
top:refMy top edge = ref's top edge
bottom:refMy bottom edge = ref's bottom edge

When both left: and right: are set, the element stretches between them.

Center Alignment

ConstraintMeaning
center-x:refMy horizontal center = ref's horizontal center
center-y:refMy vertical center = ref's vertical center

Spacing (Gap)

ConstraintMeaning
gap-x:N:refN units to the right of ref
gap-y:N:refN units below ref
gap-x:NN units right of the nearest referenced element
gap-y:NN units below the nearest referenced element

Supports px (default), rem, em, and %:

| {image:b center-y:a gap-x:1rem:a}
| {label:c left:a gap-y:2em:b}

Sizing

ConstraintMeaning
width:refMy width = ref's width
height:refMy height = ref's height

Distribution

ConstraintMeaning
distribute-x:a:bCenter horizontally between a and b
distribute-y:a:bCenter vertically between a and b

How It Works

The first element with no constraints anchors at (0, 0). The Rust solver builds a dependency graph, topologically sorts it, and computes absolute positions for each element. The container auto-sizes to the bounding box of all elements. No runtime DOM measurement — everything is computed in WASM.

Special Directives

DirectiveDescription
@each key / @end eachRepeat template for each list item
@define name / @end defineDefine reusable template
@use name scope=prefixInstantiate template with scoped state
@parametric / @end parametricConstraint-based layout container

Released under the MIT License.