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
textand style it with thestyleobject. - HTML — set
htmlwith your own markup. With the optionalcustomCodefield you can attach native CSS and JavaScript, turning aTEXTelement into a fully styled, animated mini web page.
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
| Property | Type | Notes |
|---|---|---|
type | "TEXT" | Case-insensitive in API validation. |
text or html | string | At least one must contain content. |
Placement, timing, layering, and animation fields are shared by all visual elements — see Common Element Properties.
Content
textis plain text. The API rejects<and>in this field.htmlis your own HTML markup and takes priority overtextwhen 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, andcanvas, withstyle,class,src,alt,width, andheightattributes.imgsources must be public http(s) URLs or inline rasterdata:image/…URIs.styleaccepts CSS property names and string or number values; it styles the element's root container.customCodeattaches 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.
| Field | Type | Notes |
|---|---|---|
css | string | Raw CSS injected into the page. Define @keyframes here and target the classes you used in the element's html. |
js | string | JavaScript run after the content loads. Use it to manipulate the DOM or drive animations with the Web Animations API. |
animationDuration | number | Length 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 — 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
}
}
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' });"
}
}
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
}
}
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-formsetTimeout/setInterval, dynamicimport()/require;localStorage/sessionStorage/indexedDB,document.cookie; service workers and Web Workers;window.openand navigation (location = ...);document.write. - CSS:
@import,expression(...),-moz-binding,javascript:URLs, andurl(...)pointing at any non-data:resource. Inlineurl(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.