Skip to content

Typography & Text Styling ​

RTXUI supports rich text styling including colors, alignment, decorations, bold/strong emphasis, and opacity. These are applied via CSS properties in <style> blocks, just like in the web.


Colors ​

RTXUI supports multiple color formats for color and background-color properties:

FormatExample
Named keywordsred, navy, silver, fuchsia, …
Hex (short)#f0f, #0ff
Hex (full)#ff3366, #151520
Hex with alpha#00ffcc88, #ff000080
rgb()rgb(255, 0, 128)
rgba()rgba(255, 0, 0, 0.5)

The 16 standard CSS color keywords are supported (black, white, red, green, blue, yellow, aqua, fuchsia, gray, silver, maroon, olive, navy, purple, teal, lime).

Fullscreen Demo
cpp
// Copyright 2026 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
//
// Foreground and background colors.
//
// Colors accept rgb(), #rrggbb and named forms, and are composed into a swatch
// grid by a small reusable child component.
#include <rtxui/rtxui.hpp>

using namespace rtxui;

class ColorBox : public Component<ColorBox> {
 public:
  struct Props {
    std::string text;
    std::string bg_color;
    std::string fg_color = "black";
  } props;

  std::string_view view = R"html(
      <div class="box-content">
        {text}
      </div>

      <style>
        self {
          --bg: rgb(13, 17, 23);

          background-color: var(--bg);
          display: block;
          /* `flex: 1` (grow 1, shrink 1, basis 0) rather than flex-grow alone:
             with the default `flex-basis: auto` each swatch would start at its
             label's width and only share the leftover space, so the swatches
             came out all different sizes. */
          flex: 1;
        }
        .box-content {
          padding-left: 2;
          padding-right: 2;
          padding-top: 1;
          padding-bottom: 1;
          color: {fg_color};
          background-color: {bg_color};
        }
      </style>
    )html";

  ColorBox() {
    Bind(props.text);
    Bind(props.bg_color);
    Bind(props.fg_color);
  }
};

class ColorDemo : public Component<ColorDemo> {
 public:
  std::string_view view = R"html(
      <div class="container">
        <h1>RTXUI Color System Demo</h1>
        <p>Scroll to see standard keywords, hex codes, rgb(), and rgba() syntaxes.</p>
        
        <div class="h2">1. Standard Keywords (16-color base)</div>
        <div class="row">
          <ColorBox text="black" bg_color="black" fg_color="white"></ColorBox>
          <ColorBox text="gray" bg_color="gray" fg_color="white"></ColorBox>
          <ColorBox text="silver" bg_color="silver" fg_color="black"></ColorBox>
          <ColorBox text="white" bg_color="white" fg_color="black"></ColorBox>
        </div>
        <div class="row">
          <ColorBox text="maroon" bg_color="maroon" fg_color="white"></ColorBox>
          <ColorBox text="red" bg_color="red" fg_color="white"></ColorBox>
          <ColorBox text="purple" bg_color="purple" fg_color="white"></ColorBox>
          <ColorBox text="fuchsia" bg_color="fuchsia" fg_color="white"></ColorBox>
        </div>
        <div class="row">
          <ColorBox text="green" bg_color="green" fg_color="black"></ColorBox>
          <ColorBox text="lime" bg_color="lime" fg_color="black"></ColorBox>
          <ColorBox text="olive" bg_color="olive" fg_color="white"></ColorBox>
          <ColorBox text="yellow" bg_color="yellow" fg_color="black"></ColorBox>
        </div>
        <div class="row">
          <ColorBox text="navy" bg_color="navy" fg_color="white"></ColorBox>
          <ColorBox text="blue" bg_color="blue" fg_color="white"></ColorBox>
          <ColorBox text="teal" bg_color="teal" fg_color="white"></ColorBox>
          <ColorBox text="aqua" bg_color="aqua" fg_color="black"></ColorBox>
        </div>

