video Component Type
Table of Contents
Overview
The video type extends file and keeps its embedded file value contract, picker/drop/paste acquisition, import/export, singleton, list, and download behavior.
<video data-smark='{"type":"video","name":"clip"}'
width="640" height="360" controls preload="metadata"></video>
Bare <video data-smark> elements infer type: "video" automatically. Reserve the media box with width/height attributes or CSS aspect-ratio to avoid layout shift when a different clip is loaded.
Try It
These examples use small locally bundled clips so they work without a remote media host. You can replace them with your own videos in the preview. The playgroundβs Import button can also be used with an exported embedded value.
<div id="myForm">
<strong>Clip</strong>
<video data-smark='{"name":"clip"}' width="320" height="180" preload="metadata"></video>
<button data-smark='{"action":"pick","context":"clip"}'>Choose or replace video</button>
<button data-smark='{"action":"download","context":"clip"}'>Download current video</button>
</div>
const myForm = new SmarkForm(document.getElementById("myForm"), {
"value": {"clip": "/assets/video_cat_mixkit.mp4"}
});
π Try it! This first example omits native controls, so clicking the preview is the upload/replace affordance. Choose a local H.264/AAC MP4, WebM, or another format your browser supports, then use Download current video to retrieve the embedded value.
π The example starts with a small locally bundled Mixkit clip. The URL is fetched and embedded by demoValue; replace it with your own video to try the acquisition flow.
The bundled demo sources and license links are listed in video-demo-attribution.md. Thanks to the Mixkit contributors for these freely available demo clips.
Every example in this section comes with many of the following tabs:
- HTML: HTML source code of the example.
- CSS: CSS applied (if any).
- JS: JavaScript source code of the example.
- Preview: Live, sandboxed rendering of the example β fully isolated from the page styles.
- Notes: Additional notes and insights for better understanding. Don't miss itβΌοΈ
β¨ In the Preview tab, a JSON playground editor is available with handy buttons:
β¬οΈ Exportto export the form data to the JSON playground editor.β¬οΈ Importto import data from the JSON playground editor into the form.β»οΈ Resetin forms prefilled with sample data, resets the form to its default values.β Clearto clear the whole form.
π‘ The JSON playground editor is part of the SmarkForm form itself β it is just omitted from the code snippets to keep the examples focused on what matters.
π οΈ Between the tab labels and the content there is always an edit toolbar:
βοΈ Editβ activates edit mode: each source tab turns into a syntax-highlighted code editor (powered by Ace) pre-filled with the full, merged source. Changes are sandboxed β the original example is not affected.π Include playground editorβ (only visible in edit mode) controls whether the JSON playground editor is included in the preview. When toggled, the HTML and JS editors update instantly so you can see exactly what code is needed to add or remove it.βΆοΈ Runβ (only visible in edit mode) re-renders the Preview from the current editor contents and switches to the Preview tab.
Large export warning: video values are embedded as base64. Exporting a large clip into the playground textarea serializes the entire payload and can temporarily freeze the browser. This is a limitation of displaying a large JSON/data-URL value in a textarea, not a media playback requirement. Production applications should avoid rendering multi-megabyte exports in a textarea and should submit/store the value through an appropriate binary or server-side path.
Singleton With An Editable Name
<div id="myForm">
<figure class="video-card" data-smark='{"type":"video","name":"clip"}'>
<video data-smark width="320" height="180" controls></video>
<figcaption data-smark='{"action":"rename"}'>edit filename</figcaption>
<button data-smark='{"action":"pick"}'>Choose or replace video</button>
<button data-smark='{"action":"download"}'>Download</button>
</figure>
</div>
#myForm .video-card { max-width: 360px; padding: 1rem; border: 2px dashed #999; text-align: center; background: #fafafa; border-radius: .5rem; }
#myForm video { display: block; width: 100%; height: auto; }
#myForm figcaption { margin: .75rem 0; padding: .25rem; }
#myForm button { margin: .25rem; }
const myForm = new SmarkForm(document.getElementById("myForm"), {
"value": {"clip": "/assets/video_dog_mixkit.mp4"}
});
π The wrapper accepts drops and pastes, while the caption edits the exported filename. Upload a clip, replace edit filename, then use Download.
π Native controls supplies playback. Clicking the video is intentionally reserved for native playback; use the explicit Choose or replace video button to upload another clip. SmarkForm keeps the bytes unchanged and does not generate a thumbnail or modal player.
Every example in this section comes with many of the following tabs:
- HTML: HTML source code of the example.
- CSS: CSS applied (if any).
- JS: JavaScript source code of the example.
- Preview: Live, sandboxed rendering of the example β fully isolated from the page styles.
- Notes: Additional notes and insights for better understanding. Don't miss itβΌοΈ
β¨ In the Preview tab, a JSON playground editor is available with handy buttons:
β¬οΈ Exportto export the form data to the JSON playground editor.β¬οΈ Importto import data from the JSON playground editor into the form.β»οΈ Resetin forms prefilled with sample data, resets the form to its default values.β Clearto clear the whole form.
π‘ The JSON playground editor is part of the SmarkForm form itself β it is just omitted from the code snippets to keep the examples focused on what matters.
π οΈ Between the tab labels and the content there is always an edit toolbar:
βοΈ Editβ activates edit mode: each source tab turns into a syntax-highlighted code editor (powered by Ace) pre-filled with the full, merged source. Changes are sandboxed β the original example is not affected.π Include playground editorβ (only visible in edit mode) controls whether the JSON playground editor is included in the preview. When toggled, the HTML and JS editors update instantly so you can see exactly what code is needed to add or remove it.βΆοΈ Runβ (only visible in edit mode) re-renders the Preview from the current editor contents and switches to the Preview tab.
Video List
<div id="myForm">
<ul data-smark='{"type":"list","name":"clips","of":"video","min_items":0,"max_items":4}'>
<li>
<video data-smark width="240" height="135"></video>
<button data-smark='{"action":"removeItem"}'>Remove</button>
</li>
</ul>
<button data-smark='{"action":"addItem","context":"clips"}'>Add video</button>
</div>
const myForm = new SmarkForm(document.getElementById("myForm"), {
"value": {"clips": [
"/assets/video_cat_mixkit.mp4",
"/assets/video_dog_mixkit.mp4"
]}
});
π Add clips with the list picker or drop files onto the list. Video-capable lists append OS drops instead of replacing an existing item.
Every example in this section comes with many of the following tabs:
- HTML: HTML source code of the example.
- CSS: CSS applied (if any).
- JS: JavaScript source code of the example.
- Preview: Live, sandboxed rendering of the example β fully isolated from the page styles.
- Notes: Additional notes and insights for better understanding. Don't miss itβΌοΈ
β¨ In the Preview tab, a JSON playground editor is available with handy buttons:
β¬οΈ Exportto export the form data to the JSON playground editor.β¬οΈ Importto import data from the JSON playground editor into the form.β»οΈ Resetin forms prefilled with sample data, resets the form to its default values.β Clearto clear the whole form.
π‘ The JSON playground editor is part of the SmarkForm form itself β it is just omitted from the code snippets to keep the examples focused on what matters.
π οΈ Between the tab labels and the content there is always an edit toolbar:
βοΈ Editβ activates edit mode: each source tab turns into a syntax-highlighted code editor (powered by Ace) pre-filled with the full, merged source. Changes are sandboxed β the original example is not affected.π Include playground editorβ (only visible in edit mode) controls whether the JSON playground editor is included in the preview. When toggled, the HTML and JS editors update instantly so you can see exactly what code is needed to add or remove it.βΆοΈ Runβ (only visible in edit mode) re-renders the Preview from the current editor contents and switches to the Preview tab.
Form Items With Related Metadata
For richer records, make each list item a form. The list supplies of: "form", so the item wrapper does not need to repeat its type. Each item can then contain the video plus title, notes, or any other related fields.
<div id="myForm">
<ul data-smark='{"type":"list","name":"clips","of":"form","min_items":0,"max_items":4}'>
<li>
<video data-smark='{"name":"video"}' width="240" height="135"></video>
<input data-smark='{"name":"title"}' placeholder="Title">
<textarea data-smark='{"name":"notes"}' rows="2" placeholder="Notes"></textarea>
<button data-smark='{"action":"download"}'>Download video</button>
<button data-smark='{"action":"removeItem"}' title="Remove clip" aria-label="Remove clip">βοΈ</button>
</li>
</ul>
<button data-smark='{"action":"addItem","context":"clips"}'>Add clip</button>
</div>
#myForm ul { display: grid; gap: .75rem; padding: 0; list-style: none; }
#myForm li { display: grid; grid-template-columns: 240px minmax(0, 1fr); grid-template-areas: "video title" "video notes" "video remove"; gap: .5rem .75rem; align-items: start; padding: .75rem; border: 1px solid #ccc; border-radius: .5rem; }
#myForm video { grid-area: video; width: 240px; max-width: 100%; height: auto; }
#myForm input { grid-area: title; box-sizing: border-box; width: 100%; padding: .4rem; }
#myForm textarea { grid-area: notes; box-sizing: border-box; width: 100%; min-height: 5rem; padding: .4rem; resize: vertical; }
#myForm li > button { grid-area: remove; justify-self: start; padding: .2rem .45rem; }
#myForm li > button[aria-label="Remove clip"] { grid-area: remove; }
@media (max-width: 520px) {
#myForm li { grid-template-columns: 1fr; grid-template-areas: "video" "title" "notes" "remove"; }
#myForm video { width: 100%; }
}
const myForm = new SmarkForm(document.getElementById("myForm"), {
"value": {"clips": [{"video": "/assets/video_cat_mixkit.mp4", "title": "Black cat", "notes": "Replace this clip or edit its metadata."}]}
});
π Each row is one form value: the clip travels with its title and notes. The video has no native controls, so Download video lets you retrieve the embedded value. Use Add clip to create a row and Remove clip to remove the current row.
Every example in this section comes with many of the following tabs:
- HTML: HTML source code of the example.
- CSS: CSS applied (if any).
- JS: JavaScript source code of the example.
- Preview: Live, sandboxed rendering of the example β fully isolated from the page styles.
- Notes: Additional notes and insights for better understanding. Don't miss itβΌοΈ
β¨ In the Preview tab, a JSON playground editor is available with handy buttons:
β¬οΈ Exportto export the form data to the JSON playground editor.β¬οΈ Importto import data from the JSON playground editor into the form.β»οΈ Resetin forms prefilled with sample data, resets the form to its default values.β Clearto clear the whole form.
π‘ The JSON playground editor is part of the SmarkForm form itself β it is just omitted from the code snippets to keep the examples focused on what matters.
π οΈ Between the tab labels and the content there is always an edit toolbar:
βοΈ Editβ activates edit mode: each source tab turns into a syntax-highlighted code editor (powered by Ace) pre-filled with the full, merged source. Changes are sandboxed β the original example is not affected.π Include playground editorβ (only visible in edit mode) controls whether the JSON playground editor is included in the preview. When toggled, the HTML and JS editors update instantly so you can see exactly what code is needed to add or remove it.βΆοΈ Runβ (only visible in edit mode) re-renders the Preview from the current editor contents and switches to the Preview tab.
Empty State And Playback
An empty field shows an authored native poster, the placeholder option, or the generated play-button poster. A value is displayed through an embedded data: URL. The field never changes authored dimensions, classes, styles, or playback attributes.
Use native controls when the field should be a player. Without controls, smark_video_click: "pick" (the default when controls are absent) makes the video surface an upload affordance. Use smark_video_click: "play" for a programmatic player; Space toggles playback and Shift+Space still opens the picker. The field never enables autoplay.
<video data-smark='{"name":"clip","smark_video_click":"play"}'
width="640" height="360"></video>
SmarkForm does not generate a random thumbnail or open a modal player by default. Capturing a frame requires loading and seeking the media, may fail for browser-incompatible codecs, and adds work before the form is usable. Authors can use native controls or attach their own player/modal to the fieldβs value and change lifecycle; the stored value remains the original video bytes.
Keyboard And Caption Navigation
The video itself is one SmarkForm field. Enter moves to the next field and Shift+Enter moves to the previous field. When the video has focus:
- Space opens the picker in pick mode, or toggles playback in play mode.
- Shift+Space opens the picker even in play mode.
- Delete or Backspace clears the video when it has a value.
The editable filename caption and trigger buttons are normal browser controls, so Tab and Shift+Tab reach them independently. Smooth Enter/Shift+Enter navigation therefore treats the video as one field, while classic Tab navigation can enter the caption, edit its filename, and then reach upload, download, add, or remove buttons. Delete and Backspace edit the caption while the caption has focus; they clear the video when the video field itself has focus.
Validation And Options
Interactive acquisition probes the bytes with an off-DOM video element and rejects malformed media silently. Set smark_video_validate: false to disable that probe. video_maxSize rejects oversized files before reading them and dispatches cancellable smark:videoNotice.
Common options:
acceptdefaults tovideo/*and filters picker, drop, and paste input.placeholderaccepts a poster URL/data URL orfalse.smark_video_open,smark_video_drop, andsmark_video_pastedisable the corresponding interaction when set tofalse.smark_video_clearOnDeletecontrolsDelete/Backspaceclearing.smark_video_autoPickopens the picker after rendering whentrue(subject to the browserβs user-gesture policy).formatandencodingare inherited fromfile.
The type does not transcode, resize, or re-encode video. Imported values are trusted and embedded; validation applies to interactive acquisition.
Singletons And Lists
A wrapper containing exactly one inner <video> becomes a singleton. Mark an editable filename with the rename trigger action; SmarkForm sets contenteditable and synchronizes the stored filename automatically:
<figure data-smark='{"type":"video","name":"clip"}'>
<video data-smark width="320" height="180" controls></video>
<figcaption data-smark='{"action":"rename"}'></figcaption>
</figure>
Lists use of: "video" and inherit file-list acquisition and drop behavior:
<ul data-smark='{"type":"list","name":"clips","of":"video"}'>
<li data-smark='{"type":"video"}'>
<video data-smark width="240" height="135"></video>
</li>
</ul>
OS drops append video items in a video-capable list. Captions remain item-local.
When a list item is a video field, addItem can open the picker immediately as part of the userβs add action. For a form-backed list item containing several fields, use smark_video_autoPick: true on the particular video field when an automatic picker is desired. This is opt-in and browser-dependent: a picker opened after an asynchronous render may be blocked when no user gesture is active, so an explicit pick trigger remains the reliable fallback.
Browser Limits
The metadata probe confirms that the browser recognizes the media container; it cannot guarantee every codec will play. H.264/AAC MP4 is the safest shared format. Video values are embedded as base64, so use video_maxSize to keep memory and data-URL costs appropriate for the application.