Omarchy Typography Scale: How the Rem-Based System Works in Themes
Omarchy implements a rem-style typography scale where a configurable base-size in shell.toml serves as the root value, and the QML Style singleton calculates semantic tokens using fixed multipliers for proportional scaling.
Omarchy is an open-source desktop environment built with QML that prioritizes consistent theming across its shell components. The typography scale management system decouples configuration from rendering, allowing themes to establish a base font size that automatically propagates to all UI text elements while supporting per-token overrides for precise control.
Architecture of the Typography System
The typography architecture follows a two-layer approach: configuration happens in TOML files, while calculation and exposure occurs in QML singletons.
The Rem Root in shell.toml
Every Omarchy theme derives its typography from a single source of truth defined in shell.toml. The template file default/themed/shell.toml.tpl establishes the [font] section where base-size functions as the rem root:
[font]
base-size = 12
As documented in lines 101-106 of the template, this base size anchors the entire scale. The comment explicitly states: "base-size is the rem root for the type scale. Every Style.font. derives from it (e.g. body = base, subtitle ≈ base * 1.083, heading ≈ base * 1.333)."
QML Calculation Engine in Style.qml
The singleton shell/Commons/Style.qml ingests the configuration through applyShellValues (lines 20-24) and stores the base size in fontBaseSize. Two helper functions handle the mathematics:
function fontPx(mult) { return Math.max(1, Math.round(fontBaseSize * mult)) }
function fontToken(key, fallback) {
var v = fontOverrides[key]; var n = Number(v);
return (isFinite(n) && n > 0) ? Math.round(n) : fallback;
}
These functions appear at lines 84-95 in Style.qml. The fontPx function ensures no size drops below 1 pixel, while fontToken checks for user-defined overrides before falling back to calculated values.
Semantic Token Definitions
The Style singleton exposes eight semantic typography tokens as read-only properties. Each token uses fontToken with a multiplier-based fallback generated by fontPx. Lines 27-35 in Style.qml define the scale:
readonly property int caption: root.fontToken("caption", root.fontPx(0.833)) // 10
readonly property int bodySmall: root.fontToken("body-small", root.fontPx(0.917)) // 11
readonly property int body: root.fontToken("body", root.fontPx(1.0)) // 12
readonly property int subtitle: root.fontToken("subtitle", root.fontPx(1.083)) // 13
readonly property int title: root.fontToken("title", root.fontPx(1.167)) // 14
readonly property int heading: root.fontToken("heading", root.fontPx(1.333)) // 16
readonly property int display: root.fontToken("display", root.fontPx(2.0)) // 24
readonly property int displayLarge: root.fontToken("display-large",root.fontPx(2.333)) // 28
With a default base-size of 12, these multipliers produce pixel values ranging from 10px (caption) to 28px (displayLarge). Changing the base size automatically recalculates every token proportionally.
Override System for Granular Control
Themes can pin specific tokens without disrupting the proportional scale. By adding keys under [font] in shell.toml, you override individual values while preserving the rem calculations for others.
For example, to increase only the heading size while keeping the rest of the scale tied to the 12px base:
[font]
base-size = 12
heading = 20
The fontToken function detects the heading override and returns 20 directly, while body, title, and other tokens continue calculating from base-size * multiplier.
Scaling UI Elements with Typography
Omarchy optionally couples spacing and bar dimensions to the typography scale through the fontScale property. Defined at line 84 in Style.qml as:
readonly property real fontScale: Math.max(1 / 12, fontBaseSize / 12)
This normalization factor enables proportional scaling of non-text elements. When shell.toml contains:
[spacing]
scale-with-font = true
[bar]
scale-with-font = true
The shell multiplies gap sizes and panel dimensions by fontScale, ensuring that increasing the base font size grows the entire UI density appropriately.
Practical Configuration Examples
Changing Base Size via CLI
Use the built-in helper to inspect or modify the rem root:
# Check current base size
omarchy display text size
# Set to 14px (increases whole scale)
omarchy display text size 14
This command updates [font] base-size in ~/.config/omarchy/shell.toml. The change propagates instantly to all Style.font.* references throughout the QML shell.
Pinning Specific Tokens
Create a custom theme that keeps the default scale but enlarges headings:
[font]
base-size = 12
heading = 20
display = 32
Accessing Tokens in QML Components
UI elements consume the singleton directly:
Text {
text: "Window Title"
font.pixelSize: Style.font.title
font.family: Style.font.family
}
Disabling Proportional Scaling
To keep spacing and bar sizes fixed regardless of font changes:
[spacing]
scale-with-font = false
[bar]
scale-with-font = false
Summary
- Omarchy typography relies on a rem-style system configured in
shell.tomland implemented inshell/Commons/Style.qml. - The
base-sizekey serves as the root value; all semantic tokens calculate from it using fixed multipliers ranging from 0.833 (caption) to 2.333 (displayLarge). - The
fontTokenfunction supports per-token overrides, allowing themes to pin specific sizes while maintaining proportional scaling for the rest. - Typography scale changes can automatically adjust spacing and bar dimensions through the
fontScaleproperty whenscale-with-fontis enabled. - Modifications take effect immediately across the QML shell via the
Stylesingleton.
Frequently Asked Questions
What file controls the base typography size in Omarchy?
The [font] base-size key in shell.toml controls the root size. This file is typically generated from the template at default/themed/shell.toml.tpl and located at ~/.config/omarchy/shell.toml in active configurations. The CLI tool omarchy display text size provides a convenient interface to read and write this value.
How do I change only the heading size without affecting body text?
Add a heading key under the [font] section in your theme's shell.toml. Because the fontToken function checks for overrides before applying multipliers, specifying heading = 20 pins that token to 20px while body, subtitle, and other tokens continue calculating from the base-size rem root.
What is the default base font size in Omarchy themes?
The default base-size is 12 pixels, as defined in the template configuration. This produces a body text size of 12px, subtitle at 13px, title at 14px, and heading at 16px according to the multiplier ratios implemented in Style.qml.
How does typography scaling affect panel and window spacing?
When [spacing] scale-with-font or [bar] scale-with-font is set to true in shell.toml, the shell uses the fontScale property (calculated as fontBaseSize / 12) to multiply gap sizes, margins, and bar dimensions. This ensures that increasing the base font size proportionally increases UI whitespace, maintaining visual harmony across different density preferences.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →