Search code examples
javascriptcssreactjsbootstrap-4css-transforms

React component that zooms into an image while keeping dimensions on mouse over - React + Bootstrap


So I have been looking all over the place over the past few days and cannot find anything that works. I am using React with Bootstrap. I want a stateless functional component that takes an image path and returns an img element which, when hovered over by the mouse, zooms into the image while keeping the dimensions of the element the same.

I have tried:

  1. Changing the style attribute in the onMouseOver and onMouseOut events like so
import React from "react";

const ImageHoverZoom = ({ imagePath }) => {
  return (
    <img
      src={imagePath}
      alt=""
      style={{ overflow: "hidden" }}
      onMouseOver={(e) => (e.currentTarget.style = { transform: "scale(1.25)", overflow: "hidden" })}
      onMouseOut={(e) => (e.currentTarget.style = { transform: "scale(1)", overflow: "hidden" })}
    />
  );
};

export default ImageHoverZoom;
  1. Creating a custom css class and applying that to the img element.

index.css:

.hover-zoom {
  overflow: hidden;
}

.hover-zoom img {
  transition: all 0.3s ease 0s;
  width: 100%;
}

.hover-zoom img:hover {
  transform: scale(1.25);
}

imageHoverZoom.jsx:

import React from "react";

const ImageHoverZoom = ({ imagePath }) => {
  return (
    <img
      src={imagePath}
      alt=""
      className="hover-zoom"
    />
  );
};

export default ImageHoverZoom;
  1. I have also tried a class component with state
import React, { Component } from "react";

class ImageHoverZoom extends Component {
  state = {
    path: this.props.imagePath,
    mouseOver: false,
  };

  render() {
    const { path, mouseOver } = this.state;
    return (
      <img
        className={`img-fluid w-100`}
        src={path}
        onMouseOver={() => this.setState({ mouseOver: true })}
        onMouseOut={() => this.setState({ mouseOver: false })}
        style={
          mouseOver 
            ? { transform: "scale(1.25)", overflow: "hidden"} 
            : { transform: "scale(1)", overflow: "hidden"}
        }
        alt=""
      />
    );
  }
}

I would ideally not like to use state as I know it gets updated asynchronously and I feel like that would lead to some lag on the client side when mousing over the image. Any help is much obliged, thank you in advance!

EDIT:

I tried Rahul's answer below in my project, as well as in a brand new project. Here are the relevant (I think) files. Same thing as before. No change on mouse over.

App.js

import "./App.css";
import ImageHoverZoom from "./common/imageHoverZoom";

function App() {
  return <ImageHoverZoom imagePath="http://picsum.photos/400/600" />;
}

export default App;

imageHoverZoom.jsx

import React from "react";

const ImageHoverZoom = ({ imagePath }) => {
  return (
    <div className="img-wrapper">
      <img src={imagePath} alt="" className="hover-zoom" />
    </div>
  );
};
export default ImageHoverZoom;

index.css

.img-wrapper {
  overflow: hidden;
}
.hover-zoom img:hover {
  transform: scale(1.25);
}

Solution

  • Wrap the img tag in a div and then hide the overflow from div:

    const ImageHoverZoom = ({ imagePath }) => {
    return (
        <div className="img-wrapper">
            <img
                src={imagePath}
                alt=""
                className="hover-zoom"
            />
        </div>
    );
    };
    export default ImageHoverZoom;
    

    add the styling to img-wrapper:

    .img-wrapper{
      overflow:hidden;
    }
    img.hover-zoom:hover {
      transform: scale(1.25);
    }