Search code examples
htmlcssvideo

How do I change the orientation of a <video> without changing the orientation of the video controls


<video controls>
</video>
video {
 transform: scaleX(-1)
}

This mirrors the video at 180 degrees but it mirrors the controls as well.

I have tried transforming the wrapper element for the video element with .wrapper {transform: scaleX(-1) as well and still no change.

Building controls from scratch is honestly out of my skill atm so I'm hoping to do this with just css like transform: scaleX().

How do I maintain mirror only the video whilst maintaining the controls in their original orientation?

MIRRORED IMAGE Unmirrored image

UNMIRRORED IMAGE Mirrored Image


Solution

  • The easiest way I can think is to hide the default controls, invert the video, and create your own controls. I've made a simple example below that you can customize as you'd like.

    const video = document.getElementById('videoPlayer');
    const playPauseButton = document.getElementById('playPause');
    const muteToggleButton = document.getElementById('muteToggle');
    const fullscreenToggleButton = document.getElementById('fullscreenToggle');
    const progressBarContainer = document.getElementById('progressBarContainer');
    const progressBarFilled = document.getElementById('progressBarFilled');
    const timeDisplay = document.getElementById('timeDisplay');
    
    function togglePlayPause() {
      if (video.paused) {
        video.play();
        playPauseButton.textContent = 'Pause';
      } else {
        video.pause();
        playPauseButton.textContent = 'Play';
      }
    }
    
    function toggleMute() {
      video.muted = !video.muted;
      muteToggleButton.textContent = video.muted ? 'Unmute' : 'Mute';
    }
    
    function toggleFullscreen() {
      if (!document.fullscreenElement) {
        video.requestFullscreen();
      } else {
        document.exitFullscreen();
      }
    }
    
    function updateProgressBar() {
      const percentage = (video.currentTime / video.duration) * 100;
      progressBarFilled.style.width = percentage + '%';
      updateTimerDisplay();
    }
    
    function seek(e) {
      const newTime = (e.offsetX / progressBarContainer.offsetWidth) * video.duration;
      video.currentTime = newTime;
    }
    
    function updateTimerDisplay() {
      const formattedCurrentTime = new Date(video.currentTime * 1000).toISOString().substr(14, 5);
      const formattedDuration = new Date(video.duration * 1000).toISOString().substr(14, 5);
      timeDisplay.textContent = `${formattedCurrentTime} / ${formattedDuration}`;
    }
    
    playPauseButton.addEventListener('click', togglePlayPause);
    muteToggleButton.addEventListener('click', toggleMute);
    fullscreenToggleButton.addEventListener('click', toggleFullscreen);
    progressBarContainer.addEventListener('click', seek);
    video.addEventListener('timeupdate', updateProgressBar);
    .video-container {
      position: relative;
      width: 100%;
      max-width: 640px;
    }
    
    .video-container video {
      transform: scaleX(-1);
      width: 100%;
      height: auto;
    }
    
    .video-controls {
      position: absolute;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      color: #fff;
      width: 100%;
      display: flex;
      align-items: center;
      padding: 5px -5px 5px 5px;
    }
    
    .video-controls button {
      background: none;
      border: none;
      color: #fff;
      cursor: pointer;
      margin-right: 10px;
    }
    
    .progress-bar-container {
      flex-grow: 1;
      cursor: pointer;
      margin-right: 10px;
    }
    
    .progress-bar {
      width: 100%;
      height: 5px;
      background: #666;
      position: relative;
    }
    
    .progress-bar-filled {
      background: #fff;
      height: 100%;
      width: 0;
    }
    
    .time {
      font-size: 0.8em;
      margin-right: 10px;
    }
    <div class="video-container">
      <video id="videoPlayer">
        <source src="https://uce23327b0bab5175c1c0c0cbc0a.dl.dropboxusercontent.com/cd/0/inline/CJhjJhXufoSbuAopjZ-4fWNFBDaEyp-tZ_08YeqLy-avay9VQ4coVwwdsfHZWhB9S7W6oOzxpx-e2R6Mj5Fa1QzbkumZOHOlNhHpud84YbApN3-tZHbuLrCQgakMIQ6YQRlu6I2GrK_UwdAqmaEdELw6/file#" type="video/mp4">
        Your browser does not support the video tag.
      </video>
      <div class="video-controls">
        <button id="playPause">Play/Pause</button>
        <button id="muteToggle">Mute/Unmute</button>
        <button id="fullscreenToggle">Fullscreen</button>
        <div class="progress-bar-container" id="progressBarContainer">
          <div class="progress-bar">
            <div class="progress-bar-filled" id="progressBarFilled"></div>
          </div>
        </div>
        <div class="time" id="timeDisplay">00:00 / 00:00</div>
      </div>
    </div>