Help us shape the future of Go! Take the 2026 Go Developer Survey

box

package module
v3.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: MIT Imports: 8 Imported by: 0

README

Box CLI Maker

logo

Go Reference Go GitHub release Mentioned in Awesome Go

Box CLI Maker is a Go library for rendering highly customizable boxes in the terminal.

Used by kubernetes logo kubernetes/minikube · Featured in Golang Weekly (×3) and GitHub's Release Radar

a weather card rendered with Box CLI Maker

Features

  • 9 built‑in styles (Single, Double, Round, Bold, SingleDouble, DoubleSingle, Classic, Hidden, Block)
  • Custom glyphs for all corners and edges
  • Title positions: Inside, Top, Bottom
  • Title and Content alignment: Left, Center, Right
  • Inner padding and outer margin
  • Optional content wrapping with WrapContent and WrapLimit
  • Color support with:
    • First 16 ANSI color names
    • #RGB, #RRGGBB, rgb:RRRR/GGGG/BBBB, rgba:RRRR/GGGG/BBBB/AAAA
    • Automatic conversion to the terminal's color capability; suppressed for NO_COLOR and piped output
  • Unicode and emoji support with proper width handling
  • Derived styles with Copy() for building box families from a shared base
  • Explicit errors from Render, plus MustRender for panic‑on‑error

Installation

go get github.com/box-cli-maker/box-cli-maker/v3

Quick Start

package main

import (
    "fmt"

    box "github.com/box-cli-maker/box-cli-maker/v3"
)

func main() {
    b := box.NewBox().
        Style(box.Single).  // single-line border
        Padding(2, 1).      // inner padding: x (horizontal), y (vertical)
        Margin(3, 1).       // outer margin: x (horizontal), y (vertical)
        TitlePosition(box.Top).
        ContentAlign(box.Center).
        Color(box.Cyan).
        TitleColor(box.BrightYellow)

    out, err := b.Render("Box CLI Maker", "Render highly customizable boxes\nin the terminal")
    if err != nil {
        panic(err)
    }
    fmt.Println(out)
}

NewBox constructs a box with the default Single style.
Configure it via fluent methods, then call Render (or MustRender) to get the box as a string.

API Overview

Construction
b := box.NewBox()

You can clone a configured box and tweak it:

base := box.NewBox().
        Style(box.Single).
        Padding(2, 1).
        ContentAlign(box.Left)

info := base.Copy().Color(box.Green)
warn := base.Copy().Color(box.Yellow)
Styles

Select a built‑in style:

b.Style(box.Double)
Styles showcase
box.Single

single

box.SingleDouble

single double

box.Double

double

box.DoubleSingle

double single

box.Bold

bold

box.Round

round

box.Hidden

hidden

box.Classic

classic

box.Block

block

You can override any glyph after choosing a style:

b.Style(box.Single).
  TopLeft("+").
  TopRight("+").
  BottomLeft("+").
  BottomRight("+").
  Horizontal("-").
  Vertical("|")
Titles and Alignment

Title position:

TitlePosition decides where the title goes: inside the box, on the top border, or on the bottom border. The default is box.Inside.

b.TitlePosition(box.Inside)
b.TitlePosition(box.Top)
b.TitlePosition(box.Bottom)
Title Position showcase
box.Inside

single

box.Top

top

box.Bottom

bottom

Title alignment:

TitleAlign decides where the title sits: across the box for Inside titles, or along the border for Top and Bottom titles. It works together with TitlePosition, and the two can be called in any order:

b.TitlePosition(box.Top).TitleAlign(box.Center) // title centered on the top border

The values are box.Left, box.Center, and box.Right. If you don't set it, Inside titles are centered and Top/Bottom titles are left‑aligned.

Title Alignment showcase
box.Left

box.Inside
inside left

box.Top
top left

box.Bottom
bottom left

box.Center

box.Inside
inside center

box.Top
top center

box.Bottom
bottom center

box.Right

box.Inside
inside right

box.Top
top right

box.Bottom
bottom right

Content alignment:

ContentAlign decides whether content lines sit on the left, in the center, or on the right of the box. The box is as wide as its longest line, so it's the shorter lines that move. The default is box.Left.

b.ContentAlign(box.Left)
b.ContentAlign(box.Center)
b.ContentAlign(box.Right)
Content Alignment showcase
box.Left

