Need to show HTML5 Video Controls on Hover or Play

You can do this pretty easily in any webkit-based browsers. See below for a self-contained example with inline js, including support for keyboard access.

Keeping the controls open during play is the trickiest aspect. It requires CSS pseudo selectors or access to the media player's shadow dom. If you need to support Firefox you may need to look into styling the shadow dom (or creating custom controls).

video[controls]::-webkit-media-controls-panel {
    display: flex !important;
    opacity: 1 !important;
}

/* not required */
video {
    width: 15em;
    height: auto;
}
/* /not required */
<video 
    src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4"
    type="video/mp4"
    onmouseover="dataset.over=true;controls=true"
    onmouseout="delete dataset.over;if(paused) controls=false;"
    onplay="controls=true"
    onpause="if(!dataset.over && !dataset.focus) controls=false"
    onfocusin="dataset.focus=true; controls=true"
    onfocusout="delete dataset.focus; if(paused) controls=false;">
</video>

<video
    src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4"
    type="video/mp4"
    onmouseover="dataset.over=true;controls=true"
    onmouseout="delete dataset.over;if(paused)controls=false;"
    onplay="controls=true"
    onpause="if(!dataset.over&&!dataset.focus)controls=false"
    onfocusin="dataset.focus=true; controls=true"
    onfocusout="delete dataset.focus;if(paused)controls=false;">
</video>

Updating your own code (jQuery, no keyboard/focus considerations):

var $video = $('.video');

$video.on('mouseover', mouseover);
$video.on('mouseout', mouseout);

function mouseover() {
    this.dataset.over = true;
    this.controls = true;
}

function mouseout() {
    delete this.dataset.over;
    if (this.paused)
        this.controls = false;
}
video[controls]::-webkit-media-controls-panel {
    display: flex !important;
    opacity: 1 !important;
}

/* not required */
video {
    width: 15em;
    height: auto;
}
/* /not required */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<video class="video">
    <source src="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4" type="video/mp4">
</video>

And with some very basic custom controls:

document.querySelectorAll('.video').forEach($el => {
    let timeout;
    $el.addEventListener('play', () => {
        $el.dataset.playing = '';
    });
    $el.addEventListener('pause', () => {
        delete $el.dataset.playing;
    });
  
    $el.addEventListener('timeupdate', (e) => {
        const $scrub = $el.parentElement.querySelector('.video__scrub');
        const pos = $el.currentTime / $el.duration; 
        const increment = (pos - $scrub.value)/10;
    
        const update = () => {
            clearTimeout(timeout);
            $scrub.value = +$scrub.value + increment;
            if (!$el.paused)
                timeout = setTimeout(update, 50);
        };
        update();
    });
});

document.querySelectorAll('.video__toggle').forEach($el =>
    $el.addEventListener('click', () => {
        $video = $el.parentElement.previousElementSibling;
        $video.paused ? $video.play() : $video.pause();
    }));

document.querySelectorAll('.video__scrub').forEach($el => {
     $el.addEventListener('input', () => {
         const $video = $el.parentElement.previousElementSibling;
         $video.pause();
         $video.currentTime = $el.value * $video.duration;
     });
});
video {
    width: 100%;
    height: 100%;
}

.video__controls {
    display: flex;
    position: absolute;
    bottom: 0;
    width: 100%;
    background: rgba(255,255,255,0.3);
    padding: 0.2em 0;
    opacity: 0;
    visibility: hidden;
    transition: 0.2s visibility, 0.2s opacity;
}

.video__wrap:hover .video__controls,
.video[data-playing] ~ .video__controls {
    opacity: 1;
    visibility: visible;
}

.video__toggle {
    background: none;
    border: none;
    font-size: 1.2em;
    height: 2em;
    width: 2em;
}

.video__toggle::before {
    content: '▶️';
}

.video[data-playing] ~ .video__controls .video__toggle::before {
    content: '⏸';
}

.video__scrub {
    width: calc(100% - 5em);
    margin: 0;
}

/* not required */
.video__wrap {
    display: inline-block;
    position: relative;
    width: 40%;
    height: 56.25%;
}
<div class="video__wrap">
    <video class="video" src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4" type="video/mp4"></video>
    <nav class="video__controls">
        <button class="video__toggle"></button>
        <input class="video__scrub" type="range" min=0 max=1 value=0 step=0.001>
    </nav>
</div>

<div class="video__wrap">
    <video class="video" src="https://cdn.jsdelivr.net/npm/[email protected]/video.mp4" type="video/mp4"></video>
    <nav class="video__controls">
        <button class="video__toggle"></button>
        <input class="video__scrub" type="range" min=0 max=1 value=0 step=0.001>
    </nav>
</div>

Attribute controls is boolean:

// by id video.
document.getElementById("video1").controls = true; //show
document.getElementById("video1").controls = false; //hide.

//or all video by tag name:
document.getElementsByTagName("video").controls = true; //show
document.getElementsByTagName("video").controls = false; //hide.

I hope that helps.


Check this code . its working according to your requirements. Use $('.video').get(0).paused function in if condition to set isplaying = True.

var $video = $('.video');

$video.on('mouseover', show);
$video.on('mouseleave', hide);

function show() {
    $(this).attr('controls', '');
}

function hide() {
    var isPlaying = false;
    if(!$('.video').get(0).paused) {
        isPlaying = true;
    }
    if (!isPlaying) {
        $(this).removeAttr('controls');
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<video class="video">
    <source src="http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4" type="video/mp4">
</video>

We cannot really control this behavior as it's managed internally by the browser. All we can do is to specify the controls attribute and the browser will do the rest.

For example: in Firefox (v59b when this is written) the controls will fade out when mouse is outside the element when the video is playing even if the controls attribute is set - they will show if not playing, kind of the opposite you're after. There is no way to force the controls to stay visible when the user moves the mouse outside the video element.

The only way to properly handle this cross-browser and with exact desired behavior is to build a custom controls UI for the player. This of course means more code is needed to handle the various events so you can update and manage the UI; it may also be a challenge when it comes to platform/browser specific look. But it will on the other hand give you grain control.

An alternative is to look at some libraries which wraps the video element into custom UI controls and see if they allow you to force the controls to stay visible with the given conditions. See for example videojs as a starting point.

A small but incomplete example (add functionality, event handlers, design as needed):

var $container = $("#video1");
var $video = $container.children("video"), video = $video[0]
var $controls = $container.children(".controls");
var $play = $controls.children("button");

// control visibility
$container.on("mouseover mouseout", function(e) {
  $controls.css("display", e.type === "mouseout" && video.paused ? "none" : "block");
});

// play or pause
$play.on("click", toggle);
$video.on("click", toggle);

function toggle() {
  video[video.paused ? "play" : "pause"]();
}

// todo: cover more events (seeked, error etc.)
$video.on("play pause ended", updateUI);

// update control UI elements (todo: update time/progress etc.)
function updateUI() {
  $play.text(video.paused ? "Play" : "Pause")
}
.container {
  position:relative;
  display:inline-block;
  font-size:0;
  }
.container > .controls {
  position:absolute;
  bottom:0;
  width:100%;
  background:rgba(255,255,255,0.3);
  padding:7px;
  box-sizing:content-box;
  z-index:10000;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=video1 class=container>
  <video width=640 muted src="//media.w3.org/2010/05/sintel/trailer.mp4"></video>
  <div class=controls style="display:none">
    <button>Play</button>
  </div>
</div>