        <div class="h2">2. Hex Colors (#RGB, #RRGGBB, #RGBA, #RRGGBBAA)</div>
        <div class="row">
          <ColorBox text="#f0f" bg_color="#f0f" fg_color="white"></ColorBox>
          <ColorBox text="#0ff" bg_color="#0ff" fg_color="black"></ColorBox>
          <ColorBox text="#ff3366" bg_color="#ff3366" fg_color="white"></ColorBox>
          <ColorBox text="#33cc66" bg_color="#33cc66" fg_color="black"></ColorBox>
        </div>
        <div class="row">
          <ColorBox text="#ffb3ba" bg_color="#ffb3ba" fg_color="black"></ColorBox>
          <ColorBox text="#ffdfba" bg_color="#ffdfba" fg_color="black"></ColorBox>
          <ColorBox text="#ffffba" bg_color="#ffffba" fg_color="black"></ColorBox>
          <ColorBox text="#baffc9" bg_color="#baffc9" fg_color="black"></ColorBox>
        </div>
        <div class="row">
          <ColorBox text="#bae1ff" bg_color="#bae1ff" fg_color="black"></ColorBox>
          <ColorBox text="#e8c4ff" bg_color="#e8c4ff" fg_color="black"></ColorBox>
          <ColorBox text="#ffd3e8" bg_color="#ffd3e8" fg_color="black"></ColorBox>
          <ColorBox text="#cbf3f0" bg_color="#cbf3f0" fg_color="black"></ColorBox>
        </div>
        <div class="row">
          <ColorBox text="#ff007f" bg_color="#ff007f" fg_color="white"></ColorBox>
          <ColorBox text="#39ff14" bg_color="#39ff14" fg_color="black"></ColorBox>
          <ColorBox text="#00ffcc88" bg_color="#00ffcc88" fg_color="black"></ColorBox>
          <ColorBox text="#151520" bg_color="#151520" fg_color="white"></ColorBox>
        </div>

        <div class="h2">3. RGB Colors</div>
        <div class="row">
          <ColorBox text="rgb(255,0,128)" bg_color="rgb(255,0,128)" fg_color="white"></ColorBox>
          <ColorBox text="rgb(0,255,128)" bg_color="rgb(0,255,128)" fg_color="black"></ColorBox>
          <ColorBox text="rgb(128,0,255)" bg_color="rgb(128,0,255)" fg_color="white"></ColorBox>
          <ColorBox text="rgb(255,128,0)" bg_color="rgb(255,128,0)" fg_color="black"></ColorBox>
        </div>

        <div class="h2">4. RGBA Colors with Alpha Blending</div>
        <div class="row">
          <ColorBox text="rgba(255,0,0,0.5)" bg_color="rgba(255,0,0,0.5)" fg_color="white"></ColorBox>
          <ColorBox text="rgba(0,0,255,0.3)" bg_color="rgba(0,0,255,0.3)" fg_color="white"></ColorBox>
          <ColorBox text="rgba(0,255,0,0.7)" bg_color="rgba(0,255,0,0.7)" fg_color="black"></ColorBox>
          <ColorBox text="rgba(255,255,255,0.2)" bg_color="rgba(255,255,255,0.2)" fg_color="white"></ColorBox>
        </div>
      </div>

      <style>
        self {
          display: block;
          padding: 2;
          background-color: var(--bg);
          color: #eee;
          height: 22;
          overflow-y: scroll;
        }
        h1 {
          color: #ffcc00;
        }
        .h2 {
          display: block;
          color: #00ccff;
          margin-top: 2;
          margin-bottom: 1;
          font-weight: bold;
        }
        p {
          margin-bottom: 1;
        }
        .container {
          display: block;
          max-width: 80;
          margin: 0 auto;
        }
        .row {
          display: flex;
          width: 100%;
          gap: 2;
          margin-bottom: 1;
        }
      </style>
    )html";

  ColorDemo() { Import<ColorBox>(); }
};

int main() {
  auto app = Ref<ColorDemo>::New();
  Screen screen(app);
  screen.Loop();
  return 0;
}

Weight and Style ​

Terminals render four text intensities and an italic face; RTXUI maps the standard CSS properties onto them:

css
font-weight: bold;      /* bold — also: bolder, or numbers >= 600 */
font-weight: lighter;   /* dim  — also: numbers <= 300 */
font-weight: normal;
font-style: italic;     /* also: oblique */

The semantic inline tags apply these for you: <b>/<strong> for bold, <i>/<em> for italic, <u> for underline, <s>/<del> for strikethrough.


Case Transformation ​

text-transform changes the rendered case without touching the underlying text. It is inherited.

css
text-transform: uppercase;   /* MENU */
text-transform: lowercase;   /* menu */
text-transform: capitalize;  /* Menu Item */

ASCII letters are transformed; other characters pass through unchanged.


Spacing ​

letter-spacing inserts blank cells between characters, and line-height sets how many rows each line occupies. Both take whole numbers of cells and are inherited:

css
h1 { letter-spacing: 1; }   /* H E A D I N G */
p  { line-height: 2; }      /* one blank row between lines */

The cells added by letter-spacing are non-breaking: a spaced word never wraps in the middle, while the gaps between words stay breakable. line-height is a minimum — a taller inline element still grows its line.


Text Alignment ​

Use text-align to control horizontal text placement within a block element:

css
text-align: left;    /* Default */
text-align: center;
text-align: right;
text-align: justify;

justify widens the spaces of soft-wrapped lines so each fills the content width; the last line, and lines ended by an explicit newline, keep their natural width. The alignment is inherited by child elements.

Fullscreen Demo
cpp
// Copyright 2026 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
//
// text-align: left, center and right.
#include <rtxui/rtxui.hpp>

using namespace rtxui;

class TextAlignDemo : public Component<TextAlignDemo> {
 public:
  std::string_view view = R"html(
      <div>
        <h1>RTXUI Text Alignment Demo</h1>
        <p>Demonstrates text-align left, right, and center horizontal alignment.</p>
        
        <div class="card left-align">
          <div class="title">text-align: left</div>
          <div class="content">This text is aligned to the left of the container.</div>
        </div>

        <div class="card center-align">
          <div class="title">text-align: center</div>
          <div class="content">This text is aligned to the center of the container.</div>
        </div>

        <div class="card right-align">
          <div class="title">text-align: right</div>
          <div class="content">This text is aligned to the right of the container.</div>
        </div>
      </div>

      <style>
        self {

          display: block;
          padding: 1;
          background-color: rgb(13, 17, 23);
          color: white;
          width: 50;
          height: 18;
          overflow-y: scroll;
        }
        h1 {
          color: rgb(56, 189, 248);
          font-weight: bold;
          text-align: center;
        }
        p {
          margin-bottom: 1;
          color: rgb(139, 148, 158);
          text-align: center;
        }
        .card {
          display: block;
          margin-top: 1;
          padding: 1;
          border: tall;
          border-color: rgb(48, 54, 61);
        }
        .title {
          font-weight: bold;
          color: rgb(121, 192, 255);
          margin-bottom: 1;
        }
        .left-align {
          text-align: left;
        }
        .center-align {
          text-align: center;
        }
        .right-align {
          text-align: right;
        }
      </style>
    )html";
};

int main() {
  auto app = Ref<TextAlignDemo>::New();
  Screen screen(app);
  screen.Loop();
  return 0;
}

Text Decoration ​

Use text-decoration to add visual emphasis to text. Multiple decorations can be combined by separating them with spaces.

ValueEffect
underlineSingle underline
double-underlineDouble underline
line-through / strikethroughHorizontal line through text
blinkBlinking text (terminal support varies)
noneRemove decorations

Combine multiple decorations:

css
text-decoration: double-underline strikethrough;
Fullscreen Demo
cpp
// Copyright 2026 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
//
// Text decoration: bold, dim, italic, underline and strikethrough.
#include <rtxui/rtxui.hpp>

using namespace rtxui;

class TextDecorationDemo : public Component<TextDecorationDemo> {
 public:
  std::string_view view = R"html(
      <div class="content">
        <h1>RTXUI Text Decoration Demo</h1>
        <p>Demonstrates various text-decoration styling attributes supported by the layout and painting engine.</p>
        
