Skip to content
Advertisement

How to get the rect.top and rect.left of an element if it’s mapped in React JS

I am trying to have a gloss effect on some cards when the mouse moves over them.

What I need is to move the gloss effect base on the mouse position. The problem that I have is that I can’t get the top and left of the card because they are mapped like this

          <div ref={cardsContainer} className={styles.cardsContainer}>
            {data.map((card, index) => (
              <div
                key={index}
                ref={cards}
                className={`${styles.card} cards`}
                onMouseMove={(index, e) => handleMouseMove(index, e)}
              >
                {card.title}
                <div
                  className={styles.cardGlow}
                  style={{ top: glowXPos, left: glowYPos }}
                ></div>
              </div>
            ))}
          </div>

I have tried to use the index to get the rect of the element but it doesn’t work. It’s saying that GlowingCardsGrid.jsx:21 Uncaught TypeError: index.getBoundingClientReact is not a function.

  const handleMouseMove = (index, e) => {
    const rect = index.getBoundingClientReact();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    setGlowXPos(x);
    setGlowYPos(y);
  };

Is there a way I could get the top and left of each element depending on which one I’m hovering on?

Advertisement

Answer

If you just want to change some styles or classes when an element is hovered, the better approach would be to create a reusable component that could manage its own state.

Using onMouseOver to set a state variable to true and onMouseOut to set it back to false gives you the ability to do whatever you want (e.g., run an animation, add some styles or change the classes) when the element is hovered.

function App() {
    return (
        <div>
            {data.map((card, index) => (
                <HoverCard key={index}>
                    <h3>{card.title}</h3>
                </HoverCard>
            ))}
        </div>
    );
}

function HoverCard({ children }) {
    const [isHover, setIsHover] = React.useState(false);
    const baseElementStyles = {
        backgroundColor: 'coral',
        color: 'white',
        cursor: 'pointer',
        display: 'grid',
        height: '10rem',
        margin: '1rem',
        overflow: 'hidden',
        placeContent: 'center',
        position: 'relative',
    };
    const hoverElementStyles = {
        backgroundColor: 'deeppink',
        position: 'absolute',
        inset: '0',
        transform: 'translateX(-100%)',
        transition: 'transform .2s ease-in-out',
    };
    return (
        <div
            onMouseOver={() => setIsHover(true)}
            onMouseOut={() => setIsHover(false)}
            style={baseElementStyles}
        >
            <div
                style={
                    !isHover
                        ? hoverElementStyles
                        : { ...hoverElementStyles, transform: 'translateX(0)' }
                }
            ></div>
            <div style={{ position: 'relative' }}>{children}</div>
        </div>
    );
}

var data = [
    {
        title: 'Title 1',
    },
    {
        title: 'Title 2',
    },
    {
        title: 'Title 3',
    },
];


ReactDOM.createRoot(document.getElementById("root")).render(<App />)
<div id="root"></div>

<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement