Troubleshooting Image Hover Transition in react-slick Carousel

30 Views Asked by At

I'm using react-slick to create a multi item carousel with MUI cards, but I'm running into a problem. Here's what I'm trying to do: When a user hovers over an image (which is inside the CardMedia:MUI element), I want the image to scale and move to the middle of the screen. However, I'm struggling with this.

Any ideas on how to tackle this issue? Or perhaps recommend another library besides react-slick?

I've attempted to fix it by setting the image position to fixed/absolute, but it's not smooth because the transition property doesn't affect the position property.

App.tsx


import "./App.css";
import { Grid } from "@mui/material";
import monkeySelfie from "./Monkey-Selfie.webp";
import "./index.css";
import Carousel from "./Carousel";

function App() {
    const generateCards = () => {
        var cards = [];
        for (var i = 0; i < 15; i++) {
            cards.push({ image: monkeySelfie, text: "monkey" });
        }
        return cards;
    };

    var cards = generateCards();

    return (
        <>
            <link
                rel="stylesheet"
                type="text/css"
                charSet="UTF-8"
                href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css"
            />
            <link
                rel="stylesheet"
                type="text/css"
                href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css"
            />

            <Grid container height={"100vh"} justifyContent={"space-around"}>
                <Grid item xs={12} height={"8%"} border={"solid 1px gray"}>
                    {/* NAVBAR */}
                </Grid>
                <Grid item xs={12} height={"40%"} border={"solid 1px gray"}>
                    <Carousel items={cards} />
                </Grid>
                <Grid item xs={12} height={"2%"} border={"solid 1px gray"}>
                    {/* DIVIDER */}
                </Grid>
                <Grid item xs={5} height={"50%"} border={"solid 1px gray"}>
                    {/* DATA SECTION */}
                </Grid>
                <Grid item xs={5} height={"50%"} border={"solid 1px gray"}>
                    {/* LAST SECTION */}
                </Grid>
            </Grid>
        </>
    );
}

export default App;

Carousel.tsx

import Slider from "react-slick";
import Item from "./Item";
import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos";
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";

interface Props {
    items: Item[];
}

interface Item {
    image: string;
    text: string;
}

const slideToShow: number = 5;

const settings = {
    dots: true,
    infinite: false,
    speed: 500,
    initialSlide: 0,
    slidesToShow: slideToShow,
    slidesToScroll: slideToShow,
    responsive: [
        {
            breakpoint: 1024,
            settings: {
                slidesToShow: 3,
                slidesToScroll: 3,
                infinite: true,
                dots: true,
            },
        },
        {
            breakpoint: 600,
            settings: {
                slidesToShow: 2,
                slidesToScroll: 2,
                initialSlide: 2,
            },
        },
        {
            breakpoint: 480,
            settings: {
                slidesToShow: 1,
                slidesToScroll: 1,
            },
        },
    ],
};

const arrowsStyle = { cursor: "pointer", transition: "all 0.3s ease", "&:hover": { color: "black" } };

function Carousel({ items: items }: Props) {
    return (
        <>
            <div className="slider-container" style={{ width: "95%", height: "100%", margin: "0 auto" }}>
                <Slider
                    {...settings}
                    prevArrow={<ArrowBackIosIcon color="action" sx={arrowsStyle} />}
                    nextArrow={<ArrowForwardIosIcon color="action" sx={arrowsStyle} />}
                >
                    {items.map((item, index) => (
                        <Item key={index} image={item.image} text={item.text} />
                    ))}
                </Slider>
            </div>
        </>
    );
}

export default Carousel;

Item.tsx

import { Card, CardActions, CardMedia, IconButton, Typography } from "@mui/material";
import DownloadIcon from "@mui/icons-material/Download";

interface Props {
    image: string;
    text: string;
}

function Item({ image, text }: Props) {
    return (
        <Card sx={{ maxWidth: 450, height: "100%", bgcolor: "#CECECE", overflow: "visible" }}>
            <CardMedia
                component="img"
                className="item-img"
                sx={{
                    borderRadius: "20px",
                    padding: "5px",
                    cursor: "pointer",
                    transition: "all 0.6s ease",
                    zIndex: "999",
                    "&:hover": {
                        position: "fixed",
                        zIndex: "999",
                        top: "50%",
                        left: "50%",
                        transform: "scale(3) translate(-50%, -50%)",
                    },
                }}
                image={image}
                onClick={() => {
                    console.log("open");
                }}
            />
            <CardActions sx={{ justifyContent: "space-between" }}>
                <Typography variant="body1" color="text.secondary">
                    {text}
                </Typography>
                <IconButton
                    aria-label="download"
                    sx={{ position: "relative", zIndex: "1" }}
                    onClick={() => {
                        console.log("downloading..");
                    }}
                >
                    <DownloadIcon />
                </IconButton>
            </CardActions>
        </Card>
    );
}

export default Item;

0

There are 0 best solutions below