        <div class="card">
          <div class="title">text-decoration: underline</div>
          <div class="content underline-text">This text has a single underline.</div>
        </div>

        <div class="card">
          <div class="title">text-decoration: double-underline</div>
          <div class="content double-underline-text">This text has a double underline.</div>
        </div>

        <div class="card">
          <div class="title">text-decoration: line-through / strikethrough</div>
          <div class="content strikethrough-text">This text has a horizontal line running through it.</div>
        </div>

        <div class="card">
          <div class="title">text-decoration: blink</div>
          <div class="content blink-text">This text is blinking.</div>
        </div>

        <div class="card">
          <div class="title">Combined Styles</div>
          <div class="content combined-text">This text is bold, strikethrough, and double-underlined!</div>
        </div>
      </div>

      <style>
        self {

          display: block;
          padding: 1;
          background-color: rgb(13, 17, 23);
          color: white;
          overflow-y: scroll;
        }

        .content {
          display: block;
          max-width: 60;
          max-height: 100%;
          margin: 0 auto;
        }

        h1 {
          color: rgb(100, 180, 255);
          font-weight: bold;
        }
        p {
          margin-bottom: 1;
          color: rgb(140, 160, 190);
        }
        .card {
          display: block;
          margin-top: 1;
          padding: 1;
          border: tall;
          border-color: rgb(40, 60, 90);
          background-color: rgb(20, 30, 50);
        }
        .title {
          font-weight: bold;
          color: rgb(180, 220, 255);
          margin-bottom: 1;
        }
        .content {
          color: rgb(200, 230, 255);
        }
        .underline-text {
          text-decoration: underline;
        }
        .double-underline-text {
          text-decoration: double-underline;
        }
        .strikethrough-text {
          text-decoration: strikethrough;
        }
        .blink-text {
          text-decoration: blink;
        }
        .combined-text {
          font-weight: bold;
          text-decoration: double-underline strikethrough;
        }
      </style>
    )html";
};

int main() {
  auto app = Ref<TextDecorationDemo>::New();
  Screen screen(app);
  screen.Loop();
  return 0;
}

Whitespace and Wrapping ​

white-space controls how newlines and wrapping behave inside an element:

ValueNewlinesWrapping
normal (default)Rendered as spacesWraps at spaces
nowrapRendered as spacesNever wraps
preHard line breaksNever wraps
pre-wrapHard line breaksWraps at spaces
pre-lineHard line breaks; space runs collapse to oneWraps at spaces

The <pre> element sets white-space: pre for you; <textarea> uses pre-wrap. For text that must not wrap, pair nowrap with text-overflow: ellipsis to truncate with ... instead of overflowing. Three periods rather than …, because they are one cell each and every terminal has them; in a container too narrow for the text plus the marker, as many periods are shown as fit. Truncation lands on a character boundary, so a double-width glyph is dropped whole rather than halved:

css
.crumb {
  white-space: nowrap;
  text-overflow: ellipsis;
}

Words longer than the line break at the container edge by default (overflow-wrap: anywhere — note this differs from CSS, whose default lets long words overflow). Set overflow-wrap: normal to keep such words intact and let them overflow instead:

css
.url { overflow-wrap: normal; }

Opacity ​

The opacity property controls the transparency of an element and all its children. Values range from 0.0 (fully transparent) to 1.0 (fully opaque).

css
opacity: 0.5;

Opacity is multiplicative: a child with opacity: 0.5 inside a parent with opacity: 0.5 will render at 25% opacity. Opacity can also be animated using CSS transitions.

Fullscreen Demo
cpp
// Copyright 2026 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
//
// Opacity and alpha blending, including how nested opacity compounds.
#include <rtxui/rtxui.hpp>

using namespace rtxui;

class OpacityDemo : public Component<OpacityDemo> {
 public:
  int opacity_percent = 70;

  float opacity_float() const { return opacity_percent / 100.0f; }

