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

HTML elements support text, badges, layouts, gradients, CSS/WAAPI animation, and a restricted inline SVG subset for vector shapes. Existing SVG elements remain supported; their standalone markup rules differ from the stricter SVG subtree allowed in html.

Interface​

interface TextItem {
type: "TEXT";
text?: string;
html?: string;
style?: Record<string, string | number>;
fitToBox?: boolean;
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, plus the SVG subset below. HTML elements accept 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.

Inline SVG in HTML​

html accepts geometry-only SVG: svg, g, defs, gradients/stops, paths, circles, ellipses, rectangles, lines, polylines, and polygons. Use supported geometry/paint attributes and local gradient references such as url(#brand). Scripts, event handlers, foreignObject, use, image, external resources, and SVG animation tags are rejected. Use HTML text around the SVG for labels, and customCode CSS/JavaScript for animation.

Text sizing and overflow​

Set width and height in pixels when text must fit a defined box. By default, the renderer preserves the authored typography, so long copy can be clipped. Set fitToBox: true to shrink typography just enough to keep painted text inside the declared box. Text that already fits is unchanged; this option does not enlarge text or replace intentional layout and line breaks. Fitting reduces type metrics to no less than half their authored size and does not move fixed layout geometry. Very long copy or fixed negative offsets can still overflow; inspect representative variable values and the final render.

This element fragment belongs in payload.visuals:

{
"type": "TEXT",
"text": "A product title that may become longer",
"width": 800,
"height": 160,
"position": "center-center",
"fitToBox": true,
"style": { "fontFamily": "Poppins", "fontSize": 64, "color": "#111111" }
}

See Layout for box sizing, anchors, and margins.

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 (enterBegin → exitEnd) does not increase capture time. Billing still uses the final video's duration and resolution, so a longer output can cost more credits. 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. The following animation examples are element fragments for payload.visuals. Each recorded preview includes its own complete project payload:

{
"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
}
}
{
"name": "docs-text-css-pulse",
"width": 960,
"height": 540,
"duration": 5,
"backgroundColor": "#140b2e",
"visuals": [
{
"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
}
}
]
}
Rendered by Zvid
The pulsing badge, rendered by Zvid
Watch video

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' });"
}
}
{
"name": "docs-text-waapi",
"width": 960,
"height": 540,
"duration": 5,
"backgroundColor": "#140b2e",
"visuals": [
{
"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' });"
}
}
]
}
Rendered by Zvid
Web Animations API motion, rendered by Zvid
Watch video

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
}
}
{
"name": "docs-text-css-ring",
"width": 960,
"height": 540,
"duration": 5,
"backgroundColor": "#140b2e",
"visuals": [
{
"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
}
}
]
}
Rendered by Zvid
A CSS-only loading ring, rendered by Zvid
Watch video

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​

These are element fragments for payload.visuals, not complete projects. For video-only timing fields, use a video project with a long enough duration.

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.