How to Flip an Image with JavaScript

Sometimes, we may need to flip a media element in a web app. For example, we may need to flip a video element streaming from a camera to match what we actually see or correct scanned document images that are flipped.

In this article, we are going to talk about three ways to flip an image with JavaScript.

Online demo

Build an HTML5 Page to Flip Images

Create a new HTML5 page with the following template and then let’s add the image flipping function to it.

<!DOCTYPE html>
<html lang="en">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Flip an Image with JavaScript</title>
  <div class="home">
    <h2>Flip an Image</h2>
    <button id="flipButton">Flip</button>

Select Desired Direction

We can flip an image in two directions: horizontal and vertical. We can add a select element to select which direction to use.

  <select id="directionSelect">

Load an Image File

Add an input element for selecting files and use a button element to trigger it. The image file will be loaded into an image element.


<button id="loadFileButton">Load a File</button>
<input style="display:none;" type="file" id="file" onchange="loadImageFromFile();" accept=".jpg,.jpeg,.png,.bmp" />
<div class="imageContainer">
  <img id="image"/>
  .imageContainer {
    overflow: auto;
  #image {
    max-width: 50%;


function loadImageFromFile(){
  let fileInput = document.getElementById("file");
  let files = fileInput.files;
  if (files.length == 0) {
  let file = files[0];
  fileReader = new FileReader();
  fileReader.onload = function(e){
    document.getElementById("image").src =;
  fileReader.onerror = function () {
    console.warn('oops, something went wrong.');

Flip an Image with CSS

We can use the CSS property transform to flip an HTML element like the following: = "scaleY(-1)"; //flip vertically = "scaleX(-1)"; //flip horizontally = "scaleX(-1) scaleY(-1)"; //flip both vertically and horizontally

Here is the code we use in the page to flip the image, which remembers the previous flipping status.

function flipImageWithCSS(){
  let img = document.getElementById("image");
  if (document.getElementById("directionSelect").selectedIndex == 0) {
    if ("scaleX") != -1) { ="scaleX(-1)","");
    }else{ =" scaleX(-1)";
    if ("scaleY") != -1) { ="scaleY(-1)","");
    }else{ =" scaleY(-1)";

Flip an Image with Canvas

HTML5 provides a canvas element which provides a way to manipulate image data. Unlike CSS which only changes the visual effect, we can use it to actually get a flipped image.

  1. Add a hidden canvas element to the page.

    <canvas id="canvasHidden"></canvas>
      #canvasHidden {
        display: none;
  2. Add a select element to select which flipping method to use.

      <select id="methodSelect">
  3. Flip an image with canvas when the selected method is “Canvas”.

    let method = document.getElementById("methodSelect").selectedIndex;
    if (method == 0) {
    }else if (method == 1){
      document.getElementById("image").style.transform = "";

Details of flipping an image with canvas.

  1. Set the canvas’s size to match the image’s size.

    const image = document.getElementById("image");
    const canvas = document.getElementById("canvasHidden");
    canvas.width = image.naturalWidth;
    canvas.height = image.naturalHeight;
  2. Get the context of the canvas to perform actions.

    const context = canvas.getContext("2d");
  3. Translate the (0,0) to (width,0) and then scale the image using a scaling factor of -1 in the horizontal direction to flip the image horizontally. We can use a similar logic to flip the image vertically.

    if (document.getElementById("directionSelect").selectedIndex == 0) {
      context.translate(width, 0);
      context.scale(-1, 1);
      context.translate(0, height);
      context.scale(1, -1);
  4. Use drawImage to draw the image content.

    context.drawImage(image, 0, 0);
  5. Display the flipped image.

    image.src = canvas.toDataURL();

Flip an Image with Dynamic Web TWAIN

Dynamic Web TWAIN is a document scanning SDK making it possible to scan documents in the browser. It provides various image processing methods. We can use its Flip and Mirror methods to flip an image.

The advantage of using it is that it can be used to batch process a large volume of images as the processing is done using a native process.

Here are the steps to use it:

  1. Include Dynamic Web TWAIN in the page.

    <script src=""></script>
  2. Initialize an instance of Web TWAIN and use it to flip the image. You can apply for its license here.

    let DWObject;
    Dynamsoft.DWT.AutoLoad = false;
    Dynamsoft.DWT.ProductKey = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; //one-day trial
    Dynamsoft.DWT.ResourcesPath = "";
    async function flipImageWithWebTWAIN(){
      if (!DWObject) {
        await initDWT();
      let response = await fetch(document.getElementById("image").src);
      let buffer = await response.arrayBuffer();
        if (document.getElementById("directionSelect").selectedIndex == 0) {
          function(){ //success
            document.getElementById("image").src = DWObject.GetImageURL(0);
          function(errorCode, errorString){ //fail
          function(){ //success
            document.getElementById("image").src = DWObject.GetImageURL(0);
          function(errorCode, errorString){ //fail
      function(errorCode, errorString){
    function initDWT(){
      return new Promise((resolve, reject) => {
        const title = document.querySelector("h2").innerText;
        document.querySelector("h2").innerText = "Loading Dynamic Web TWAIN...";
          WebTwainId: 'dwtcontrol'
        function(obj) {
          DWObject = obj;
          document.querySelector("h2").innerText = title;
        function(err) {
          document.querySelector("h2").innerText = "Failed to load Dynamic Web TWAIN";

What You Should Know About Dynamic Web TWAIN

Source Code

You can find all the code and an online demo in the following repo: