Design

A terminal is one of the most proven, durable text interfaces ever built. It has survived every design trend for fifty years - flat design, skeuomorphism, neumorphism, glassmorphism - because it never participated. It just renders text, and people have read it productively for decades.

term.css applies that philosophy to the web. Every decision below exists because we asked: "Would a terminal do this?" If the answer was no, we didn't do it. That's a design constraint, not a universal principle - the web is not a terminal, and we don't pretend it is. But strong constraints produce coherent systems, and coherence makes a system easier to learn and predict.

This document explains the tradeoffs.


Classless-First Design

term.css styles every standard HTML element without any classes. Write <table>, get a styled table. Write <blockquote>, get a styled blockquote. Write <nav>, get a tmux-like status bar.

This is the terminal philosophy applied to HTML. In a terminal, you don't add classes to your output. You write text, and the terminal renders it. term.css does the same: you write HTML, and the stylesheet renders it.

Classes exist for five optional components (.t-card, .t-grid, .t-badge, .t-callout, .t-table-bordered) that have no semantic HTML equivalent, plus four semantic color utilities (.t-error, .t-warn, .t-success, .t-info) that compose with badges and callouts. But the base experience - headings, paragraphs, lists, tables, code, forms, navigation - requires zero classes.

This has practical benefits:


Full-Width Layout

The conventional wisdom says body text should be 45-75 characters wide. This comes from Robert Bringhurst's The Elements of Typographic Style - a book about print. Print has fixed page widths. The web does not.

A terminal never imposes max-width: 80ch on itself. The user controls the window width. If they want 80 columns, they resize to 80 columns. If they want 120, they resize to 120. The content fills whatever space the user chose.

The same applies to browsers. People don't read websites full-screen on 2560px monitors. They have windows side-by-side, or they use a laptop where the screen is 1200-1400px wide. At those widths, full-width monospace text at 14px produces comfortable line lengths - without the framework making assumptions about what's comfortable.

What you gain by removing max-width:

The tradeoff

This is an honest trade: you give up a predictable reading measure for prose in exchange for density, simplicity, and user-controlled layout.

On a very wide window, long lines of prose can become harder to track. A max-width can act as protective ergonomics for those users.

We accept this tradeoff because term.css targets content where code and prose are interleaved. Code blocks benefit enormously from wider layouts - they wrap less, they're more readable, and you scroll less. For a technical article with ten code blocks, the width savings compound. The prose between those code blocks is usually short enough that line length doesn't become a problem.

If your content is pure long-form prose with no code, a constrained width may serve you better. term.css is optimized for the mixed case.


Single Font Size

Most CSS frameworks give you six heading sizes. Headings get progressively larger: h1 is 2.5rem, h2 is 2rem, down to h6 at 0.875rem. This is a print convention carried to the web.

Terminals don't have font sizes. Every character is the same size. A heading in a man page is differentiated by weight (bold) and whitespace, not by being 36px in a 14px document.

term.css follows this: 0.875rem (14px) everywhere. Headings use font-weight: 700. That's it.

Why this works:

The tradeoff

Font size is a powerful scanning channel. Larger headings establish document structure faster, create stronger entry points, and help distinguish sections at a glance.

Open a terminal and run man git. You can scan that document - the headings are bold, there's whitespace around them, and they're in uppercase by convention. Three signals, none requiring a larger font size. It works. But it works partly because the audience is practiced.

For a general audience, a modest size hierarchy likely helps more readers find what they're looking for, faster. For the audience term.css targets - people who are comfortable reading terminals - weight and whitespace are sufficient.


Monospace Everywhere

Most websites use a sans-serif font for body text and switch to monospace for code. term.css doesn't do this.

The tradeoff

For extended prose, proportional fonts usually win on raw readability. Proportional type packs word shapes more naturally and reduces horizontal sprawl.

term.css accepts a likely small readability tradeoff in prose in exchange for consistency, terminal authenticity, and better code/content harmony. On a page where prose and code are interleaved - which is the primary use case - the consistency of a single font family outweighs the marginal readability advantage of switching fonts mid-page.


Why JetBrains Mono

System monospace fonts vary wildly across platforms - Menlo on macOS, Consolas on Windows, DejaVu Sans Mono on Linux. They look different, they space differently, and they render at different sizes.

term.css bundles JetBrains Mono as WOFF2 web fonts so the rendering matches across every platform and browser:

We use font-display: swap to prevent invisible text while the font loads. The browser shows the system monospace fallback immediately and swaps in JetBrains Mono when it's ready. The layout doesn't shift because the fallback is also monospace.


Vertical Rhythm with lh Units

