Text & Rich Text

Blinc provides two main elements for displaying text: text() for plain text and rich_text() for inline-formatted text with HTML-like markup.

For headings, paragraphs, captions and inline composition, see the Typography helpers guide.

Plain Text

The text() element is the simplest way to display text:

#![allow(unused)]
fn main() {
use blinc::layout::prelude::*;

// Basic text
text("Hello, World!")

// Styled text
text("Styled text")
    .size(24.0)
    .color(Color::BLUE)
    .bold()
    .italic()

// Text with decorations
text("Underlined and struck")
    .underline()
    .strikethrough()
}

Text Properties

MethodDescription
.size(f32)Font size in pixels
.color(Color)Text color
.bold()Bold weight
.italic()Italic style
.underline()Underline decoration
.strikethrough()Strikethrough decoration
.align(TextAlign)Horizontal alignment (Left, Center, Right)
.v_align(TextVerticalAlign)Vertical alignment (Top, Middle, Bottom)
.font_family(FontFamily)Custom font family
.line_height(f32)Line height multiplier (default: 1.2)
.wrap(bool)Enable/disable text wrapping

Rich Text

The rich_text() element supports inline formatting using HTML-like tags. This is ideal for text that needs mixed styling within a single block.

#![allow(unused)]
fn main() {
use blinc::layout::prelude::*;

// Basic formatting
rich_text("This has <b>bold</b> and <i>italic</i> text.")
    .size(16.0)
    .default_color(Color::WHITE)

// Nested tags
rich_text("<b>Bold with <i>nested italic</i></b>")

// Inline colors
rich_text(r#"Colors: <span color="#FF0000">red</span> and <span color="blue">blue</span>"#)

// Links (clickable, opens in browser)
rich_text(r#"Visit <a href="https://example.com">our website</a> for more info."#)
}

Supported Tags

TagEffect
<b>, <strong>Bold text
<i>, <em>Italic text
<u>Underlined text
<s>, <strike>, <del>Strikethrough text
<a href="url">Clickable link (auto-underlined)
<span color="...">Inline color

Color Formats

The <span color="..."> tag supports multiple color formats:

#![allow(unused)]
fn main() {
// Hex colors
rich_text(r#"<span color="#FF0000">Red</span>"#)
rich_text(r#"<span color="#F00">Short hex</span>"#)
rich_text(r#"<span color="#FF000080">With alpha</span>"#)

// Named colors (CSS subset)
rich_text(r#"<span color="crimson">Crimson</span>"#)
rich_text(r#"<span color="steelblue">Steel Blue</span>"#)

// RGB/RGBA
rich_text(r#"<span color="rgb(255, 128, 0)">Orange</span>"#)
}

Supported named colors: black, white, red, green, blue, yellow, cyan, magenta, gray, silver, maroon, olive, navy, purple, teal, orange, pink, brown, lime, coral, gold, indigo, violet, crimson, salmon, tomato, skyblue, steelblue, transparent

HTML Entity Decoding

Rich text automatically decodes common HTML entities:

#![allow(unused)]
fn main() {
rich_text("Use &lt;b&gt; for bold")  // Renders: Use <b> for bold
rich_text("&copy; 2024 &bull; All Rights Reserved &trade;")
rich_text("&ldquo;Smart quotes&rdquo; &mdash; and &hellip;")
}

Supported entities: &lt;, &gt;, &amp;, &quot;, &apos;, &nbsp;, &copy;, &reg;, &trade;, &mdash;, &ndash;, &hellip;, &lsquo;, &rsquo;, &ldquo;, &rdquo;, &bull;, &middot;, and numeric entities (&#65;, &#x41;)

Range-Based API

For programmatic control, use the range-based API with byte indices:

#![allow(unused)]
fn main() {
// Style specific byte ranges
rich_text("Hello World")
    .bold_range(0..5)           // "Hello" is bold
    .color_range(6..11, Color::CYAN)  // "World" is cyan
    .size(18.0)
    .default_color(Color::WHITE)

// Multiple overlapping styles
rich_text("Important Notice: Please read carefully!")
    .bold_range(0..16)           // "Important Notice" bold
    .color_range(0..9, Color::ORANGE)  // "Important" orange
    .underline_range(18..39)     // "Please read carefully" underlined
}

Available range methods:

  • .bold_range(Range<usize>)
  • .italic_range(Range<usize>)
  • .underline_range(Range<usize>)
  • .strikethrough_range(Range<usize>)
  • .color_range(Range<usize>, Color)
  • .link_range(Range<usize>, url: &str)

Links in rich text are fully interactive:

  • Click to open: Clicking a link opens the URL in the system's default browser
  • Pointer cursor: The cursor changes to a pointer when hovering over links
  • Auto-underlined: Links are automatically underlined for visibility
#![allow(unused)]
fn main() {
rich_text(r#"
    Check the <a href="https://docs.example.com">documentation</a>
    or view the <a href="https://github.com/example">source code</a>.
"#)
    .size(14.0)
    .default_color(Color::WHITE)
}

For simple clickable text, use the link() widget:

#![allow(unused)]
fn main() {
// Default behavior - opens URL in browser
link("Click here", "https://example.com")

// Custom styling
link("Styled link", "https://example.com")
    .font_size(18.0)
    .text_color(Color::CYAN)
    .no_underline()

// Underline only on hover
link("Hover to see underline", "https://example.com")
    .underline_on_hover()
}

Default colours

Links, blockquotes, rules, lists and tables take their colours from the default stylesheet's rules, so a stylesheet restyles them:

ClassElementDefault
blinc-linka link()--text-link, --primary-hover on hover
blinc-blockquotea blockquote()--surface-overlay fill, --border left edge
blinc-hran hr()--border
blinc-list-markera bullet or number--text-tertiary
blinc-task-boxa task item's box, checked when done--text-tertiary
blinc-thead, blinc-tfoota table's head and foot--surface-overlay
blinc-th, blinc-tdtext from th_text(), td_text()--text-primary, --text-secondary
blinc-tr-altan odd row from striped_tr()--accent-subtle
.blinc-link { color: #0ea5e9; }
.blinc-tr-alt { background: transparent; }

A colour given to the widget (text_color, hr_color, header_bg, a config colour) is set on the element and wins over the rule.

From StyledText

For integration with syntax highlighting or markdown rendering, create rich text from a pre-built StyledText:

#![allow(unused)]
fn main() {
use blinc::layout::styled_text::{StyledText, StyledLine, TextSpan};

let styled = StyledText {
    lines: vec![
        StyledLine {
            text: "Hello World".to_string(),
            spans: vec![
                TextSpan {
                    start: 0,
                    end: 5,
                    bold: true,
                    color: Color::RED,
                    ..Default::default()
                },
            ],
        },
    ],
};

rich_text_styled(styled)
    .size(16.0)
    .default_color(Color::WHITE)
}

Example

Here's a complete example demonstrating various text features:

#![allow(unused)]
fn main() {
use blinc::app::prelude::*;
use blinc::core::Color;

fn demo_ui() -> impl ElementBuilder {
    div()
        .flex_col()
        .gap(16.0)
        .p(20.0)
        // Plain text
        .child(
            text("Plain Text Example")
                .size(24.0)
                .color(Color::WHITE)
                .bold()
        )
        // Rich text with inline formatting
        .child(
            rich_text("This is <b>bold</b>, <i>italic</i>, and <span color=\"#00FF00\">green</span>.")
                .size(16.0)
                .default_color(Color::WHITE)
        )
        // Interactive link
        .child(
            rich_text(r#"Visit <a href="https://github.com">GitHub</a> for more."#)
                .size(16.0)
                .default_color(Color::WHITE)
        )
        // Range-based styling
        .child(
            rich_text("Programmatic styling with ranges")
                .bold_range(0..13)
                .color_range(14..21, Color::CYAN)
                .underline_range(22..32)
                .size(16.0)
                .default_color(Color::WHITE)
        )
}
}

Run the rich text demo to see all features in action:

cargo run -p blinc_app_examples --example rich_text_demo --features windowed