Styling and Colors
Overview
go-tui uses a Tailwind-inspired class system for styling. You set colors, text decorations, borders, and gradients through the class attribute on elements, and the code generator converts them into tui.Element options at compile time. For cases where classes aren't flexible enough, you can construct Style values in Go and pass them through attributes.
Text Styles
Text decorations are applied through classes on any element that renders text:
<div class="flex-col gap-1">
<span class="font-bold">Bold text</span>
<span class="font-dim">Dimmed text</span>
<span class="italic">Italic text</span>
<span class="underline">Underlined text</span>
<span class="strikethrough">Struck-through text</span>
<span class="reverse">Reversed foreground/background</span>
</div>
The full set of text style classes:
| Class | Effect |
|---|---|
font-bold |
Bold / bright |
font-dim or text-dim |
Dimmed / faint |
italic |
Italic |
underline |
Underlined |
strikethrough |
Struck through |
reverse |
Swaps foreground and background colors |
font-dim and text-dim are aliases that produce the same result.
Text Colors
go-tui supports the standard 16 ANSI terminal colors. Each has a text- prefixed class:
<div class="flex-col">
<span class="text-red">Red</span>
<span class="text-green">Green</span>
<span class="text-blue">Blue</span>
<span class="text-cyan">Cyan</span>
<span class="text-magenta">Magenta</span>
<span class="text-yellow">Yellow</span>
<span class="text-white">White</span>
<span class="text-black">Black</span>
</div>
Each color has a bright variant:
<div class="flex-col">
<span class="text-bright-red">Bright red</span>
<span class="text-bright-green">Bright green</span>
<span class="text-bright-blue">Bright blue</span>
<span class="text-bright-cyan">Bright cyan</span>
<span class="text-bright-magenta">Bright magenta</span>
<span class="text-bright-yellow">Bright yellow</span>
<span class="text-bright-white">Bright white</span>
<span class="text-bright-black">Bright black (gray)</span>
</div>
Arbitrary Hex Colors
For colors beyond the 16 ANSI palette, use the bracket syntax with a hex value:
<span class="text-[#FF6B35]">Custom orange</span>
<span class="text-[#A3F]">Short-form hex (expands to #AA33FF)</span>
Both #RRGGBB (6-digit) and #RGB (3-digit shorthand) formats work. These produce true-color output if the terminal supports it, with automatic fallback to the nearest ANSI color on limited terminals.
Background Colors
The same color set is available with the bg- prefix:
<div class="flex-col gap-1">
<span class="bg-red text-white p-1">Red background</span>
<span class="bg-cyan text-black p-1">Cyan background</span>
<span class="bg-bright-yellow text-black p-1">Bright yellow background</span>
<span class="bg-[#2D1B69] text-white p-1">Custom purple background</span>
</div>
Every named color and bright variant that works with text- also works with bg-. Arbitrary hex values work the same way: bg-[#RRGGBB] or bg-[#RGB].
Combining Styles
Multiple classes compose. List them space-separated in the class attribute:
<span class="font-bold text-cyan bg-black underline">
Bold, cyan, on black, underlined
</span>
Styles on parent elements do not cascade to children. Each element's class applies only to that element:
<div class="text-cyan">
<span>This text is NOT cyan. It uses the default color</span>
<span class="text-cyan">This text IS cyan</span>
</div>
If you want consistent styling across a subtree, apply the class to each element that needs it, or use a pure component to encapsulate the pattern.
Borders
Borders wrap an element in box-drawing characters. Four styles are available:
| Class | Style | Characters |
|---|---|---|
border-single |
Single line | ┌─┐│└─┘ |
border-double |
Double line | ╔═╗║╚═╝ |
border-rounded |
Rounded corners | ╭─╮│╰─╯ |
border-thick |
Heavy line | ┏━┓┃┗━┛ |
<div class="flex gap-2">
<div class="border-single p-1">
<span>Single</span>
</div>
<div class="border-double p-1">
<span>Double</span>
</div>
<div class="border-rounded p-1">
<span>Rounded</span>
</div>
<div class="border-thick p-1">
<span>Thick</span>
</div>
</div>
Border Colors
Color the border with border-{color}:
<div class="border-rounded border-cyan p-1">
<span>Cyan bordered box</span>
</div>
All 16 named colors and their bright variants work: border-red, border-bright-green, etc. Arbitrary hex values are supported too: border-[#FF6B35].
Border Titles
The borderTitle attribute draws a label centered in the top border line:
<div class="border-rounded p-1" borderTitle=" Status ">
<span>All systems normal</span>
</div>
╭────── Status ──────╮
│ All systems normal │
╰────────────────────╯
The title renders with the border's style, so border color classes and the borderStyle attribute color both the line and the label. Titles wider than the top edge are truncated. Wrapping the text in spaces (" Status ") keeps a gap between the label and the line characters.
Border titles also work with border gradients. The gradient draws first and the title overwrites the characters it covers.
Gradients
Gradients interpolate between two colors across text, backgrounds, or borders.
Syntax
The general form is:
{target}-gradient-{start}-{end}[-{direction}]
Where:
- target:
text,bg, orborder - start and end: any named ANSI color (
red,cyan,bright-blue, etc.) - direction (optional):
-h(horizontal, the default),-v(vertical),-dd(diagonal down),-du(diagonal up)
Text Gradients
<div class="flex-col gap-1">
<span class="text-gradient-cyan-magenta">Horizontal gradient (default)</span>
<span class="text-gradient-red-yellow-h">Explicit horizontal</span>
<span class="text-gradient-green-blue-v">Vertical gradient</span>
<span class="text-gradient-cyan-magenta-dd">Diagonal down</span>
<span class="text-gradient-yellow-red-du">Diagonal up</span>
</div>
Background Gradients
<div class="bg-gradient-blue-cyan-h p-1">
<span class="text-white">Blue-to-cyan background</span>
</div>
Border Gradients
<div class="border-rounded border-gradient-cyan-magenta p-1">
<span>Gradient border</span>
</div>
The gradient travels around the perimeter of the border, shifting from the start color to the end color over the first half, then back again over the second half.
Direction Reference
| Suffix | Direction | Description |
|---|---|---|
-h (or omitted) |
Horizontal | Left to right |
-v |
Vertical | Top to bottom |
-dd |
Diagonal down | Top-left to bottom-right |
-du |
Diagonal up | Bottom-left to top-right |
Programmatic Styling
When you need dynamic styles that depend on state or computed values, construct Style objects in Go and pass them through element attributes.
Building Styles
Use tui.NewStyle() with chainable methods:
highlight := tui.NewStyle().
Bold().
Foreground(tui.Cyan).
Background(tui.Black)
Available methods on Style:
| Method | Effect |
|---|---|
Foreground(Color) |
Set text color |
Background(Color) |
Set background color |
Bold() |
Bold text |
Dim() |
Dimmed text |
Italic() |
Italic text |
Underline() |
Underlined text |
Strikethrough() |
Struck-through text |
Reverse() |
Swap foreground and background |
Blink() |
Blinking text (rarely supported by terminals) |
All methods return a new Style, so they chain:
style := tui.NewStyle().Bold().Underline().Foreground(tui.Red)
Color Constructors
Several ways to create a Color:
// Named color variables (already Color values)
tui.Cyan
tui.BrightRed
// ANSI 256 palette index (0-255)
tui.ANSIColor(33)
// 24-bit RGB
tui.RGBColor(255, 107, 53)
// Hex string (returns Color and error)
color, err := tui.HexColor("#FF6B35")
The named color variables (tui.Red, tui.Cyan, tui.BrightGreen, etc.) are already Color values, so you can use them directly with Foreground() and Background():
style := tui.NewStyle().Foreground(tui.Cyan).Bold()
Applying Styles to Elements
Pass styles through element attributes in .gsx:
templ (s *myApp) Render() {
<div borderStyle={tui.NewStyle().Foreground(tui.Magenta)} class="border-rounded p-1">
<span textStyle={tui.NewStyle().Bold().Foreground(tui.Cyan)}>Dynamic style</span>
</div>
}
Style attributes you can set:
| Attribute | Controls |
|---|---|
textStyle |
Text foreground color, background, and decorations |
borderStyle |
Border line color and decorations |
background |
Element background fill |
When to Use Programmatic Styles
Class-based styling handles most cases. Programmatic styles are useful when the style depends on runtime values, like coloring a number red when negative and green when positive, or when you need 256-palette indices or RGB colors computed at runtime.
package main
import (
"fmt"
tui "github.com/grindlemire/go-tui"
)
type statusApp struct {
value *tui.State[int]
}
func StatusApp() *statusApp {
return &statusApp{
value: tui.NewState(0),
}
}
func (s *statusApp) KeyMap() tui.KeyMap {
return tui.KeyMap{
tui.On(tui.KeyEscape, func(ke tui.KeyEvent) { ke.App().Stop() }),
tui.On(tui.Rune('+'), func(ke tui.KeyEvent) {
s.value.Update(func(v int) int { return v + 1 })
}),
tui.On(tui.Rune('-'), func(ke tui.KeyEvent) {
s.value.Update(func(v int) int { return v - 1 })
}),
}
}
func valueStyle(v int) tui.Style {
if v > 0 {
return tui.NewStyle().Bold().Foreground(tui.Green)
}
if v < 0 {
return tui.NewStyle().Bold().Foreground(tui.Red)
}
return tui.NewStyle().Dim()
}
templ (s *statusApp) Render() {
<div class="flex-col items-center justify-center h-full gap-1">
<span textStyle={valueStyle(s.value.Get())}>{fmt.Sprintf("Value: %d", s.value.Get())}</span>
<span class="font-dim">Press + / - to change, Esc to quit</span>
</div>
}
Color Capabilities
Terminals vary in color support. go-tui detects the current terminal's capabilities at startup and falls back to supported colors automatically.
Detection
tui.DetectCapabilities() checks environment variables (COLORTERM, TERM, and terminal-specific variables like ITERM_SESSION_ID or KITTY_WINDOW_ID) to determine what the terminal supports:
caps := tui.DetectCapabilities()
fmt.Println(caps.Colors) // Color16, Color256, or ColorTrue
fmt.Println(caps.TrueColor) // true if 24-bit RGB is supported
fmt.Println(caps.Unicode) // true if Unicode rendering is supported
Color Levels
| Level | Constant | Colors |
|---|---|---|
| None | tui.ColorNone |
Monochrome |
| 16 | tui.Color16 |
Standard + bright ANSI |
| 256 | tui.Color256 |
ANSI 256 palette |
| True color | tui.ColorTrue |
24-bit RGB |
Automatic Fallback
You don't need to handle color fallback yourself. When you use an RGB color (via tui.RGBColor() or hex classes like text-[#FF6B35]) on a terminal that only supports 256 or 16 colors, the framework approximates it to the nearest supported color using the Color.ToANSI() method. This maps RGB values to the closest entry in the ANSI 256 palette's 6x6x6 color cube and grayscale ramp.
If even ANSI colors aren't supported, colors are dropped entirely and the terminal's default foreground and background are used.
The styling examples from this guide look like this in the terminal:

Next Steps
- Layout -- Flexbox layout: direction, alignment, spacing, and sizing
- State and Reactivity -- Reactive state with
State[T]