Gradients
New to SharpConsoleUI? Gradients are covered hands-on in Tutorial 3: Settings App.
SharpConsoleUI supports gradient colors for both text and window backgrounds, extending the existing ColorGradient system.
Table of Contents
- Gradient Text in Markup
- Window Background Gradients
- CharacterBuffer Direct API
- Gradient Direction
- Predefined Gradients
- Custom Gradients
Gradient Text in Markup
Use the [gradient=...] tag in markup to apply color gradients across text:
// Named gradient
window.AddControl(new MarkupControl("[gradient=spectrum]Rainbow Text[/]"));
// Two-color gradient
window.AddControl(new MarkupControl("[gradient=blue->cyan]Ocean Breeze[/]"));
// Multi-stop gradient
window.AddControl(new MarkupControl("[gradient=red->yellow->green]Traffic Light[/]"));
// Predefined gradient names
window.AddControl(new MarkupControl("[gradient=warm]Temperature Rising[/]"));
window.AddControl(new MarkupControl("[gradient=cool]Arctic Chill[/]"));
How It Works
The parser measures the text span length, then assigns per-character interpolated foreground colors. Inner decorations (bold, underline, etc.) are preserved.
// Gradient with decorations
"[gradient=blue->white][bold]Bold Gradient[/][/]"
// Nested tags inside gradient
"[gradient=spectrum]Hello [underline]World[/][/]"
Separator Syntax
Both → (Unicode arrow) and -> (ASCII) are supported as color stop separators:
"[gradient=red→blue]Unicode arrow[/]"
"[gradient=red->blue]ASCII arrow[/]"
Window Background Gradients
Apply gradient backgrounds to entire windows:
// Via builder
var window = new WindowBuilder(ws)
.WithTitle("Gradient Background")
.WithBackgroundGradient(
ColorGradient.FromColors(Color.DarkBlue, Color.Black),
GradientDirection.Vertical)
.Build();
// Programmatic
window.BackgroundGradient = new GradientBackground(
ColorGradient.FromColors(Color.DarkBlue, Color.DarkCyan),
GradientDirection.Horizontal);
// Remove gradient
window.BackgroundGradient = null;
Background gradients are rendered via PreBufferPaint, so all controls paint on top of the gradient.
CharacterBuffer Direct API
Apply gradients directly to any CharacterBuffer region:
// In a PostBufferPaint handler or CanvasControl
buffer.FillGradient(
new LayoutRect(0, 0, 40, 10),
ColorGradient.Predefined["spectrum"],
GradientDirection.DiagonalDown);
This delegates to GradientRenderer.FillGradient() which handles the interpolation and direction logic.
Gradient Direction
public enum GradientDirection
{
Horizontal, // Left to right
Vertical, // Top to bottom
DiagonalDown, // Top-left to bottom-right
DiagonalUp // Bottom-left to top-right
}
Predefined Gradients
Access via ColorGradient.Predefined:
| Name | Colors |
|---|---|
spectrum |
Full rainbow (red → orange → yellow → green → cyan → blue → violet) |
warm |
Red → Orange → Yellow |
cool |
Blue → Cyan → Green |
var gradient = ColorGradient.Predefined["spectrum"];
Custom Gradients
FromColors Factory
// Two colors
var gradient = ColorGradient.FromColors(Color.Red, Color.Blue);
// Multiple stops
var gradient = ColorGradient.FromColors(
Color.Red, Color.Yellow, Color.Green, Color.Cyan, Color.Blue);
Parse from String
// Color names
var gradient = ColorGradient.Parse("red->blue");
// Hex colors
var gradient = ColorGradient.Parse("#FF0000->#0000FF");
// Predefined name
var gradient = ColorGradient.Parse("spectrum");
Transparent Control Backgrounds
Controls support Color.Transparent as their background color, which tells the renderer to
composite the control's cells against whatever is already in the buffer — including window
background gradients.
// Control floats on top of the window gradient — no opaque rectangle behind it
var label = new MarkupControl("[bold cyan]CPU Usage[/]");
// BackgroundColor defaults to null, which resolves to Color.Transparent
// Opaque override — solid background, ignores whatever is behind the control
label.BackgroundColor = Color.Grey11;
The Resolution Chain
Each control resolves its background through a priority chain:
- Control's own
BackgroundColor— if explicitly set to a non-transparent color - Theme slot — e.g.
ITheme.LineGraphBackgroundColor,ITheme.SparklineBackgroundColor Color.Transparent— the terminal fallback
Color.Transparent is not "no color" — it is a definite instruction: show what is underneath.
The underlying content might be the window's gradient background, another control, or the desktop
fill.
Alpha Compositing in CharacterBuffer
CharacterBuffer applies Porter-Duff "over" compositing to both the background and
the foreground of every cell written via SetCell / SetNarrowCell.
resolved_bg = Color.Blend(new_bg, existing_bg)
resolved_fg = Color.Blend(new_fg, resolved_bg)
Background: when a control writes Color.Transparent as the background, the existing
background (typically the gradient painted before controls render) shows through unchanged.
Foreground: when a control writes a semi-transparent foreground, the glyph is blended against the resolved background of that cell — not against the previous foreground. This is the physically correct model: the background is what sits beneath the glyph, so a partially transparent character reveals the background behind it.
new_bg = Transparent → resolved_bg = gradient color at that position
new_fg = cyan @ 50 % → resolved_fg = blend(cyan, resolved_bg) // not blend(cyan, white)
This means gradient window backgrounds remain visible beneath any control that uses
Color.Transparent, and semi-transparent foreground characters (including █ full-block
characters) blend smoothly into the gradient rather than fading toward white.
// Window with a blue→black vertical gradient
var window = new WindowBuilder(ws)
.WithBackgroundGradient(
ColorGradient.FromColors(Color.DarkBlue, Color.Black),
GradientDirection.Vertical)
.Build();
// SparklineControl with transparent background — gradient shows through the graph area
var spark = new SparklineControl();
// BackgroundColor is null → resolves to Color.Transparent → gradient visible behind bars
window.AddControl(spark);
Alpha Channel in Color
Color carries an alpha channel. ColorGradient.BlendColors interpolates all four channels
(R, G, B, A), so gradients can themselves fade to transparent — creating controls whose
background dissolves into the window gradient at one edge.
// Gradient that fades from cyan to fully transparent
var fadeOut = ColorGradient.FromColors(Color.Cyan, Color.FromArgb(0, 0, 255, 255));
var bar = new BarGraphControl { SmoothGradient = fadeOut };
See Also
- Markup Syntax — Full markup reference
- Compositor Effects — Buffer manipulation hooks
- Themes — Customizing visual appearance