SVG Text
<SVGText> is the text building block for custom SVG elements in @joint/react. Use a plain <text> node for short one-line labels. Reach for <SVGText> when text needs wrapping, ellipsis, multiline alignment, or richer styling inside an SVG shape.
When text should drive an element's size rather than fit inside a fixed one, pair <SVGText> with Measuring Elements.
When to use itโ
- Use plain
<text>when the label is short and never wraps - Use
<SVGText>when text must stay inside a bounded SVG area - Combine
<SVGText>withuseMeasureElement()when the text should define the element size
Basic usageโ
This fixed-size task card uses useCell(selectElementSize) for the current node dimensions and lets <SVGText> handle both line breaking and truncation. The three cards below have increasing text lengths: notice how the title clamps to one line and the description wraps and truncates with an ellipsis.
Wrapping and clampingโ
textWrap enables line breaking. You can pass true for the default behavior or an options object when the label needs clamping or ellipsis.
<SVGText width={160} textWrap>
A longer label that should wrap across multiple lines.
</SVGText>
<SVGText
width={160}
textWrap={{ ellipsis: true, maxLineCount: 2 }}
>
A longer label that should wrap, but only across two visible lines.
</SVGText>
width defines the wrapping box. maxLineCount is enough when you only want to cap the number of visible lines. height becomes useful when the text also needs to fit a fixed vertical area inside the shape.
If you omit width while textWrap is enabled, <SVGText> can fall back to the current element width. In practice, an explicit inner width is usually clearer because most custom nodes want text padding rather than full edge-to-edge wrapping.
Positioning and alignmentโ
x and y set the text anchor point. textAnchor controls horizontal alignment, and textVerticalAnchor controls vertical alignment inside the text box.
textAnchor | Horizontal | textVerticalAnchor | Vertical |
|---|---|---|---|
"start" | Left-aligned with x | "top" | Top-aligned with y |
"middle" | Centered with x | "middle" | Centered with y |
"end" | Right-aligned with x | "bottom" | Bottom-aligned with y |
Toggle the buttons below to see how each combination positions the text. The blue dot marks the anchor point, and the dashed lines show the alignment axes.
Combining with useMeasureElement()โ
If text should define the node size instead of fitting inside a fixed one, combine <SVGText> with useMeasureElement() in Measuring Elements.
import { SVGText, useMeasureElement } from '@joint/react';
import { useRef } from 'react';
function StatusBadge({ label }: { label: string }) {
const groupRef = useRef<SVGGElement>(null);
const { width, height } = useMeasureElement(groupRef, {
transform: ({ width: measuredWidth, height: measuredHeight }) => ({
width: measuredWidth + 24,
height: measuredHeight + 16,
}),
});
return (
<>
<rect width={width} height={height} rx={999} fill="#1d4ed8" />
<g ref={groupRef} transform="translate(12, 8)">
<SVGText fill="white">{label}</SVGText>
</g>
</>
);
}
Here <SVGText> still handles the SVG text rendering, while useMeasureElement() turns that rendered content into the final element size.
Advanced text optionsโ
<SVGText> also supports a few higher-level text features that are awkward to build by hand with raw SVG:
annotationsfor styling ranges of text without manually creating<tspan>nodesdisplayEmptywhen an empty text node should still stay renderedtextPathwhen the text should follow an SVG path
<SVGText
fill="#e2e8f0"
annotations={[{ start: 0, end: 5, attrs: { fill: '#22c55e', fontWeight: 700 } }]}
>
READY ยท build-184
</SVGText>
For most custom elements, wrapping and alignment are the main reasons to use <SVGText>. The advanced options are there when the label needs more than a single uniform style.
Practical notesโ
childrenmust be a string- Use
<SVGText>insiderenderElementor a component rendered from it - Start with explicit
widthandheightvalues when you are building a bounded label area - Do not also call
useCell(selectElementSize)in the same component when measuring withuseMeasureElement;useMeasureElementalready returns the live size