Skip to main content

Text & HTML Elements

TEXT elements render text or HTML into a visual layer and compose it into the video. They have two modes:

  • Plain text — set text and style it with the style object.
  • HTML — set html with your own markup. With the optional customCode field you can attach native CSS and JavaScript, turning a TEXT element into a fully styled, animated mini web page.
HTML vs SVG elements

With native CSS and JavaScript, an HTML element covers nearly everything the deprecated SVG element was used for — text, badges, layout, gradients, CSS/WAAPI animation. Note that html accepts a safe tag subset (see below) which does not include inline <svg> markup: for raw vector shapes, use an SVG element or reference an SVG file from an IMAGE element.

Interface

interface TextItem {
type: "TEXT";
text?: string;
html?: string;
style?: Record<string, string | number>;
customCode?: CustomCode;
x?: number;
y?: number;
width?: number;
height?: number;
anchor?: Anchor;
position?: PositionPreset;
enterBegin?: number;
enterEnd?: number;
exitBegin?: number;
exitEnd?: number;
track?: number;
opacity?: number;
angle?: number;
flipV?: boolean;
flipH?: boolean;
enterAnimation?: XFadeEffect | null;
exitAnimation?: XFadeEffect | null;
}

interface CustomCode {
css?: string;
js?: string;
animationDuration?: number;
}

Required Fields

PropertyTypeNotes
type"TEXT"Case-insensitive in API validation.
text or htmlstringAt least one must contain content.

Placement, timing, layering, and animation fields are shared by all visual elements — see Common Element Properties.

Content

  • text is plain text. The API rejects < and > in this field.
  • html is your own HTML markup and takes priority over text when both are present. The hosted API accepts a safe tag subset: div, span, p, br, b, strong, i, em, u, s, ul, ol, li, img, and canvas, with style, class, src, alt, width, and height attributes. img sources must be public http(s) URLs or inline raster data:image/… URIs.
  • style accepts CSS property names and string or number values; it styles the element's root container.
  • customCode attaches native CSS and JavaScript — see below.

Native CSS & JavaScript (customCode)

customCode lets you style, animate, and script the element with the same tools you use on the web. The element's html is rendered in a headless browser, your css and js run against it, and the result is captured as the element's visual layer.

FieldTypeNotes
cssstringRaw CSS injected into the page. Define @keyframes here and target the classes you used in the element's html.
jsstringJavaScript run after the content loads. Use it to manipulate the DOM or drive animations with the Web Animations API.
animationDurationnumberLength of one animation loop in seconds (max 15). Only that loop is captured and then looped to fill the element's timeline. Auto-detected when omitted.

How animation capture works

When customCode is present, Zvid captures a single loop of your animation and lets FFmpeg repeat it for the element's on-screen duration. This means the element's timeline length (enterBeginexitEnd) does not increase capture time — a 1-second loop costs the same whether the element is on screen for 3 seconds or 30. Set animationDuration to the exact length of one loop for a seamless repeat; omit it to let Zvid auto-detect.

Example: CSS keyframe animation

A pulsing badge — no text, just HTML targeted by a CSS class:

{
"type": "TEXT",
"html": "<div class=\"badge\">LIMITED OFFER</div>",
"position": "center-center",
"enterBegin": 0,
"exitEnd": 5,
"customCode": {
"css": ".badge { color: #ffffff; font-family: Poppins; font-size: 72px; padding: 20px 40px; background: #e11d48; border-radius: 16px; animation: pulse 1s ease-in-out infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); } }",
"animationDuration": 1
}
}
The pulsing badge, rendered by Zvid

Example: JavaScript with the Web Animations API

Use js and element.animate(...) when you want to build motion programmatically:

{
"type": "TEXT",
"html": "<div class=\"price\">$9.99</div>",
"position": "center-center",
"enterBegin": 0,
"exitEnd": 5,
"customCode": {
"css": ".price { color: #fbbf24; font-family: Poppins; font-size: 96px; font-weight: 700; }",
"js": "document.querySelector('.price').animate([{ transform: 'translateY(0)' }, { transform: 'translateY(-30px)' }, { transform: 'translateY(0)' }], { duration: 800, iterations: Infinity, easing: 'ease-in-out' });"
}
}
Web Animations API motion, rendered by Zvid

Example: a pure-CSS spinner

Vector-looking graphics don't need markup at all — borders, gradients, and border-radius go a long way:

{
"type": "TEXT",
"html": "<div class=\"ring\"></div>",
"width": 220,
"height": 220,
"position": "center-center",
"enterBegin": 0,
"exitEnd": 5,
"customCode": {
"css": ".ring { width: 160px; height: 160px; border-radius: 50%; border: 14px solid rgba(34,211,238,0.25); border-top-color: #22d3ee; animation: spin 1.5s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }",
"animationDuration": 1.5
}
}
A CSS-only loading ring, rendered by Zvid

customCode safety

customCode runs inside the rendering browser, so it may only style, script, and animate the element's own content. The renderer rejects anything that could reach the network, filesystem, or browser storage, including:

  • JavaScript: fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon; eval, new Function, string-form setTimeout/setInterval, dynamic import()/require; localStorage/sessionStorage/indexedDB, document.cookie; service workers and Web Workers; window.open and navigation (location = ...); document.write.
  • CSS: @import, expression(...), -moz-binding, javascript: URLs, and url(...) pointing at any non-data: resource. Inline url(data:...) is allowed.

Keep your animations self-contained — define keyframes, target your own classes, and use the Web Animations API for dynamic motion.

Examples

Plain Text

{
"type": "TEXT",
"text": "Hello World",
"x": 640,
"y": 360,
"anchor": "center-center",
"style": {
"fontSize": 48,
"color": "#000000",
"textAlign": "center"
}
}

Styled Text With Animation

{
"type": "TEXT",
"text": "Welcome to Zvid",
"position": "center-center",
"enterBegin": 0,
"enterEnd": 1,
"exitBegin": 9,
"exitEnd": 10,
"enterAnimation": "fade",
"exitAnimation": "fade",
"style": {
"fontSize": 36,
"color": "#ff6b35",
"textAlign": "center",
"fontWeight": "bold"
}
}

HTML With Inline Styles

{
"type": "TEXT",
"html": "<div style=\"text-align:center\"><p style=\"color:#ff6b35; margin:0; font-size:48px\">Big Title</p><p style=\"color:#666666; font-size:18px\">Subtitle text</p></div>",
"position": "center-center",
"enterBegin": 0,
"enterEnd": 2,
"exitBegin": 8,
"exitEnd": 10
}

Watermark

{
"type": "TEXT",
"text": "WATERMARK",
"x": 660,
"y": 340,
"anchor": "center-center",
"angle": 45,
"opacity": 0.3,
"track": 10,
"style": {
"fontSize": 72,
"color": "#000000",
"fontFamily": "Anton",
"textAlign": "center"
}
}

Font Handling

Use exact Google Fonts family names, such as Poppins, Montserrat, Roboto, Open Sans, Lato, Playfair Display, Oswald, or Bebas Neue. Set the family in style.fontFamily (plain text / HTML) or in your customCode.css.