17

i'm trying to hide the video controls on my video, until the user hover over the video, then the controls shows up. Any idea or advice? Thanks. And I've got more than one video.

HTML:

<div class="item spoon burger"><video width="300" height="auto" controls><source src="videos/sruthi.mp4" type="video/mp4"></video></div>
monkey
  • 526
  • 7
  • 21
user3453264
  • 333
  • 1
  • 5
  • 17
  • What things have you tried? – EnigmaRM Apr 24 '14 at 21:17
  • possible duplicate of [HTML5 video - show/hide controls programtically](http://stackoverflow.com/questions/5399412/html5-video-show-hide-controls-programtically) – EnigmaRM Apr 24 '14 at 21:28
  • i tried this: http://jsfiddle.net/dySyv/1/. but it removes the controls only when click – user3453264 Apr 24 '14 at 21:28
  • Take a look at my example. It is done via hover. – EnigmaRM Apr 24 '14 at 21:29
  • hmm i dont think it's a duplicate, because i'm trying to do it when the user hover on the video itself. – user3453264 Apr 24 '14 at 21:29
  • Note that as of now, if you have both `controls` and `autoplay` attributes on, most browsers/OSes will automatically show/hide on hover/unhover. So depending on your needs, this all might be unnecessary. https://jsfiddle.net/ubvLxzp2/show – V. Rubinetti Aug 17 '22 at 17:12

6 Answers6

26

We can accomplish this through just a couple lines of jQuery, making use of .hover():

Working Example

$('#myvideo').hover(function toggleControls() { if (video.hasAttribute("controls")) { video.removeAttribute("controls") } else { video.setAttribute("controls", "controls") } })

Edit I mistakenly left the variable video in the code above. I changed it to this so that you won't have to manage variables that grab an ID.

$('#myvideo').hover(function toggleControls() {
    if (this.hasAttribute("controls")) {
        this.removeAttribute("controls")
    } else {
        this.setAttribute("controls", "controls")
    }
})

HTML

<video width="300" height="auto" id="myvideo">
    <source src="#" type="video/mp4" />
</video>

Update: You mentioned that you have several videos. So you can use this same logic, and just add additional selectors into $( ). Here's an example:

$('#yourID1, #yourID2, #yourID3').hover(function toggleControls() { ...

Doing that will listen or wait until it detects that you're hovering over one of those IDs.

Updated fiddle

EnigmaRM
  • 7,523
  • 11
  • 46
  • 72
  • so it works on jsfiddle, but not on my browser. Is that because i've got more than one video, so getElementByID won't work? – user3453264 Apr 24 '14 at 22:05
  • Are you including jQuery on your page? Are you updating the `$('#myvideo')` part of the code? I'm not sure if you're familiar with jQuery at all, but that is your element selector. '#insertYourIDHere'. And if you have multiple videos, you can pass in multiple ID's there. I'll update the code above. – EnigmaRM Apr 24 '14 at 23:24
  • thanks for your help, it's working. No, i'm not too familiar with jQuery, still pretty new to it. – user3453264 Apr 25 '14 at 02:32
  • using if statement has its flaws for example i the user rushes to hover the video the if statements effect will be inverted, hence showing the controls when the user is outside the video surface – Wandile Feb 04 '15 at 12:09
  • @Wandile Is there a better way to do it then without the `if`? Please share. Thank you. – purple11111 Aug 30 '16 at 01:06
  • 2
    @purple11111 i just did this simple jQuery `hover` in | out to toggle https://jsfiddle.net/Wandile/hmL837zn/ you can remove the `controls` attribute by default should you wish for the controls not to show by default – Wandile Sep 02 '16 at 09:19
  • In Firefox (didnt test other browsers) the controls are "flickering" whe you move cursor. – user301441 Sep 14 '17 at 15:07
  • HOw would you do this for all classes – Skyler May 31 '18 at 00:50
  • all videos in a class* – Skyler May 31 '18 at 01:03
  • @Skyler, you would only need to modify your `selector` for the element that you want to add this functionality to. Replace the ``#yourID1, #yourID2, #yourID3'` with a reference to your `class`. – EnigmaRM Jun 04 '18 at 18:02
11

One issue with @EnigmaRM's answer is that if jQuery somehow misses a hover event, the controls can be toggled the "wrong" way - that is, they disappear on mouse enter and reappear on mouse leave.

Instead, we can ensure that the controls always appear and disappear correctly with event.type:

$("#myvideo").hover(function(event) {
    if(event.type === "mouseenter") {
        $(this).attr("controls", "");
    } else if(event.type === "mouseleave") {
        $(this).removeAttr("controls");
    }
});
rickcnagy
  • 1,774
  • 18
  • 24
7

Untested, but I believe this would work. It uses JavaScript instead of CSS.

<div class="item spoon burger"><video id="videoElement" width="300" height="auto"><source src="videos/sruthi.mp4" type="video/mp4"></video></div>

<script type="text/javascript">
    (function(window) {
        function setupVideo()
        {
            var v = document.getElementById('videoElement');
            v.addEventListener('mouseover', function() { this.controls = true; }, false);
            v.addEventListener('mouseout', function() { this.controls = false; }, false);
        }

        window.addEventListener('load', setupVideo, false);
    })(window);
</script>
Sean Bright
  • 118,630
  • 17
  • 138
  • 146
  • I tested this solution: it works and it does not require Jquery, wich is great. Thanks @sean-bright! – ganar Mar 19 '19 at 14:18
  • This was a useful start! I had to swap `this` for `v` in the callback, set the property to `'controls'` instead of `true`, and add a line to disable controls on load. Working solution here: https://stackoverflow.com/a/66299017/1079110 – danijar Feb 21 '21 at 03:59
  • You needed to change `this` to `v` because `this` [has a different meaning when used in a function vs. an arrow function](https://www.typescriptlang.org/docs/handbook/functions.html#this-and-arrow-functions). – Sean Bright Feb 22 '21 at 15:04
  • Also, using `'controls'` instead of `true` is just implicitly converting `'controls'` to `true` due to Javascript's implicit type conversions. [The `controls` property is a boolean, not a string](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/controls). – Sean Bright Feb 22 '21 at 15:21
4
<script>
function setupVideos() {
  for (const video of document.querySelectorAll('video')) {
    video.controls = false
    video.addEventListener('mouseover', () => { video.controls = 'controls' })
    video.addEventListener('mouseout', () => { video.controls = false })
  }
}
window.addEventListener('load', setupVideos, false)
</script>
danijar
  • 32,406
  • 45
  • 166
  • 297
0

Using the code below, you don't need a separate javascript section (if that is a concern, which is the case sometimes). Just simply use onmouseover="this.play();this.setAttribute('controls','controls')" and onmouseout="this.load();this.removeAttribute('controls')"

If you don't want it to reset to a poster image, then you can get rid of the this.load.

<div class="img_placeholder">
         <video width="350" height="250" loop preload="none" poster="../assets/icon-32.png" onmouseover="this.play();this.setAttribute('controls','controls')" onmouseout="this.load();this.removeAttribute('controls')">
         <source src="../assets/bear.mp4" type="video/mp4" />
         Your browser does not support the video tag.
         </video>
    </div>
Joseph Astrahan
  • 8,659
  • 12
  • 83
  • 154
-1

A previous post explained how to do it this way HTML5 video - show/hide controls programmatically

<video id="myvideo">
  <source src="path/to/movie.mp4" />
</video>

<p onclick="toggleControls();">Toggle</p>

<script>
var video = document.getElementById("myvideo");

function toggleControls() {
  if (video.hasAttribute("controls")) {
     video.removeAttribute("controls")   
  } else {
     video.setAttribute("controls","controls")   
  }
}
</script>

Check if their solution works for you! Please +1 them if so!

Community
  • 1
  • 1
3066d0
  • 1,853
  • 1
  • 14
  • 18
  • 3
    While the goal is similar, this doesn't answer OP's question. He wants it on hover. And that previous post was already linked to in the initial comments. – EnigmaRM Apr 25 '14 at 14:12
  • @EnigmaRM That comment was posted after this answer. – 3066d0 Sep 07 '18 at 22:10