Skip to content

RichText

RichText (from scenerystack/scenery) renders a string containing a constrained, security-conscious subset of HTML-like markup, splitting it internally into multiple Text children. Use it when a single string needs mixed styling — bold/italic runs, sub/superscripts, links, line breaks — that plain Text can't express. Malformed markup is not accepted, and HTML entities in the content must be escaped.

ts
import { RichText } from 'scenerystack/scenery';
import { PhetFont } from 'scenerystack/scenery-phet';

const description = new RichText(
  'RichText supports <b>bold</b>, <i>italic</i>, and H<sub>2</sub>O-style subscripts.',
  { font: new PhetFont( 16 ), fill: 'black' }
);

const withLink = new RichText(
  'See <a href="{{phetWebsite}}">our website</a> for more.',
  {
    links: {
      phetWebsite: 'https://phet.colorado.edu'
    }
  }
);

Supported markup

<b>/<strong>, <i>/<em>, <sub>, <sup>, <u>, <s>, <br>, <span style="color: ...; font-size: ...; font-family: ...;">, <span dir="ltr"/"rtl">, <a href="..."> links, and <node id="..."> for embedding an arbitrary Node inline.

Options

OptionEffect
string / stringPropertyThe markup string to render, same as Text
font, fill, stroke, lineWidthBase styling applied to unmarked text (per-tag colors override fill locally)
linksEither true (embed hrefs directly from the markup) or a Record<string, string | (() => void)> mapping placeholder names to real URLs/callbacks — the default (safer) way to allow links
linkFillFill color used specifically for link text
linkEventsHandledWhether clicking a link calls event.handle(), stopping propagation
nodesA Record<string, Node> of Nodes to splice in for <node id="..."> tags
tagsA Record<string, (node: Node) => Node> for custom wrapping tags, e.g. <blur>...</blur>
align'left', 'center', or 'right' alignment across wrapped lines
lineWrapMaximum line width (in local coordinates) before wrapping; null disables wrapping
leadingExtra vertical spacing between wrapped lines
subScale, subXSpacing, subYOffset, supScale, supXSpacing, supYOffsetFine-tune subscript/superscript sizing and placement
underlineLineWidth, underlineHeightScale, strikethroughLineWidth, strikethroughHeightScaleFine-tune <u>/<s> rendering

RichText also accepts the full set of Node options.

Links default to being ignored, not embedded

Passing a raw <a href="https://example.com"> without a matching links map entry causes that link to be silently ignored — this is a deliberate XSS guard, since RichText content often comes from translated strings. To use literal hrefs straight from the markup, pass links: true explicitly; to remap placeholders to safe destinations, use the links: { placeholder: url } form shown above.