left

box.Center

center

box.Right

right

Padding

Padding adds space inside the box borders, between the border and the content: px columns of spaces on both the left and right of every line, and py blank rows above and below the content.

b.Padding(px, py) // set both: horizontal (px), then vertical (py)
b.HPadding(px)    // horizontal only
b.VPadding(py)    // vertical only

Horizontal comes first — the reverse of CSS's padding: vertical horizontal shorthand.

Padding defaults to 0. Setting negative padding causes Render to return an error.

padding comparison

Margin

Margin adds space outside the box borders — horizontal margin prepends spaces to every line, vertical margin adds blank lines above and below.

b.Margin(mx, my) // horizontal (mx) and vertical (my) margin
b.HMargin(mx)    // horizontal only
b.VMargin(my)    // vertical only

The argument order matches Padding: horizontal first.

Margin defaults to 0. Setting negative margin causes Render to return an error.

margin comparison

Wrapping

Long content can wrap automatically to fit the terminal, or at an exact width with WrapLimit. Wrapping is off by default.

b.WrapContent(true)       // enable wrapping (default: 2/3 of terminal width, minus any HMargin)
b.WrapLimit(40)           // set explicit wrap width (enables wrapping)
b.WrapContent(false)      // disable wrapping

wrapping comparison

Tabs are expanded (at 8‑column stops) before wrapping, so the configured limit is honored even for tab‑heavy content.

Render returns an error if the wrap limit is not positive or the terminal width cannot be determined when wrapping is enabled without a limit.

Colors

Colors can be applied to:

  • Title: TitleColor
  • Content: ContentColor
  • Border: Color

Accepted formats:

  • The 16 ANSI color names: box.Black, box.Red, box.Green, box.Yellow, box.Blue, box.Magenta, box.Cyan, box.White — each also available with a Bright prefix (e.g. box.BrightYellow) or its Hi alias (e.g. box.HiRed).
  • Hex and XParseColor formats (TrueColor and 8-bit): #RGB, #RRGGBB, rgb:RRRR/GGGG/BBBB, rgba:RRRR/GGGG/BBBB/AAAA

Example:

b.TitleColor(box.BrightYellow)
b.ContentColor("#00FF00")
b.Color("rgb:0000/ffff/0000")

Invalid colors cause Render to return an error.

Colors automatically adapt to what the terminal supports (TrueColor, 256‑color, or 16‑color). When the output can't show color at all — NO_COLOR set, TERM=dumb, or output piped to a file — colors are dropped entirely, so logs stay free of escape codes.

Styled Content and ANSI Safety

Your text may already be styled before it reaches the box — by your logger, a color library, or your own escape codes. That's fine: pass it in as-is, and the box renders correctly around it.

styled := "\x1b[31mthis red part is long enough to wrap\x1b[0m and this part is plain"
out, _ := box.NewBox().WrapLimit(24).Render("", styled)

unclosed styling bleeding into the border, versus staying on the text

What you can rely on:

  • Colors and styles in your text never leak into the borders or padding.
  • Styling survives wrapping: when a colored sentence breaks across lines, every line keeps its color.
  • Clickable hyperlinks (OSC 8) stay clickable — and the borders never become part of the link.
  • This works together with Color / ContentColor: your styling and the box's styling don't fight.

There is nothing to enable — this is how Render always behaves. (For the curious: every rendered line is made self‑contained by closing any open styling at the line's end and re‑opening it on the next line.)

Rendering
out, err := b.Render("Title", "Content")
if err != nil {
    // handle invalid style, colors, padding, wrapping, etc.
}

fmt.Println(out)

Render returns an error if:

  • The BoxStyle is invalid
  • The TitlePosition is invalid
  • The TitleAlign or ContentAlign is invalid
  • The wrap limit is not positive
  • Padding or margin is negative
  • A multiline title is used with a non‑Inside title position
  • Any configured colors are invalid
  • Terminal width detection fails when needed for wrapping

For convenience:

out := b.MustRender("Title", "Content") // panics on error

Examples

The examples directory contains small, focused programs that showcase different features:

  • simple_box – minimal single box with title and content.
  • content_align – compare Left, Center, and Right content alignment.
  • content_wrap – demonstrate WrapContent / WrapLimit with long text.
  • titles – every title position (Inside, Top, Bottom) with every alignment (Left, Center, Right).
  • spacing – inner padding vs outer margin, separately and combined.
  • box_styles – render all built‑in border styles and colors.
  • custom_box – build boxes using fully custom corner/edge glyphs.
  • ansi_styles_and_links – use bold/underline/blink/strikethrough and OSC 8 hyperlinks.
  • colors_and_unicode – mix hex/ANSI colors with CJK, emoji, and wrapping.
  • ansi_art – render more decorative/"artistic" boxes.
  • shared_styles – derive multiple boxes from a shared base style with Copy.
  • ksctl – real‑world example from ksctl showing wide titles vs narrow content.
  • lolcat – rainbow color demo using custom ANSI styling helpers.
  • readme – code used to generate the screenshot at the top of this README.

Unicode, Emoji, and Width Handling

This library uses mattn/go-runewidth and github.com/charmbracelet/x/ansi to handle:

  • Wide characters (e.g., CJK)
  • Emojis and other multi‑cell glyphs
  • Stripping ANSI sequences when measuring widths

Note:

  1. Rendering quality depends on the terminal emulator and font. Some combinations may misalign visually.
  2. Indic scripts and complex text may not display correctly in most terminals.
  3. Online playgrounds and many CI environments often use basic fonts and may not render Unicode/emoji correctly, so boxes may look misaligned there.

Migration from v2

v3 is a new major version with a redesigned API.

Key changes:

  • Config struct and New(Config) have been replaced with:

    b := box.NewBox().
        Style(box.Single).
        Padding(2, 1).
        TitlePosition(box.Top).
        ContentAlign(box.Left)
    
  • String‑based fields (Type, ContentAlign, TitlePos) are now strongly typed:

    • "Single" → box.Single
    • "Top" → box.Top
    • "Center" → box.Center
  • Colors:

    • No more interface{} colors (uint, [3]uint, etc.).
    • Use ANSI names or the documented hex/rgb formats instead.
    • Invalid colors now error at Render time.
  • Print / Println behavior can be replicated by fmt.Println(b.MustRender(...)) or your own helper.

Read more at Migration guide.

The old v2 API remains available at:

go get github.com/Delta456/box-cli-maker/v2

but is no longer actively developed.

Using Box CLI Maker in your project? Add it to the adopters list — we'd love to feature it.

Sponsors

Thanks to CodeRabbit for sponsoring my open source work.

Acknowledgements

Thanks to:

for inspiration, and to all contributors who have improved this library over time.

License

Licensed under MIT.

Documentation

Overview

Package box renders styled boxes around text for terminal applications.

The core type is Box, constructed with NewBox and configured via a fluent API. Boxes support multiple built‑in styles, title positions, alignment, wrapping, and ANSI/truecolor output.

Basic example:

b := box.NewBox().
	Style(box.Single).
	Padding(2, 1).
	TitlePosition(box.Top).
	ContentAlign(box.Center).
	Color(box.Cyan).
	TitleColor(box.BrightYellow)

out, err := b.Render("Box CLI Maker", "Render highly customizable boxes\nin the terminal")
if err != nil {
	log.Fatal(err)
}
fmt.Println(out)

Construction

It is recommended to create boxes using NewBox, which returns a Box with sensible defaults. The returned Box can then be configured using methods such as Style, Padding, ContentAlign, Color, TitleColor, and TitlePosition.

The zero value of Box is not intended to be used directly with Render. If you construct a Box manually (e.g. with &box.Box{} or new(box.Box)), you must fully initialize all required fields (style, padding, glyphs, colors, etc.) yourself before calling Render.

Styles

Box styles are selected with Style and the BoxStyle constants:

box.Single
box.Double
box.Round
box.Bold
box.SingleDouble
box.DoubleSingle
box.Classic
box.Hidden
box.Block

You can further customize any style by overriding the corner and edge glyphs using TopRight, TopLeft, BottomRight, BottomLeft, Horizontal, and Vertical.

Titles and alignment

Titles can be placed inside the box, on the top border, or on the bottom border using TitlePosition with the TitlePosition constants:

box.Inside
box.Top
box.Bottom

Title alignment is controlled with TitleAlign and content alignment with ContentAlign; both use the AlignType constants:

box.Left
box.Center
box.Right

An Inside title defaults to Center; a Top/Bottom title defaults to Left on the border. Content defaults to Left.

Padding

Padding adds space inside the box borders between the content and the edges. Horizontal padding adds spaces on the left and right of each line. Vertical padding adds blank lines above and below the content. Use Padding to set both at once, or HPadding / VPadding to set each independently.

The argument order is horizontal first: Padding(2, 1) means 2 columns of side padding and 1 blank row above and below — the reverse of CSS's "padding: vertical horizontal" shorthand. Padding defaults to 0; negative padding causes Render to return an error.

Margin

Margin adds space outside the box borders. Horizontal margin prepends spaces to every rendered line. Vertical margin adds blank lines above and below the box. Use Margin to set both at once, or HMargin / VMargin to set each independently. The argument order matches Padding: horizontal first. Margin defaults to 0; negative margin causes Render to return an error.

Wrapping

WrapContent enables or disables automatic wrapping of the content. By default, when wrapping is enabled, the wrap limit is two‑thirds of the available terminal width. If a horizontal margin is set, it is subtracted from the terminal width first so the rendered box stays within the terminal. WrapLimit can be used to set an explicit maximum width. Tabs are expanded at 8-column stops before wrapping, so the limit is honored for tab-heavy content, and Windows \r\n line endings are normalized to \n.

Styled content

Content and titles may already contain ANSI styling — colors, bold, underline, and OSC 8 hyperlinks — and can be passed in as-is: user styling never bleeds into the borders or padding, styling survives wrapping, and this composes with Color and ContentColor.

Every rendered row is made self-contained: styles or hyperlinks that would span a line break (from wrapping or the content's own newlines) are closed at the end of each row and re-opened on the next.

Colors

TitleColor, ContentColor, and Color accept either one of the 16 ANSI color name constants — the 8 base names (e.g. box.Green), each also with a Bright prefix (box.BrightRed) or its Hi alias (box.HiRed) — or a #RGB / #RRGGBB / rgb:RRRR/GGGG/BBBB / rgba:RRRR/GGGG/BBBB/AAAA value. Invalid colors cause Render to return an error.

Colors automatically adapt to what the terminal supports (TrueColor, 256-color, or 16-color). When the output cannot show color at all — NO_COLOR set, TERM=dumb, or output piped to a file — colors are dropped entirely, so captured output stays free of escape sequences.

Errors

Render returns an error if the style or title position is invalid, the wrap limit is not positive, padding or margin is negative, a multiline title is used with a non‑Inside title position, any configured colors are invalid, or the terminal width cannot be determined. MustRender is a convenience wrapper that panics on error.

Copying

Copy returns a shallow copy of a Box so you can define a base style and derive variants without mutating the original:

base := box.NewBox().Style(box.Single).Padding(2, 1)
info := base.Copy().Color(box.Green)
warn := base.Copy().Color(box.Yellow)

Each Copy can then be customized and rendered independently.

Index

Constants

View Source
const (
	Black   = "Black"
	Red     = "Red"
	Green   = "Green"
	Yellow  = "Yellow"
	Blue    = "Blue"
	Magenta = "Magenta"
	Cyan    = "Cyan"
	White   = "White"

	BrightBlack   = "BrightBlack"
	HiBlack       = "HiBlack"
	BrightRed     = "BrightRed"
	HiRed         = "HiRed"
	BrightGreen   = "BrightGreen"
	HiGreen       = "HiGreen"
	BrightYellow  = "BrightYellow"
	HiYellow      = "HiYellow"
	BrightBlue    = "BrightBlue"
	HiBlue        = "HiBlue"
	BrightMagenta = "BrightMagenta"
	HiMagenta     = "HiMagenta"
	BrightCyan    = "BrightCyan"
	HiCyan        = "HiCyan"
	BrightWhite   = "BrightWhite"
	HiWhite       = "HiWhite"
)

Standard and bright ANSI color name constants usable with Color, TitleColor, and ContentColor.

Variables

This section is empty.

Functions

This section is empty.

Types

type AlignType

type AlignType string

AlignType represents the horizontal alignment of content inside the box.

const (
	// Center represents centered content alignment.
	Center AlignType = "Center"
	// Left represents left-aligned content.
	Left AlignType = "Left"
	// Right represents right-aligned content.
	Right AlignType = "Right"
)

type Box

type Box struct {
	// contains filtered or unexported fields
}

Box renders styled borders around text content.

func NewBox

func NewBox() *Box

NewBox creates a new Box with the box.Single style preset applied.

func (*Box) BottomLeft

func (b *Box) BottomLeft(glyph string) *Box

BottomLeft sets the glyph used in the lower-left corner.

func (*Box) BottomRight

func (b *Box) BottomRight(glyph string) *Box

BottomRight sets the glyph used in the lower-right corner.

func (*Box) Color

func (b *Box) Color(color string) *Box

Color sets the color used for the box border (chrome).

Accepts one of the first 16 ANSI color name constants (e.g. box.Green, box.BrightRed) or a #RGB / #RRGGBB / rgb:RRRR/GGGG/BBBB / rgba:RRRR/GGGG/BBBB/AAAA value.

Colors are automatically converted to the terminal's detected color profile, and suppressed entirely when the output does not support color (NO_COLOR set, TERM=dumb, or a non-TTY stdout).

Invalid colors cause Render to return an error.

func (*Box) ContentAlign

func (b *Box) ContentAlign(align AlignType) *Box

ContentAlign sets the horizontal alignment of content inside the box.

Supported values are box.Left, box.Center, and box.Right.

func (*Box) ContentColor

func (b *Box) ContentColor(color string) *Box

ContentColor sets the color used for the content text.

Accepts one of the first 16 ANSI color name constants (e.g. box.Green, box.BrightRed) or a #RGB / #RRGGBB / rgb:RRRR/GGGG/BBBB / rgba:RRRR/GGGG/BBBB/AAAA value.

Colors are automatically converted to the terminal's detected color profile, and suppressed entirely when the output does not support color (NO_COLOR set, TERM=dumb, or a non-TTY stdout).

Invalid colors cause Render to return an error.

func (*Box) Copy

func (b *Box) Copy() *Box

Copy returns a shallow copy of the Box so further mutations do not affect the original.

Useful for creating base styles and deriving multiple boxes from them.

func (*Box) HMargin added in v3.1.0

func (b *Box) HMargin(mx int) *Box

HMargin sets horizontal outer margin (left spacing).

func (*Box) HPadding

func (b *Box) HPadding(px int) *Box

HPadding sets horizontal padding (left and right).

func (*Box) Horizontal

func (b *Box) Horizontal(glyph string) *Box

Horizontal sets the glyph used for the horizontal edges.

func (*Box) Margin added in v3.1.0

func (b *Box) Margin(mx, my int) *Box

Margin sets horizontal (mx) and vertical (my) outer margin around the box.

func (*Box) MustRender

func (b *Box) MustRender(title, content string) string

MustRender is like Render but panics if an error occurs.

Use MustRender in examples or CLIs where failures should abort execution instead of being handled explicitly.

func (*Box) Padding

func (b *Box) Padding(px, py int) *Box

Padding sets horizontal (px) and vertical (py) inner padding.

func (*Box) Render

func (b *Box) Render(title, content string) (string, error)

Render generates the box with the given title and content.

It returns an error if:

  • the BoxStyle is invalid,
  • the TitlePosition is invalid,
  • the wrap limit set by WrapLimit is not positive,
  • padding is negative,
  • a multiline title is used with a non-Inside TitlePosition, or
  • any configured colors are invalid.

func (*Box) Style

func (b *Box) Style(box BoxStyle) *Box

Style selects one of the built-in BoxStyle presets.

Common styles include box.Single, box.Double, box.Round, box.Bold, box.SingleDouble, box.DoubleSingle, box.Classic, box.Hidden, and box.Block.

To make custom styles, call TopRight, TopLeft, BottomRight, BottomLeft, Horizontal, and Vertical after Style to override individual glyphs.

Example:

b := box.NewBox()
b.TopRight("+").TopLeft("+").BottomRight("+").BottomLeft("_").Horizontal("-").Vertical("|")

func (*Box) TitleAlign added in v3.1.0

func (b *Box) TitleAlign(align AlignType) *Box

TitleAlign sets the horizontal alignment of the title.

When TitlePosition is Inside, it aligns the title lines inside the box. When TitlePosition is Top or Bottom, it aligns the title on the border.

Supported values are box.Left, box.Center, and box.Right.

func (*Box) TitleColor

func (b *Box) TitleColor(color string) *Box

TitleColor sets the color used for the title text.

Accepts one of the first 16 ANSI color name constants (e.g. box.Green, box.BrightRed) or a #RGB / #RRGGBB / rgb:RRRR/GGGG/BBBB / rgba:RRRR/GGGG/BBBB/AAAA value.

Colors are automatically converted to the terminal's detected color profile, and suppressed entirely when the output does not support color (NO_COLOR set, TERM=dumb, or a non-TTY stdout).

Invalid colors cause Render to return an error.

func (*Box) TitlePosition

func (b *Box) TitlePosition(pos TitlePosition) *Box

TitlePosition sets where the title is rendered relative to the box.

Valid positions are box.Inside, box.Top, and box.Bottom.

func (*Box) TopLeft

func (b *Box) TopLeft(glyph string) *Box

TopLeft sets the glyph used in the upper-left corner.

func (*Box) TopRight

func (b *Box) TopRight(glyph string) *Box

TopRight sets the glyph used in the upper-right corner.

func (*Box) VMargin added in v3.1.0

func (b *Box) VMargin(my int) *Box

VMargin sets vertical outer margin (blank lines above and below).

func (*Box) VPadding

func (b *Box) VPadding(py int) *Box

VPadding sets vertical padding (top and bottom).

func (*Box) Vertical

func (b *Box) Vertical(glyph string) *Box

Vertical sets the glyph used for the vertical edges.

func (*Box) WrapContent

func (b *Box) WrapContent(allow bool) *Box

WrapContent enables or disables automatic wrapping of content.

When enabled, content is wrapped to fit roughly two-thirds of the available terminal width by default. If a horizontal margin is set, it is subtracted from the terminal width before computing the wrap limit, so the rendered box stays within the terminal. For custom limits or non-TTY outputs, use WrapLimit instead.

func (*Box) WrapLimit

func (b *Box) WrapLimit(limit int) *Box

WrapLimit enables wrapping and sets an explicit maximum width for content.

The limit must be positive; Render returns an error otherwise. For automatic wrapping based on the terminal width, use WrapContent instead.

type BoxStyle

type BoxStyle string

BoxStyle defines a built‑in border style for a Box.

const (
	// Single is a box style with single-line borders.
	Single BoxStyle = "Single"
	// Double is a box style with double-line borders.
	Double BoxStyle = "Double"
	// Round is a box style with rounded corners.
	Round BoxStyle = "Round"
	// Bold is a box style with heavy lines.
	Bold BoxStyle = "Bold"
	// SingleDouble is a box style with single horizontal and double vertical lines.
	SingleDouble BoxStyle = "SingleDouble"
	// DoubleSingle is a box style with double horizontal and single vertical lines.
	DoubleSingle BoxStyle = "DoubleSingle"
	// Classic is a box style using plus and minus characters.
	Classic BoxStyle = "Classic"
	// Hidden is a box style with invisible (space) edges and visible "+"
	// corner markers indicating the box's extent.
	//
	// For a fully invisible box, override the corners with spaces:
	//
	//	box.NewBox().Style(box.Hidden).TopLeft(" ").TopRight(" ").BottomLeft(" ").BottomRight(" ")
	Hidden BoxStyle = "Hidden"
	// Block is a box style with solid block characters.
	Block BoxStyle = "Block"
)

type TitlePosition

type TitlePosition string

TitlePosition represents the position of the title relative to the box.

const (
	// Inside places the title as the first lines inside the box.
	Inside TitlePosition = "Inside"
	// Top places the title on the top border of the box.
	Top TitlePosition = "Top"
	// Bottom places the title on the bottom border of the box.
	Bottom TitlePosition = "Bottom"
)

Directories

Path Synopsis
examples
ansi_art command
box_styles command
content_align command
content_wrap command
custom_box command
ksctl command
lolcat command
readme command
shared_styles command
simple_box command
spacing command
titles command
scripts
screenshots/showcase command
Command showcase renders one README showcase box to stdout, named by argument (a style, title position/alignment, or content alignment).
Command showcase renders one README showcase box to stdout, named by argument (a style, title position/alignment, or content alignment).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL