JSFiddle - React, Tailwind, and code Playground

HTML

<div class="gallery" id="gallery">
   <div class="image-full">

   <img src="http://tarunin.pw/media/product_images/132/main_image/absolute_summer_8.jpg">
   <div class="image-zoom-zone"> </div>
   <div class="image-zoom-fade"> </div>
</div>
<div class="image-zoom"> </div>
</div>

CSS

* {
    box-sizing: border-box; 
}
.gallery{
  border 3px solid gray;
  position: relative;
  width: 450px;
  margin: 50px;
  display: flex;
}
.image-full{
  width: 450px;
  position: relative;
  overflow: hidden;
  cursor: crosshair;;
  align-self: flex-start;
  background: lightgray;
}
.image-full img{
    display: block;
    width: 100%;
  }
.image-zoom{
  display: none;
  z-index: 1000;
  position: absolute;
  width: 250px;
  height: 250px;
  left: 101%;
  top: 0;
  background-color: lightgray;
  background-repeat: no-repeat;
  background-size: 1000px;
  background-position: center;
   background-image: url('http://tarunin.pw/media/product_images/132/main_image/absolute_summer_8.jpg');
}
 .image-zoom-zone{
   box-sizing: content-box;
   position: absolute;
   width: 150px;
   height: 150px;
   left: 0;
   top: 0;
   z-index: 1000;
   border: solid 30px lightblue;
   opacity: .5;

}
.image-zoom-fade{
  visibility: hidden;
  transition: .2s;
  position: absolute;
  z-index: 999;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background-color: lightblue;
  opacity: .95;
}

JavaScript

initGallery();
function initGallery() {
  var gallery = document.getElementById("gallery");
  var imageFullContainer = gallery.querySelector(".image-full");
  var imageFull = imageFullContainer.firstElementChild;
  var imageZoom = gallery.querySelector(".image-zoom");
  var imageZone = gallery.querySelector(".image-zoom-zone");
  var imageFade = gallery.querySelector(".image-zoom-fade");


  function move(event) {
    var imageCoords = imageFull.getBoundingClientRect();
    var imageHeight  = imageFull.offsetHeight;
    var imageWidth = imageFull.offsetWidth;
    var mouseX = event.clientX - imageCoords.left;
    var mouseY = event.clientY - imageCoords.top;
    var zone = {
      left: Math.max(Math.min(mouseX - imageZone.offsetWidth/2, imageWidth - imageZone.offsetWidth), 0),
      top: Math.max(Math.min(mouseY - imageZone.offsetHeight/2, imageHeight - imageZone.offsetHeight), 0)
    };
    var relation =  imageZoom.offsetWidth / imageZone.offsetWidth;



    imageZone.style.backgroundSize = imageFull.offsetWidth + "px";
    imageZone.style.backgroundPositionX = -zone.left + "px";
    imageZone.style.backgroundPositionY = -zone.top + "px";

    imageZone.style.left = zone.left  + "px";
    imageZone.style.top = zone.top  + "px";

    imageZoom.style.backgroundSize = imageWidth * relation + "px";
    imageZoom.style.backgroundPositionX = -zone.left * relation+ "px";
    imageZoom.style.backgroundPositionY = -zone.top * relation+ "px";

  }
  function zoomImageOver(event) {
    if (this.classList.contains("image-full")) {
      imageZoom.style.display = "block";
      imageZone.style.display = "block";
      //imageFade.style.visibility = "visible";
      imageFade.style.opacity = "0.5";
      move(event);
    }
  }
  function zoomImageOut(event) {
    if (this.classList.contains("image-full")) {
      imageZoom.style.display = "none";
      imageZone.style.display = "none";
      imageFade.style.visibility = "hidden";
      imageFade.style.opacity = "0";
    }
 ...