'Can HTML5 subtitles be positioned with css?

I am using a custom HTML5 app for streaming videos on a local network, and now I am adding subtitles support.

I have around 500 .vtt subtitles converted from .srt. After I converted them from .srt, I noticed they display right at the bottom of the screen, and I'd like them to have a little margin-bottom.

I am able to style the subtitles with css pseudo element ::cue, but only for font size, color, background. Doesn't seem to support any margin, padding or positioning rules.

Before coding a script to modify all the .vtt files to add line:XX% to the cues (that's the only way I found so far to move them), I was wondering if there's a way to position the subtitles without having to modify all the .vtt files.

If I disable my custom controls and tried the default controls instead. When a subtitle is displayed and I put the mouse over the video to show the controls, the subtitle do move up, and when the controls get auto hidden after a few seconds that line of subtitles stay at that place. But the next line move back down. This is the reason I am wondering if they can be moved without editing the .vtt files, since showing the controls move them up, maybe there's a way I can do it programmatically.

So the question is, can .vtt subtitles be positioned using CSS or any other method other than modifying the .vtt files?

This is the basic code I am using for testing:

<video controls autoplay>
    <source src="http://192.168.0.1/video.mp4" type="video/mp4" />
    <track src="http://192.168.0.1/subtitles.vtt" kind="subtitles" srclang="en" label="English" default />
</video>
<style>
    video::cue {
        font-size:100%;
        color:white;
    }
</style>


Solution 1:[1]

This link might be useful, change line position in it

http://ronallo.com/demos/webvtt-cue-settings/

Solution 2:[2]

This isn't css, but incase new visitors want a solution with JS:

const track = document.getElementsByTagName('track')[0].track;

// Position the cue at the top
track.activeCues[0].line = 0;

// Position the cue at the bottom (default)
track.activeCues[0].line = -1;

// Move the cue up 3 lines to make room for video controls
track.activeCues[0].line = -4;

Solution 3:[3]

you can extract text from individual cues using textTrack.activeCues[0].text and display them in div and set position of div.

Solution 4:[4]

You can give the line-height to the ::cue, but the problem with it is if subtitle goes into multiple lines then the gap between the lines increases.

Solution 5:[5]

The best solution I could think of (in React+Typescript, principle should work anywhere. hacky but works). The main idea is:

  1. Wait for load event to fire on track element
  2. Get VTT cues of track
  3. Set line property of each cue
trackRef = (node: HTMLTrackElement) => {
    if (node == null) return

    node.addEventListener('load', () => {
        if (node.track.cues == null) return
        Array.from(node.track.cues).forEach((c) => {
            (c as VTTCue).line = -4
        })
    })
}

//...

<video>
    <source
        src="..."
    />
    <track
        default
        src="..."
        ref={this.trackRef}
    />
</video>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Supraja Ganji
Solution 2 internet-nico
Solution 3 sithLords
Solution 4 Supraja Ganji
Solution 5 erik