ef-trim-handles
Attributes
modestringLayout mode ("standalone" or "track")
standaloneelement-idstringID of element being trimmed (included in events)
pixels-per-msnumberZoom level for pixel-to-time conversion
valueTrimValueCurrent trim value ({startMs, endMs})
intrinsic-duration-msnumberTotal duration of source media
show-overlaysbooleanShow darkened overlay on trimmed regions
trueseek-targetstringID of element to seek when trimming
Interactive trim handles for adjusting the start and end points of media elements. Provides visual feedback and emits events for timeline integration.
Basic Usage
Trim handles on a video element.
<div class="space-y-4"><ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="trim-demo"><ef-videosrc="https://assets.editframe.com/bars-n-tone.mp4"class="size-full object-contain"id="trim-video"></ef-video></ef-timegroup><div class="p-4 bg-gray-900 rounded-lg"><div class="text-white text-sm mb-2">Drag handles to trim video:</div><div class="h-[60px] relative bg-gray-800 rounded-lg"><ef-trim-handleselement-id="trim-video"intrinsic-duration-ms="10000"seek-target="trim-demo"></ef-trim-handles></div><ef-controls target="trim-demo" class="flex gap-2 mt-3"><ef-toggle-play class="px-3 py-1 bg-blue-600 text-white rounded"></ef-toggle-play><ef-time-display class="text-white font-mono"></ef-time-display></ef-controls></div></div><script>const handles = document.querySelector('ef-trim-handles');const video = document.getElementById('trim-video');handles.addEventListener('trim-change', (e) => {const { value } = e.detail;video.setAttribute('trimstart', `${value.startMs}ms`);video.setAttribute('trimend', `${value.endMs}ms`);});</script>
With Timeline
Trim handles are automatically enabled in ef-timeline when enable-trim is set.
<ef-timeline target="composition" enable-trim></ef-timeline>
The timeline handles trim events internally and updates element attributes.
Track Mode
In track mode, handles are pinned to container edges for timeline integration.
<div class="space-y-4"><ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="track-demo"><ef-videosrc="https://assets.editframe.com/bars-n-tone.mp4"class="size-full object-contain"id="track-video"trimstart="2s"trimend="3s"></ef-video></ef-timegroup><div class="p-4 bg-gray-900 rounded-lg"><div class="text-white text-sm mb-2">Track mode (handles at edges):</div><div class="h-[48px] relative bg-gray-800 rounded-lg overflow-hidden"><div style="position: absolute; left: 80px; right: 120px; top: 0; bottom: 0; background: rgba(59,130,246,0.2);"><ef-trim-handlesmode="track"element-id="track-video"intrinsic-duration-ms="10000"pixels-per-ms="0.04"></ef-trim-handles></div></div><ef-controls target="track-demo" class="flex gap-2 mt-3"><ef-toggle-play class="px-3 py-1 bg-blue-600 text-white rounded"></ef-toggle-play><ef-time-display class="text-white font-mono"></ef-time-display></ef-controls></div></div><script>const trackHandles = document.querySelectorAll('ef-trim-handles[mode="track"]')[0];const trackVideo = document.getElementById('track-video');if (trackHandles && trackVideo) {trackHandles.value = { startMs: 2000, endMs: 3000 };trackHandles.addEventListener('trim-change', (e) => {const { value } = e.detail;trackVideo.setAttribute('trimstart', `${value.startMs}ms`);trackVideo.setAttribute('trimend', `${value.endMs}ms`);});}</script>
Region Dragging
In standalone mode, drag the region between handles to slide the trim window.
<div class="space-y-4"><ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="region-demo"><ef-videosrc="https://assets.editframe.com/bars-n-tone.mp4"sourcein="2s"sourceout="6s"class="size-full object-contain"id="region-video"></ef-video></ef-timegroup><div class="p-4 bg-gray-900 rounded-lg"><div class="text-white text-sm mb-2">Drag region to slide trim window:</div><div class="h-[60px] relative bg-gray-800 rounded-lg"><ef-trim-handleselement-id="region-video"intrinsic-duration-ms="10000"seek-target="region-demo"></ef-trim-handles></div><ef-controls target="region-demo" class="flex gap-2 mt-3"><ef-toggle-play class="px-3 py-1 bg-blue-600 text-white rounded"></ef-toggle-play><ef-time-display class="text-white font-mono"></ef-time-display></ef-controls></div></div><script>const regionHandles = document.querySelectorAll('ef-trim-handles')[2];const regionVideo = document.getElementById('region-video');if (regionHandles && regionVideo) {regionHandles.value = { startMs: 2000, endMs: 4000 };regionHandles.addEventListener('trim-change', (e) => {const { value, type } = e.detail;if (type === 'region') {// Region drag - update sourcein/sourceout instead of trimconst duration = 10000 - value.startMs - value.endMs;regionVideo.setAttribute('sourcein', `${value.startMs}ms`);regionVideo.setAttribute('sourceout', `${value.startMs + duration}ms`);}});}</script>
Custom Styling
Style handle appearance with CSS custom properties.
<div class="space-y-4"><ef-timegroup mode="contain" class="w-[720px] h-[480px] bg-black" id="styled-demo"><ef-videosrc="https://assets.editframe.com/bars-n-tone.mp4"class="size-full object-contain"id="styled-video"></ef-video></ef-timegroup><div class="p-4 bg-gray-900 rounded-lg"><div class="text-white text-sm mb-2">Custom styled handles:</div><div class="h-[60px] relative bg-gray-800 rounded-lg"><ef-trim-handlesid="styled-handles"element-id="styled-video"intrinsic-duration-ms="10000"></ef-trim-handles></div></div></div><style>#styled-handles {--trim-handle-width: 12px;--trim-handle-color: rgba(139, 92, 246, 0.8);--trim-handle-active-color: #8b5cf6;--trim-overlay-color: rgba(0, 0, 0, 0.6);}</style><script>const styledHandles = document.getElementById('styled-handles');const styledVideo = document.getElementById('styled-video');styledHandles.addEventListener('trim-change', (e) => {const { value } = e.detail;styledVideo.setAttribute('trimstart', `${value.startMs}ms`);styledVideo.setAttribute('trimend', `${value.endMs}ms`);});</script>
Trim Modes
Standalone mode (mode="standalone", default):
- Handles positioned absolutely based on trim values
- Shows draggable region between handles
- Best for full-width trim UI
Track mode (mode="track"):
- Handles pinned to container edges
- No draggable region
- Best for timeline track integration
Event Handling
trim-change Event
Fired continuously during drag operations.
interface TrimChangeDetail {elementId: string; // Element being trimmedtype: 'start' | 'end' | 'region'; // Which handle/region movedvalue: { // New trim valuesstartMs: number;endMs: number;};}
trim-change-end Event
Fired when drag completes (on pointer up).
interface TrimChangeEndDetail {elementId: string;type: 'start' | 'end' | 'region';}
Trim Value Semantics
Trim values represent time trimmed from source media:
startMs— Time trimmed from startendMs— Time trimmed from end- Effective duration =
intrinsicDurationMs - startMs - endMs
Example with 10 second source:
{startMs: 2000, endMs: 3000}= play seconds 2-7 (5 second duration){startMs: 0, endMs: 0}= play entire source (10 second duration)
Seeking During Trim
When seek-target is set, the element seeks during trim operations:
- Dragging start handle — seeks to trimmed start (0:00 of visible region)
- Dragging end handle — seeks to trimmed end (last frame of visible region)
- Dragging region — maintains relative position
CSS Custom Properties
Customize handle appearance:
ef-trim-handles {--trim-handle-width: 8px;--trim-handle-color: rgba(255, 255, 255, 0.7);--trim-handle-active-color: #3b82f6;--trim-overlay-color: rgba(0, 0, 0, 0.4);--trim-handle-border-radius-start: 2px 0 0 2px;--trim-handle-border-radius-end: 0 2px 2px 0;--trim-selected-border-width: 0px;--trim-selected-border-color: transparent;}
Notes
-
TrimHandles work in two modes: standalone (inline positioning) or track (pinned to edges)
-
Handles constrain dragging to valid ranges
-
Region between handles can be dragged to move both simultaneously
-
Overlays show trimmed (non-visible) regions
-
Use
seek-targetto update video preview while dragging -
Event types: "start", "end", or "region" indicate which handle was dragged
-
Automatically accounts for zoom level via
pixels-per-ms -
CSS custom properties allow extensive styling customization