Most CSS frameworks use rem or em for spacing. term.css uses lh - a unit equal to the element's computed line-height. At line-height: 1.5 and font-size: 0.875rem, 1lh equals 1.3125rem (21px).

The line-height: 1.5 value is the WCAG 2.1 AA minimum for body text. It's also comfortable for monospace text, which needs slightly more leading than proportional text because every character has the same width.


No Border-Radius

Every CSS framework ships with border-radius. Buttons are rounded, cards have rounded corners, inputs have subtle curves. This is a GUI convention inherited from physical buttons.

Terminals are rectangular. Every element is a rectangle. There are no curves. term.css never sets border-radius - the browser default of 0 does the work.

Rounded corners say "this is a GUI widget." Sharp corners say "this is text in a box." For a terminal-aesthetic framework, the latter is more consistent.


Minimal Hover States

CSS frameworks typically add prominent :hover states - buttons change color, links get underlines or color shifts, cards lift with shadow. term.css takes a minimal approach:

Terminals don't have hover states. You navigate with the keyboard. When you move a cursor over text in a terminal, nothing changes.

The tradeoff

Hover states provide affordance, confirmation, and discoverability. Even terminal-comfortable users browse the web with a mouse sometimes.

The philosophy isn't "zero feedback" - it's "minimum effective feedback." The cursor change plus the link's existing visual distinction (color + underline) means the hover state doesn't need to do heavy lifting.

For interactive-heavy pages with many clickable elements, more prominent hover states would help discoverability. term.css is optimized for content-heavy pages where the primary interaction is reading, not clicking.


No Smooth Scrolling

scroll-behavior: smooth is a popular addition to CSS resets. term.css explicitly does not use it.

Terminals don't smooth-scroll. When you press Page Down, the content jumps. When you scroll with a mouse wheel, the content moves in discrete line increments. There's no easing, no animation, no physics.

Smooth scrolling is also an accessibility concern. Users with vestibular disorders can experience motion sickness from animated scrolling. The prefers-reduced-motion media query can disable it, but not using it in the first place is simpler and safer.


OKLCH Color System

term.css uses OKLCH for all colors. Every theme defines 10 variables in OKLCH format.

Lightning CSS generates fallbacks for older browsers automatically, so OKLCH in source doesn't mean OKLCH-only in output.


light-dark() for Themes

Each term.css theme is a single :root block using the CSS light-dark() function. Before this, each theme required four blocks: @media (prefers-color-scheme: dark), @media (prefers-color-scheme: light), :root[data-theme="dark"], and :root[data-theme="light"]. Every variable was duplicated four times.

light-dark() collapses this to one block. The browser picks the correct value based on color-scheme. A two-line override (color-scheme: light or color-scheme: dark) switches everything. The data-theme attribute does this for manual control.

This reduced every theme file from ~85 lines to ~32 lines. Thirteen themes times ~50 lines saved is ~650 lines of CSS eliminated with zero functionality loss.


Nav and Footer as tmux Bars

In a terminal multiplexer like tmux, the top and bottom of the screen have thin status bars. They show the session name, window list, time, and other metadata. They're dense, full-width, and use a surface color to differentiate from the content area.

term.css styles <nav> and <footer> the same way:


No Decorative Elements

term.css has no box shadows, gradients, background images, text shadows, backdrop filters, animations, transitions, or rounded corners. Each of these is a GUI convention. They exist to make web pages look like physical objects - cards that float above the page, buttons that press down, surfaces that blur what's behind them.

Terminals have none of this. They have text, borders made of characters, and colors.

The result is a design that loads fast, renders instantly, and never distracts from the content. There's nothing to animate, nothing to composite, nothing to blur. It's just text.


Who This Is For

term.css doesn't claim this approach works for every website. A marketing landing page needs visual hierarchy and emotional design. A dashboard needs data visualization. An e-commerce site needs trust signals and visual affordances that term.css deliberately omits.

term.css is for content-heavy technical sites: blogs, documentation, personal sites, technical writing. Places where the content is the interface and everything else is overhead.

The target audience is people who actively enjoy terminal-like presentation - who choose TUI tools over GUIs, who set their editor to monospace and don't look back, who feel more at home in a man page than a Medium article. Not every developer fits this description, and that's fine.

For a broader audience, some of these choices - same-size headings, full-width prose, monospace body text - may feel unfamiliar or less comfortable. That's a real cost. term.css prioritizes consistency, density, and terminal authenticity over conventional web typography. If that tradeoff doesn't work for your audience, it's the wrong tool.

Readable is not the same as universally optimal. term.css chooses a reading environment that is proven, coherent, and preferred by its target audience. It brings the terminal to the web - not because the web should be a terminal, but because for certain content and certain readers, the terminal's answers are still good ones.