ef-captions
Attributes
targetstringSelector for ef-video or ef-audio element
captions-scriptstringID of script element with JSON captions
captions-srcstringURL to JSON captions file
captions-dataobjectDirect captions data object
Synchronized captions with word highlighting.
Basic Usage
Caption Data Format
{"segments": [{ "start": 0, "end": 3, "text": "Sentence one." }],"word_segments": [{ "start": 0, "end": 0.5, "text": "Sentence" },{ "start": 0.5, "end": 1.0, "text": "one." }]}
Times are in seconds relative to the parent timegroup.
Active Word Styling
Color Highlighting
Background Box Style
Underline and Shadow
Animated Pop Effect
Slide-In Animation
Segment-Level Styling
Full Segment Display
Multi-Line Segments
Karaoke-Style Captions
Classic Karaoke
Progress Bar Karaoke
Gradient Progression
Custom Timing Examples
Fast-Paced Captions
Slow Dramatic Timing
Multiple Speakers
Loading Captions
From External File
<ef-captions captions-src="/captions/video-transcript.json" class="absolute bottom-12 left-0 right-0 text-center"><ef-captions-before-active-word class="text-white/60 text-xl"></ef-captions-before-active-word><ef-captions-active-word class="text-yellow-300 text-2xl font-bold"></ef-captions-active-word><ef-captions-after-active-word class="text-white/40 text-xl"></ef-captions-after-active-word></ef-captions>
From Inline Script
<ef-captions captions-script="my-captions"><ef-captions-active-word class="text-yellow-300"></ef-captions-active-word></ef-captions><script type="application/json" id="my-captions">{"segments": [{ "start": 0, "end": 3, "text": "Your caption text here." }],"word_segments": [{ "start": 0, "end": 1, "text": "Your" },{ "start": 1, "end": 2, "text": "caption" },{ "start": 2, "end": 3, "text": "text" },{ "start": 3, "end": 4, "text": "here." }]}</script>
Via JavaScript
<ef-captions id="dynamic-captions"><ef-captions-active-word class="text-cyan-400"></ef-captions-active-word></ef-captions><script>const captions = document.getElementById('dynamic-captions');captions.captionsData = {segments: [{ start: 0, end: 3, text: "Dynamically loaded captions." }],word_segments: [{ start: 0, end: 1, text: "Dynamically" },{ start: 1, end: 2, text: "loaded" },{ start: 2, end: 3, text: "captions." }]};</script>
Sub-Elements
ef-captions uses child elements to separate caption text into styleable parts. These elements act as slots — they're containers that ef-captions fills with text. You style them with CSS classes, and ef-captions handles updating their content.
All caption sub-elements use display: inline by default for natural text flow. They act as transparent containers — the text flows as if the element boundaries don't exist.
ef-captions-active-word
The word currently being spoken. Automatically hidden when empty or contains only punctuation.
CSS Variables:
--ef-word-seed- Deterministic random (0-1) per word for animations
Behavior:
- Adds trailing space automatically for proper word spacing
- Hidden via
hiddenattribute when no active word
ef-captions-before-active-word
All words in the current segment that have already been spoken.
Behavior:
- Adds trailing space when followed by active word
- Hidden via
hiddenattribute when no prior words
ef-captions-after-active-word
All words in the current segment not yet spoken.
Behavior:
- No leading space (active word adds trailing space)
- Hidden via
hiddenattribute when no upcoming words
ef-captions-segment
The full text of the current caption segment.
Behavior:
- Hidden via
hiddenattribute when no active segment - Can be used alone or alongside word-level elements
Layout Patterns
<!-- Inline flow (default) --><ef-captions class="text-white text-xl"><ef-captions-before-active-word></ef-captions-before-active-word><ef-captions-active-word class="font-bold"></ef-captions-active-word><ef-captions-after-active-word></ef-captions-after-active-word></ef-captions><!-- Multi-line layout --><ef-captions><div class="text-center"><ef-captions-segment class="block text-white/50 mb-1"></ef-captions-segment></div><div class="text-center"><ef-captions-active-word class="text-yellow-400 text-2xl"></ef-captions-active-word></div></ef-captions>
Technical Notes
- All sub-elements use light DOM (not shadow DOM) for styling simplicity
- Parent
ef-captionselement updates childtextContentdirectly - Empty or punctuation-only content automatically hides elements via
hiddenattribute - Elements maintain text flow by using
display: inlinewith no margins/padding --ef-word-seedprovides deterministic randomness based on word index (not random each frame)
Generate Captions
Use the Editframe CLI to generate captions from video/audio files:
npx editframe transcribe video.mp4 -o captions.json
# Transcribe with specific languagenpx editframe transcribe video.mp4 --language en -o captions.json# Transcribe audio filenpx editframe transcribe audio.mp3 -o captions.json
Then load the generated captions:
See transcription.md for complete transcription workflow documentation.