Box Drawing With Unicode: Build Clean Text Boxes and Frames
Draw text boxes and frames with Unicode box-drawing characters for CLI output, ASCII diagrams, code comments and READMEs. Single vs double line styles explained.
Box Drawing With Unicode: Build Clean Text Boxes and Frames
A box around a line of text does something a bold font cannot do in plain text: it forces the eye to stop. In a 600-line source file, an email with no formatting, or a terminal scrolling past, a framed heading is the one thing that survives. The trick is that those frames are not drawn with slashes and dashes hammered together by hand. They are built from a small, purpose-made set of Unicode characters, and they only behave when two conditions hold.
What box-drawing characters actually are
Unicode reserves a block (U+2500 to U+257F) for box drawing. It contains exactly the pieces you need to build a frame: horizontal lines, vertical lines, four corners, and the T-junctions where a divider meets an edge. The corners and lines snap together into clean frames because every glyph is designed to start and end at the same point on the character cell, so a ┌ flows into a ─ flows into a ┐ with no gap.
A single-line frame uses these:
- Corners:
┌ ┐ └ ┘ - Edges:
─(horizontal),│(vertical) - Junctions:
├ ┤for a divider that ties into the left and right walls
There is nothing magic happening. ┌ is one character, ─ is one character, and laid in a row they read as a continuous line. The same logic gives you the double-line set (╔ ═ ╗ ║ ╚ ╝), the heavy set (┏ ━ ┓ ┃), and the rounded corners (╭ ╮ ╰ ╯) that keep the straight ─ │ edges but soften the four corners.
Why monospace is non-negotiable
Here is the part most people learn the hard way: these characters only line up in a monospace font. In a proportional font (the kind this paragraph is set in) an i is narrow and an m is wide, so two lines with the same number of characters end at different horizontal positions. A box built on the assumption that every character is one column wide collapses the moment the font stops honoring that assumption.
In a monospace font every glyph occupies one identical cell, so column 14 of line one sits directly above column 14 of line two, and the right wall of your box lands in a straight vertical line. That is why box drawing lives in terminals, code editors, <pre> blocks and fenced code blocks on GitHub, and falls apart the instant you paste it into a word processor or a chat client that renders with a proportional font. If your frame looks ragged, check the font before you blame the characters.
The one exception that catches everyone is wide characters. A Chinese, Japanese or fullwidth character such as 中 takes two terminal columns, not one, even in a monospace font. A naive generator that counts characters will leave the right edge of a mixed line ragged. A width-aware tool measures display width and doubles those columns so a line of 中文 and a line of English close on the same column.
A worked example: a labeled box
Say you want a section banner above a block of authentication code. You have a title, AUTH, and one body line, Token + refresh handlers. With a single style, a one-character pad, and a title divider, the output is:
┌──────────────────────────┐
│ AUTH │
├──────────────────────────┤
│ Token + refresh handlers │
└──────────────────────────┘
Read it from the pieces. The top is ┌, a run of ─, then ┐. Each text row is │, a space of padding, the content, padding to fill out to the widest line, then │. The title divider is ├, a matching run of ─, then ┤ so it ties cleanly into both walls. The bottom mirrors the top with └ ┘. The box auto-sizes to its widest line, Token + refresh handlers, so the shorter AUTH line is padded out to match and the right wall stays flush. You did not count a single column.
You can build the whole thing without hand-counting using the Text Box Drawing Generator: paste your lines, pick a style, add a title, and copy the result.
Single vs double, and where each fits
The style you pick is a volume control. Single (┌─┐) reads as a quiet divider; it is the default for a section comment that should organize a file without shouting. Double (╔═╗) is heavier and demands attention, which is exactly what you want around a warning. A ╔══╗ box around DO NOT MERGE — failing tests in a code review comment turns a sentence a reviewer might skim past into a block they cannot.
Rounded (╭─╮) keeps the same edges but softens the corners, which suits README headings and CLI welcome screens where sharp corners feel rigid. Heavy (┏━┓) sits between double and single in weight. All of the Unicode styles render identically in any monospace font that ships the box-drawing glyphs, so the choice is purely about how loud the frame should be.
One real constraint: rounded, double, and heavy corners are Unicode-only. If the output has to render somewhere that lacks box-drawing glyphs — an old log viewer, a legacy terminal, a system stuck on plain ASCII — fall back to the ASCII style (+--+ with | edges). It is uglier, but + and - and | exist everywhere, so the box never turns into garbage characters.
Where boxes earn their keep
I keep a bilingual cheat-sheet where some rows are Chinese and some are English, and for months I aligned the right edge by adding spaces by hand and re-counting every time I edited a line. The first time I pasted the whole thing into a width-aware box generator and watched the CJK rows and the English rows close on the same column with no manual nudging, I deleted the spreadsheet of spaces I had been maintaining. That is the moment the feature stops being cosmetic.
The common uses fall into a few buckets:
- CLI output. Welcome banners, status panels and summary blocks that group related lines so they read as one unit instead of a flat list.
- ASCII diagrams. Boxes are the nodes; you connect them with the same
─and│runs plus junctions to draw a simple architecture sketch that lives in a comment. - Code comments. A framed
// SECTIONbanner above a function gives a long file a table-of-contents feel and lets a reviewer jump to a block in a diff. - READMEs. A project name in a fenced code block wrapped in a rounded box renders the same on GitHub, in a terminal, and in a chat paste.
If you want to push past frames into full ASCII banners and figlet-style lettering, the ASCII Art Generator is the companion tool for the louder end of the spectrum.
The whole point is to stop counting columns. Once a box auto-sizes to its widest line and handles wide characters for you, drawing a clean frame is a paste-and-copy operation, and the result holds its shape anywhere a monospace font is rendering it.
Made by Toolora · Updated 2026-06-13