HtmlControl

June 12, 2026 · View on GitHub

Render real HTML content in the terminal with scrolling, link navigation, and inline images.

Overview

HtmlControl parses and renders HTML content using the AngleSharp HTML parser, displaying it with colors, text formatting, block layout, tables, lists, images (via half-block rendering), and interactive link navigation. It supports both inline HTML content and loading from URLs with progressive image loading.

Properties

PropertyTypeDefaultDescription
ForegroundColorColorTheme defaultDefault text color
BackgroundColorColorTheme defaultBackground color
LinkColorColorCyanColor for unvisited links
VisitedLinkColorColorPurpleColor for visited links
ShowImagesboolfalseEnable half-block image rendering
ShowBulletPointsbooltrueShow bullet characters for <ul> lists
TabSizeint4Tab stop width in characters
BlockSpacingint1Blank lines between block elements
ScrollbarVisibilityScrollbarVisibilityAutoWhen to show the vertical scrollbar
LoadingTextstring"Loading..."Text shown during URL loading
ScrollOffsetint0Current vertical scroll position
ContentHeightint(read-only)Total height of rendered content
IsLoadingbool(read-only)Whether a URL is currently loading
LoadingStatusstring?(read-only)Current loading phase description
CurrentUrlstring?(read-only)URL of the currently loaded page
RawHtmlstring?(read-only)The raw HTML source
MouseWheelScrollSpeedint3Lines scrolled per mouse wheel tick
IsEnabledbooltrueWhether the control accepts input

Events

EventArgumentsDescription
LinkClickedLinkClickedEventArgs(Url, Text, Mouse?)A link was activated (click or Enter)
LinkHoverLinkHoverEventArgsMouse moved over a link
ContentLoadedEventArgsHTML content was parsed and laid out
LoadingCompletedEventArgsURL loading and image loading finished
LoadErrorLoadErrorEventArgsAn error occurred during URL loading
MouseClickMouseEventArgsNon-link area was clicked
MouseRightClickMouseEventArgsRight-click on the control

Creating HtmlControl

var html = Controls.Html()
    .WithContent("<h1>Hello World</h1><p>This is <b>bold</b> and <em>italic</em>.</p>")
    .WithLinkColor(Color.Cyan1)
    .WithShowImages(true)
    .WithScrollbarVisibility(ScrollbarVisibility.Auto)
    .OnLinkClicked((sender, e) => Console.WriteLine($"Clicked: {e.Url}"))
    .Fill()
    .Build();

window.AddControl(html);

Using Constructor

var html = new HtmlControl();
html.SetContent("<h1>Hello</h1><p>World</p>");
html.LinkClicked += (sender, e) => NavigateTo(e.Url);
window.AddControl(html);

Loading from URL

var html = Controls.Html()
    .WithShowImages(true)
    .Fill()
    .Build();

window.AddControl(html);

// Load asynchronously — shows loading banner while fetching
await html.LoadUrlAsync("https://example.com");

Loading with Base URL

// Set content with a base URL for resolving relative links and images
html.SetContent(htmlString, "https://example.com/page/");

Keyboard Support

KeyAction
Up ArrowScroll up one line
Down ArrowScroll down one line
Page UpScroll up one viewport
Page DownScroll down one viewport
HomeScroll to top
EndScroll to bottom
TabFocus next link
Shift+TabFocus previous link
EnterActivate focused link (fires LinkClicked)

Mouse Support

ActionResult
Click on linkFires LinkClicked event
Click on scrollbarScroll to position
Drag scrollbar thumbSmooth scrolling
Mouse wheelScroll up/down
Hover over linkFires LinkHover, brightens link text
Right-clickFires MouseRightClick

Focus Behavior

HtmlControl implements IFocusableControl and IInteractiveControl:

  • Tab focus: Control receives focus via Tab key navigation
  • Mouse focus: Clicking anywhere on the control (including scrollbar) sets focus
  • Visual indicator: Scrollbar thumb turns cyan when focused
  • Link highlight: Focused link is shown with inverted colors (foreground/background swapped)
  • Multi-line links: Links spanning multiple lines are treated as a single Tab stop; all segments highlight together

Supported HTML Elements

Block Elements

<h1><h6>, <p>, <div>, <blockquote>, <pre>, <code>, <hr>, <br>, <table>, <ul>, <ol>, <li>, <dl>, <dt>, <dd>, <details>, <summary>, <figure>, <figcaption>

Inline Elements

<b>, <strong>, <i>, <em>, <u>, <s>, <strike>, <del>, <code>, <a>, <span>, <sub>, <sup>, <mark>, <small>, <abbr>

Tables

<table>, <thead>, <tbody>, <tfoot>, <tr>, <th>, <td> — with column width calculation, borders, and header styling.

Images

<img src="..." alt="..."> — rendered using half-block pixel art when ShowImages is enabled. Supports PNG, JPEG, BMP, GIF, WebP, TIFF. Images respect the HTML width attribute. Progressive loading fetches and renders images in the background after initial text layout.

Examples

Simple HTML Content

var html = Controls.Html()
    .WithContent("""
        <h1>Welcome</h1>
        <p>This is a paragraph with <b>bold</b> and <em>italic</em> text.</p>
        <ul>
            <li>Item one</li>
            <li>Item two</li>
            <li>Item three</li>
        </ul>
    """)
    .Fill()
    .Build();

Web Browser with Navigation

var html = Controls.Html()
    .WithShowImages(true)
    .OnLinkClicked(async (sender, e) =>
    {
        var control = (HtmlControl)sender!;
        await control.LoadUrlAsync(e.Url);
    })
    .Fill()
    .Build();

await html.LoadUrlAsync("https://en.wikipedia.org/wiki/Main_Page");

Email Viewer

var html = Controls.Html()
    .WithShowImages(false)  // Don't load remote images in emails
    .WithLinkColor(Color.Blue)
    .WithBackgroundColor(Color.White)
    .WithForegroundColor(Color.Black)
    .Fill()
    .Build();

html.SetContent(emailHtmlBody, emailBaseUrl);
var statusLabel = Controls.Markup().Build();

var html = Controls.Html()
    .OnLinkHover((sender, e) =>
    {
        statusLabel.SetContent(new List<string>
        {
            e.Url != null ? $"[dim]{e.Url}[/]" : ""
        });
    })
    .Fill()
    .Build();

Custom Colors and Styling

var html = Controls.Html()
    .WithContent("<h1>Dark Theme</h1><p>Content here</p>")
    .WithForegroundColor(new Color(200, 200, 200))
    .WithBackgroundColor(new Color(30, 30, 30))
    .WithLinkColor(Color.Cyan1)
    .WithVisitedLinkColor(new Color(180, 130, 255))
    .WithBlockSpacing(2)
    .Fill()
    .Build();

Performance Notes

  • DOM caching: The HTML parser caches the parsed DOM document. Width-only changes (e.g., window resize) skip re-parsing and only re-flow the layout.
  • Resize debouncing: During rapid resize, relayout is debounced (150ms) to keep the UI responsive. Content renders at the previous width until resize settles.
  • Progressive image loading: When ShowImages is enabled, text content renders immediately. Images load in the background and are progressively committed to the layout.
  • Large documents: For very large HTML documents, consider setting an explicit Height to avoid measuring the full document height.

Best Practices

  • Use ShowImages = true only when image content is expected — it enables background HTTP fetches
  • Handle LinkClicked to implement navigation; the control does not navigate automatically
  • Use SetContent(html, baseUrl) when HTML contains relative URLs
  • For email rendering, disable images and set explicit colors for readability
  • Use LoadUrlAsync with cancellation support for user-navigatable content
  • The control consumes Tab key for link navigation — use Shift+Tab to move focus away

NativeAOT

HtmlControl works under NativeAOT — a published native binary renders HTML (including CSS calc()) correctly, verified by the library's AOT smoke test.

The one caveat: its dependency AngleSharp.Css evaluates CSS calc() via reflection, so AOT-publishing an app that uses HtmlControl surfaces 4 IL2072 trim warnings (from AngleSharp.Css, not SharpConsoleUI). They're an analysis limitation, not a runtime failure. If your build treats trim warnings as errors, see NativeAOT Compatibility → HtmlControl caveat for the scoped .csproj fix. If you don't use HtmlControl, the rest of the library is AOT-clean with no action needed.

See Also

Back to Controls | Back to Main Documentation