HTML oncuechange Attribute

Beginner
⏱️ 5 min read
📚 Updated: Jun 2026
🎯 3 Examples
Media

Introduction

The oncuechange handler runs JavaScript when the cuechange event fires on a TextTrack. That happens when the set of active cues changes during <audio> or <video> playback—for example when a WebVTT caption line starts or ends. Use it to build custom caption displays, log subtitle timing, or sync UI with timed text. Attach the handler to textTrack.oncuechange or addEventListener("cuechange", …) on the track from media.textTracks. Set textTrack.mode to "hidden" or "showing" so cues activate.

What You’ll Learn

01

Event handler

TextTrack JS.

02

cuechange

Cues updated.

03

WebVTT

Captions file.

04

activeCues

Current lines.

05

addEventListener

Preferred way.

06

.oncuechange

Property API.

Purpose of oncuechange

The primary purpose of oncuechange is to run JavaScript when the active cues on a text track change. Cues are timed lines in a WebVTT file (captions, subtitles, or metadata). When playback reaches a cue start or end time, the browser fires cuechange on the TextTrack object.

Use it to build custom caption panels, highlight transcript lines, log subtitle timing, or sync UI with spoken content. The handler attaches to textTrack.oncuechange or textTrack.addEventListener("cuechange", …)—not as a standard inline HTML attribute on <track>.

💡
Set textTrack.mode so cues activate

Tracks default to mode = "disabled". Set "hidden" (process cues without native display) or "showing" (native captions visible) before cuechange will fire.

📝 Syntax

Attach the handler on the TextTrack from media.textTracks:

oncuechange.html
<audio id="clip" controls>

  <source src="/audio/count.mp3" type="audio/mpeg">

  <track kind="captions" src="/audio/count.vtt" srclang="en" label="English">

</audio>



<script>

  const audio = document.getElementById("clip");

  const track = audio.textTracks[0];

  track.mode = "hidden";

  track.addEventListener("cuechange", handleCueChange);



  function handleCueChange() {

    const cues = track.activeCues;

    if (!cues || cues.length === 0) return;

    console.log(cues[0].text);

  }

</script>

Syntax Rules

  • Handler runs when the set of active cues on a TextTrack changes.
  • Attach to the TextTrack from audio.textTracks or video.textTracks.
  • Set textTrack.mode to "hidden" or "showing" so cues become active.
  • Read current lines from textTrack.activeCues inside the handler.
  • Property form: textTrack.oncuechange = function() { … }.
  • Preferred: textTrack.addEventListener("cuechange", handler).

💎 Values

oncuechange is an event-handler property on TextTrack, not a string attribute on HTML:

  • track.oncuechange = handleCueChange — Assign a function reference.
  • track.oncuechange = function() { … } — Inline function.
  • track.addEventListener("cuechange", handleCueChange) — Preferred modern form.
oncuechange-js.html
const track = video.textTracks[0];

track.mode = "showing";

track.oncuechange = function () {

  const panel = document.getElementById("caption-panel");

  const cues = track.activeCues;

  panel.textContent = cues.length ? cues[0].text : "";

};

⚡ Quick Reference

EventWhen it firesHandler
cuechangeActive cues on a text track changetextTrack.oncuechange
activeCuesVTTCue objects active nowRead in handler
mode"hidden" or "showing"Required for cues
Custom caption UIUpdate a div on cuechangeCommon pattern
timeupdateFires often on media elementDifferent event

Applicable Elements

TargetSupported?Notes
<audio> + <track>YesHandler on audio.textTracks[n]
<video> + <track>YesMost common for captions
<track> inline attributeNoNot a standard HTML attribute—use JavaScript on TextTrack
TextTrack objectYesWhere oncuechange / cuechange attach

oncuechange vs timeupdate vs onloadedmetadata

HandlerWhen it firesTypical use
onloadedmetadataMedia metadata loaded (duration, tracks list)Wire up text tracks once
timeupdatePlayback time advances (often ~4×/sec)Progress bar, custom timers
oncuechangeActive caption cues changeCustom caption display, transcript sync

Examples Gallery

addEventListener on TextTrack, the oncuechange property, and cuechange vs timeupdate.

👀 Live Preview

Play the audio — active caption text appears when cues change:

Press play — caption text will appear here…

Example — addEventListener("cuechange")

Listen for cue changes on the TextTrack and read active cue text:

cuechange-listener.html
<audio id="clip" controls>

  <source src="/audio/count.mp3" type="audio/mpeg">

  <track kind="captions" src="/audio/count.vtt" srclang="en">

</audio>



<script>

  const audio = document.getElementById("clip");

  audio.addEventListener("loadedmetadata", () => {

    const track = audio.textTracks[0];

    track.mode = "hidden";

    track.addEventListener("cuechange", () => {

      for (const cue of track.activeCues) {

        console.log("Active cue:", cue.text);

      }

    });

  });

