2

I'm trying to achieve something similar to the products in this website: https://www.adidas.de/en/women-shoes-outlet

When I hover, I want the row below to stay at the same position and the hovered product overlays the one below.

I am using a combination of Material UI and plain old CSS. So far everything has been achieved except this exact problem. Right now the code is not in its final form but I am trying to get the layout finalized.

This is a codepen of the work so far codpen

Here is the React component:

import React from "react";
import "./ProductCard.css";
import ShareIcon from '@mui/icons-material/Share';
import { Grid, IconButton } from "@mui/material";

const PricePanel = ({ product }) => {
    const { price, discount } = product;
    let display_price;
    if (discount) display_price = price - (price * (discount / 100));
    return (
        <div className="price-overlay">
            {discount ?
                <>
                    <div className="price">
                        <span style={{ textDecoration: "line-through" }}>€{Math.ceil(price)}</span>
                        {` `}
                        <span style={{ color: 'red' }}>€{Math.ceil(display_price)}</span></div>
                </>
                :
                <div className="price">€{Math.ceil(price)}</div>}

        </div>
    );
};

const ProductCard = ({ product }) => {
    const [currentImage, setCurrentImage] = React.useState(product.images[0].image);
    const [checked, setChecked] = React.useState(false);

    const handleColorHover = (image) => { setCurrentImage(image); };

    const { id, title, description, discount } = product;


    return (
        <Grid item xs={12} md={6} lg={3} id={id}>
            <div className="product-card">
                <div className="product-image">
                    <img id="main" src={currentImage} alt="Product" />
                    {discount && (
                        <div className="discount-overlay">
                            -{Math.ceil(discount)}%
                        </div>
                    )}

                    <PricePanel product={product} />
                    <div className="color-options">
                        {product.images.map((item) => (
                            <img
                                key={item.color}
                                className="color-thumbnail"
                                src={item.thumbnail}
                                alt={item.color}
                                onMouseEnter={() => handleColorHover(item.image)}
                            />
                        ))}
                    </div>
                </div>
                <div className="product-details">
                    <h3 className="product-name">{title}</h3>
                    <p className="product-category">{description}</p>
                    <div className="icon-buttons" >
                        <IconButton aria-label="share">
                            <ShareIcon />
                        </IconButton>
                        <IconButton onClick={() => setChecked(!checked)} aria-label="fav">
                            <span className={checked ? 'checked' : 'notchecked'} color="#aab8c2">❤</span>
                        </IconButton>
                    </div>
                </div>
            </div>

        </Grid >
    );
};

export default ProductCard;

And here is the css

.product-card {
    width: 100%;
    overflow: hidden;
    transition: transform 0.3s ease-in-out;
    background-color: #fff;
    text-align: center;
    position: relative;
    cursor: pointer;
}

.product-card:hover {
    position: relative;
    z-index: 10000;
    border: 1px solid #ccc;
}

.product-image {
    position: relative;
    width: 100%;
}

.product-image #main {
    width: 100%;
    display: block;
    transition: transform 0.3s ease-in-out;
}

.color-options {
    display: none;
    justify-content: left;
    background-color: #fff;
}

.product-card:hover .color-options {
    display: flex;
}

.color-thumbnail {
    height: 50px;
    cursor: pointer;
}

.favorite-icon {
    position: absolute;
    top: 10px;
    right: 10px;
    color: #fff;
    font-size: 24px;
    cursor: pointer;
    z-index: 100000;
}

.price-overlay {
    position: absolute;
    top: 85%;
    left: 10px;
    color: rgba(0, 0, 0, 0.7);
    font-size: 0.7rem;
    z-index: 1;
    background-color: #fff;
    padding: 5px 7px;
    opacity: 50;
}

.discount-overlay {
    position: absolute;
    top: 5%;
    right: 10px;
    color: rgba(0, 0, 0, 0.7);
    font-weight: bold;
    font-size: 0.7rem;
    z-index: 1;
    background-color: #fff;
    padding: 5px 7px;
    opacity: 50;
}

.product-card:hover .price-overlay {
    top: 75%;

}

.product-details {
    padding: 10px;
    background-color: #fff;
}

.product-name {
    margin: 0;
    font-size: 16px;
    text-align: left;
}

.product-category {
    margin-top: 5px;
    color: #777;
    font-size: 14px;
    text-align: left;
}

.icon-buttons {
    float: right;
}

.strike {
    text-decoration: 'line-through';
}

.checked {
    color: #e2264d;
}

The ProductCard component is wrapped in a simple Grid <Grid item container spacing={1} xs={12}></Grid>

momal
  • 576
  • 2
  • 13
  • 30
  • `position: absolute;` – Amaury Hanser Jun 22 '23 at 07:35
  • @AmauryHanser where? – momal Jun 22 '23 at 07:38
  • Well, if you want the exact same thing than the website you've linked, inspect what happens when you hover, you'll find `.glass-product-card {position: absolute}` when you hover the card. If you want help with your code, you could create a [example]. If you post the generated html, it will be easier than a React component. – Amaury Hanser Jun 22 '23 at 08:05
  • @AmauryHanser you're right. i'll add a codepen – momal Jun 22 '23 at 09:40
  • `.MuiGrid-item { position: relative; } .product-card:hover { position: absolute; }` would put you on the right track. – Amaury Hanser Jun 22 '23 at 09:48
  • @AmauryHanser worked perfectly! thanks! I had tried the absolute thing before but i missed the grid item relative thing and was stuck. do you want to answer the question? – momal Jun 22 '23 at 09:51

0 Answers0