  std::string_view view = R"html(
      <div class="container">
        <p class="title">Opacity Property Demo</p>
        <p class="desc">
          rtxui supports the CSS 'opacity' property (0.0 to 1.0) for alpha-blending
          elements and text transparently over underlying terminal content.
        </p>

        <!-- Live Binding Control -->
        <div class="control-row">
          <span class="label">Adjust Opacity:</span>
          <slider value="{opacity_percent}" min="0" max="100" step="10" width="30" />
          <span class="value">{opacity_percent}%</span>
        </div>

        <div class="demo-grid">
          <!-- 1. Opacity Box & Inheritance -->
          <div class="card box-card">
            <h3>1. Alpha Blending & Inheritance</h3>
            <div class="parent-box" style="opacity: {opacity_float};">
              <span class="parent-label">Parent Container (opacity: {opacity_float})</span>
              <div class="child-box">
                <span class="child-label">Nested Child (inherits/accumulates opacity)</span>
              </div>
            </div>
          </div>

          <!-- 2. CSS Transitions on Opacity -->
          <div class="card transition-card">
            <h3>2. CSS Transition on Hover</h3>
            <p class="sub-desc">Hover or focus the button below to trigger a smooth opacity transition:</p>
            <div class="hover-btn" tabindex="0">Hover/Focus Me</div>
          </div>
        </div>
      </div>

      <style>
        self {
          --surface: rgb(22, 27, 34);
          --muted: rgb(139, 148, 158);
          --accent: rgb(88, 166, 255);
          --accent-bright: rgb(121, 192, 255);

          display: block;
          padding: 1;
          background-color: rgb(13, 17, 23);
          color: white;
        }
        .container {
          display: block;
        }
        .title {
          display: block;
          font-weight: bold;
          color: rgb(56, 189, 248);
          margin-bottom: 1;
        }
        .desc {
          display: block;
          color: var(--muted);
          margin-bottom: 2;
        }
        .control-row {
          display: flex;
          gap: 2;
          margin-bottom: 2;
          align-items: center;
        }
        .label {
          color: rgb(56, 189, 248);
          width: 16;
        }
        .value {
          font-weight: bold;
          color: rgb(56, 189, 248);
        }
        .demo-grid {
          display: flex;
          flex-direction: row;
          gap: 2;
          width: 100%;
        }
        .card {
          flex: 1;
          display: block;
          border: tall;
          border-color: var(--surface);
          padding: 1 2;
          height: 12;
        }
        h3 {
          color: var(--accent-bright);
          font-weight: bold;
          margin-bottom: 1;
        }
        .sub-desc {
          color: var(--muted);
          margin-bottom: 2;
        }

        /* 1. Inheritance Styling */
        .parent-box {
          display: block;
          border: solid;
          border-color: var(--accent);
          background-color: rgb(30, 58, 138);
          padding: 1;
        }
        .parent-label {
          color: white;
          font-weight: bold;
        }
        .child-box {
          display: block;
          margin-top: 1;
          border: dashed;
          border-color: var(--accent-bright);
          background-color: var(--surface);
          padding: 1;
        }
        .child-label {
          color: var(--accent-bright);
        }

        /* 2. Interactive Button Styling */
        .hover-btn {
          display: block;
          border: tall;
          border-color: var(--accent);
          background-color: rgb(30, 58, 138);
          color: rgb(191, 219, 254);
          padding: 1 3;
          text-align: center;
          width: 20;
          opacity: 0.4;
          transition: opacity 0.3s ease-in-out, background-color 0.2s linear, border-color 0.2s linear;
        }
        .hover-btn:hover {
          opacity: 1.0;
          background-color: rgb(29, 78, 216);
          border-color: white;
          color: white;
        }
        .hover-btn:focus {
          border-color: var(--accent-bright);
        }
      </style>
    )html";

  OpacityDemo() {
    Bind(opacity_percent);
    BindComputed(opacity_float);
  }
};

int main() {
  auto app = Ref<OpacityDemo>::New();
  Screen screen(app);
  screen.Loop();
  return 0;
}