</script>
Try It Yourself

How It Works

After metadata loads, set track.mode so cues activate. The browser fires cuechange whenever the active cue set changes during playback.

Dynamic Values with JavaScript

Assign the handler with the oncuechange property:

oncuechange-property.html
const track = audio.textTracks[0];

track.mode = "showing";

track.oncuechange = function () {

  console.log("Cue change detected!");

  for (let cue of track.activeCues) {

    console.log("Active cue:", cue.text);

  }

};
Try It Yourself

How It Works

The property form is equivalent to a single listener. Use mode = "showing" if you want native captions visible alongside your custom logic.

Example — cuechange vs timeupdate

timeupdate fires often; cuechange only when caption lines change:

cuechange-vs-timeupdate.html
audio.addEventListener("timeupdate", () => {

  // Fires frequently — good for progress bars

});



track.addEventListener("cuechange", () => {

  // Fires only when active cues change — good for captions

});
Try It Yourself

How It Works

Caption timing is handled by the text track engine. Listen for cuechange instead of polling currentTime on every timeupdate.

♿ Accessibility

  • Provide captions for video and audio — Use <track kind="captions"> with WebVTT files so deaf and hard-of-hearing users can follow content.
  • Do not rely on cuechange alone — Native mode="showing" or a custom accessible caption panel should display text visibly.
  • Contrast and readability — Custom caption UI needs sufficient color contrast and readable font size.
  • Keyboard and controls — Let users toggle captions via native media controls or an accessible button.
  • Live regions for custom UI — If you mirror captions in a separate div, consider aria-live="polite" for screen reader updates.

🧠 How oncuechange Works

1

Add track + WebVTT

Link captions file on audio/video.

<track>
2

Get TextTrack

From media.textTracks.

loadedmetadata
3

Set mode

hidden or showing.

textTrack.mode
=

cuechange fires

Read activeCues.

Browser Support

The cuechange event and oncuechange handler on TextTrack are supported in all modern browsers — Chrome, Firefox, Safari, and Edge — for WebVTT captions on <audio> and <video>.

DOM Events · Fully supported

Universal oncuechange support

All major browsers fire the underlying event and honor the oncuechange handler attribute.

99% Browser support
Google Chrome Fully supported
Full support
Mozilla Firefox Fully supported
Full support
Apple Safari Fully supported
Full support
Microsoft Edge Fully supported
Full support
Internet Explorer IE 9+ supported
Full support
Opera Fully supported
Full support
oncuechange attribute 99% supported

Bottom line: Universal support for TextTrack cuechange. Test with real WebVTT files and both audio and video elements.

💡 Best Practices

✅ Do

  • Set textTrack.mode — Use "hidden" for custom UI or "showing" for native captions.
  • Use addEventListener on TextTrack — Clearer than relying on a non-standard inline attribute on <track>.
  • Wire up after loadedmetadata — Text tracks are available once media metadata loads.
  • Prefer cuechange over timeupdate — Do not poll currentTime to guess caption timing.
  • Handle empty activeCues — Between cues, activeCues may be empty—clear your caption panel.

❌ Don’t

  • Test across browsers — Verify WebVTT parsing and cue timing with your actual media files.

Conclusion

The oncuechange handler runs JavaScript when the cuechange event fires on a TextTrack. Active caption cues change as media plays, so you can build custom caption displays or sync UI with timed text.

Set textTrack.mode, read activeCues in your handler, and prefer addEventListener("cuechange", …) over polling timeupdate.

Key Takeaways

Knowledge Unlocked

Five truths every developer should know about oncuechange

Bookmark these before wiring your next event handler.

5
Core concepts
🌐 02

TextTrack

JS object API.

Scope
🔄 03

activeCues

Current caption lines.

Pattern
📝 04

addEventListener

Preferred.

Modern
05

mode hidden/showing

Cues must activate.

Note

❓ Frequently Asked Questions

It runs JavaScript when the cuechange event fires on a TextTrack — when active caption or subtitle cues change during media playback.
On the TextTrack from audio.textTracks or video.textTracks — not as a standard inline HTML attribute on <track>.
activeCues is a list of VTTCue objects currently active at the media currentTime. Read cue.text in the handler to display caption text.
timeupdate fires often as playback time advances. cuechange fires only when the set of active cues changes — when a caption line starts or ends.
Prefer textTrack.addEventListener("cuechange", …). The oncuechange property works the same way on the TextTrack object.
Set textTrack.mode to "hidden" or "showing". Default mode is "disabled" and cues will not become active.

Handle text track cue changes

Practice addEventListener cuechange, the oncuechange property, and comparison with timeupdate in the Try It editor.

Try oncuechange demo →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful