# Cell metrics

How big one glyph cell is, how it stays sharp on every screen, and how to change its size and font.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. The asciicn agent skill, for building any ASCII effect on the engine, is at [/.well-known/agent-skills/asciicn/SKILL.md](/.well-known/agent-skills/asciicn/SKILL.md).

Every renderer lays glyphs on a grid of cells. A cell is as tall as one line of text and as wide as one glyph advance in the font, so it is about twice as tall as it is wide, unless you ask for [square cells](#square-cells). Its height sets the grain: small cells read as texture, large ones as type.



## Setting the size [#setting-the-size]

`cell` is always the cell **height** in CSS pixels. It comes from the `--ascii-cell` variable, 12px by default. Change it for the whole site, or for one section on a wrapper:

```css
.pricing-hero {
  --ascii-cell: 16px;
}
```

To size one component, pass `cell`. It wins over the variable:

```tsx
<AsciiImage src="/portrait.jpg" cell={8} />
```

The font size is the cell height divided by 1.2, the line height glyphs are set at, so a 12px cell sets glyphs at 10px. The width follows the font: most monospace fonts advance 0.6em, which makes a 12px cell 6px wide.

## Square cells [#square-cells]

Pass `square` to make cells as wide as they are tall. `cell` then sets both sides, so `cell={7}` is a 7x7 px cell and about 200 columns across a 1440px screen.

```tsx
<AsciiShader field={FIELD} charset="dots" square cell={7} />
```

Square cells are for ramps of round glyphs, above all `dots`: the dots lie on an even halftone lattice instead of rows twice as far apart as their columns. Text glyphs sit centred with room around them. Braille and quadrants stretch to fill the square, so leave `square` off for them. Fields don't change: `res.x / res.y` is still the box's true aspect ratio, and `res.y` still counts sample rows. Both `AsciiShader` and `AsciiGrid` take `square`, and `measureCell({ square: true })` returns the square metrics.

## The font [#the-font]

Glyphs that come from a font use `--ascii-font`, a monospace stack starting at `ui-monospace`. Set it to your own:

```css
:root {
  --ascii-font: "JetBrains Mono", ui-monospace, monospace;
}
```

`measureCell` measures the font's real advance once per family and measures again when a web font finishes loading, so the grid never drifts out of step with the glyphs. Blocks, shades, quadrants, Braille, dots and box lines don't come from the font at all: they are drawn from shapes, so they look the same whichever font you pick.

## Sharp on every screen [#sharp-on-every-screen]

A glyph edge that falls between two device pixels turns into a blurry grey line. To avoid it, `measureCell` rounds both sides of the cell to whole device pixels: at 2× density, a 12px cell is exactly 24 device pixels tall, and its width rounds to the nearest whole device pixel. The canvas is sized in whole cells, and block edges inside a cell snap to whole pixels too.

The cost is that the CSS size of a cell can be fractional (6.5px at 2×, for example). The grid still covers the box; the last column or row is clipped by the component.

```ts
const metrics = measureCell({ cell: 12, font: readFont(element) });
// { width: 6, height: 12, deviceWidth: 12, deviceHeight: 24, dpr: 2, fontSize: 10, font: "…" }

const { columns, rows } = gridSize(metrics, box.width, box.height);
```

## Reading the tokens [#reading-the-tokens]

| Helper              | Returns                                                 |
| ------------------- | ------------------------------------------------------- |
| `readCell(el)`      | `--ascii-cell` on an element in pixels, or 12           |
| `readFont(el)`      | `--ascii-font` on an element, or the default stack      |
| `readGlow(el)`      | `--ascii-glow` (or the older `--ascii-bloom`), 0 to 1   |
| `measureCell(opts)` | `CellMetrics` for a height, font and device pixel ratio |
| `gridSize(m, w, h)` | Whole columns and rows that cover a box                 |

`readAsciiCell` is the same as `readCell`, kept under its older name.

## Picking a size [#picking-a-size]

* 8 to 10px for dense backgrounds and photos, where you want the picture first.
* 12px for most components. Glyphs are still legible, so the ASCII reads as text.
* 16px and up for hero text, logos and anything that should look like a terminal at arm's length.

Braille and quadrants carry 8 and 4 samples per cell, so they keep detail at larger cells than ramps do.