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;