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>