Is there a way to adjust the orientation of a <video> element without affecting the orientation of the video controls?

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

This CSS code flips the video horizontally, but it also flips the control buttons along with it.

I attempted to flip the wrapper element containing the video using .wrapper {transform: scaleX(-1), but it did not solve the issue.

Since I am not proficient in creating custom video controls from scratch, I am seeking a solution that involves only CSS like transform: scaleX().

How can I achieve a mirrored effect on the video itself while keeping the control buttons unaffected?

MIRRORED IMAGE

UNMIRRORED IMAGE

Answer №1

If you're looking for a simple solution, you can hide the default video controls, flip the video horizontally, and create your own custom controls. Below is a basic example that you can modify to suit your needs.

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to use a figure tag as a fancybox link?

I am curious, is it possible to turn a figure tag into a fancybox link with just a background image and no content? I understand that this may not be recommended, but I am wondering if it can actually be achieved? <figure class="appear"><a class= ...

creating a table displaying data in a horizontal format sourced from ajax/json transformation

I am currently working on a piece of code that retrieves a list of IDs from local storage and compares them to IDs in a JSON file. If there is a match, the corresponding data is displayed in a table. However, I am facing an issue with my table layout as i ...

Sending JSON Data from C# to External JavaScript File without Using a Web Server

Trying to transfer JSON data from a C# (winforms) application to a static HTML/JavaScript file for canvas drawing without the need for a web server. Keeping the HTML file unhosted is preferred. Without involving a server, passing data through 'get&ap ...

Tips for maintaining HTML lines within an 80-character limit

Someone mentioned to me the importance of keeping HTML lines under 80 characters. My code editor, Atom, even displays a reminder for this limit. I've come across many discussions on this topic but haven't found any examples. For instance, consid ...

Connect button with entry field

I want to create a connection between an input element and a button, where the button triggers the input and the input remains hidden. Here is a solution that I came across: <a href="javascript:void(0)" id="files" href=""> <button id="uploadDe ...

The amazingly efficient Chrome quick find feature, accessible by pressing the powerful combination of Ctrl + F, ingeniously

Currently using Google Chrome version 29.0.1547.62 m. I've employed the CSS attribute overflow set to hidden on the parent element, which renders some of my DIV elements hidden from view. Additionally, these concealed DIV elements are adjusted in pos ...

Using jQuery to apply gradient fill to SVG elements

Is it possible to create a gradient fill in an SVG with two or three colors dynamically? Currently, filling an SVG path with just one color can be done easily. Radial gradients are an option but don't offer much flexibility as colors have to be define ...

Begin the div at a width of 0 pixels and expand it towards the right

My current project involves opening a row of blocks with an animation. The desired outcome is to transition from 2 blocks to 3 blocks by clicking a button. Specifically, the block that needs to be added should appear in the middle and fade in from left to ...

Confirming the accuracy of multiple fields in a form

Looking for help with validating both password and email fields on a registration form. I've successfully implemented validation for passwords, but need assistance adding validation for the email section as well. Can both be validated on the same form ...

At 400 pixels screen size, the buttons in the appBar component are spilling out

In my appBar component, I have three buttons that appear fine on large screens. However, when the screen size reaches 400px, they start stretching out of the appBar. Here is how they look on large screens: And this is how they appear at 400px: I attempt ...

Prevent Fixed Gridview Header from being affected by browser Scroll-bar using JQuery

Is there a way to make the fixed header responsive to only one scroll bar in JQuery? Specifically, is it possible to have it respond solely to the div's scroll bar and not the browser's scroll bar? I attempted to remove the browser's scroll ...

Display elements exclusively when the class XY is in an active state using JavaScript

Hello everyone, I'm new to this platform and excited to share my first post. Currently, I find myself facing a major challenge as I navigate through a bootcamp program. I have been working on a website with different sections that require specific fu ...

Use CSS properties to isolate and extract the logo from the Sprite image

If we have a sprite image, like the StackOverflow sprite, and CSS properties like: background-position: 0px 0px; width: 250px; height: 61px; We can use the Chunky PNG library to crop out a specific part of the sprite. However, some websites use negative ...

Embedded Youtube code saved in database is not displaying on HTML form

My PHP update page allows me to modify a website's database that contains YouTube embed codes. However, when I try to edit the embed code on the update page, only "<iframe width=" displays instead of the complete original code. <html> <? ...

Looking to incorporate multiple accordion drop down menus on your website? Utilize a combination of HTML, CSS, and JavaScript to

I am experiencing a challenge with implementing multiple accordion menus on my website. Whenever I attempt to duplicate the code, the new accordion menu appears but clicking on the first bar simply scrolls me back to the top of the webpage. Below is the H ...

Tips for loading images dynamically (or lazily) as they come into the user's view with scrolling

Many modern websites, such as Facebook and Google Image Search, display images below the fold only when a user scrolls down the page enough to bring them into view (even though the page source code shows X number of <img> tags, they are not initially ...

Stripping CSS prefixes upon file initialization

When developing my application, I have a process in place where I load CSS files on the back-end using Express.JS and then transmit them to the front-end. However, before sending the CSS code to the front-end, I need to: Identify the user's browser; ...

Tips for customizing column width in v-simple-table with Vuetify.js component

For my most recent projects UI component, I decided to use vuetify.js. I attempted to adjust the width of the th and td elements within a v-simple-table using CSS, but unfortunately, nothing seemed to happen. My goal was to set the width of every th and td ...

How to easily upload zip files in Angular 8

Currently, I am working on integrating zip file upload feature into my Angular 8 application. There are 3 specific requirements that need to be met: 1. Only allow uploading of zip files; display an error message for other file types 2. Restrict the file s ...

Unable to reveal hidden text with invisible formatting (font-size: 0)

I have a Joomla 3 website where I created a blog using a design-controll template. I made a "new-article" page but realized that some buttons were missing text. Upon inspecting with Firebug, I found that there was a font-size:0 property causing this issue. ...