You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React+Material UI中实现图片hover时居中显示按钮并加透明度

解决Material UI CardMedia悬停时的透明度与中央按钮显示问题

你的代码存在三个核心问题,导致无法实现需求:

  • 全局共用悬停状态:所有卡片共享同一个Hover状态,鼠标悬停任意一张卡片,所有按钮都会显示
  • 按钮位置错误:按钮渲染在卡片下方,而非图片中央
  • 缺少图片透明度样式:未添加悬停时图片的透明度变化效果

以下是修改后的完整代码,完全适配你的需求:

import { useState } from 'react';
import { Box, Grid, Card, CardMedia, Button } from '@mui/material';

// 假设images是你的图片数组
const images = [/* 你的图片数据 */];

export default function PortfolioCards() {
  // 用对象存储每个卡片的悬停状态,key为卡片索引
  const [hoverStates, setHoverStates] = useState({});

  const handleMouseEnter = (index) => {
    setHoverStates(prev => ({ ...prev, [index]: true }));
  };

  const handleMouseLeave = (index) => {
    setHoverStates(prev => ({ ...prev, [index]: false }));
  };

  return (
    <Box p={5}>
      <Grid container spacing={5} justifyContent="center">
        {images.map((product, i) => {
          const isHovered = hoverStates[i] || false;
          return (
            <Grid key={i} item xs={12} sm={6} md={4}>
              {/* 用相对定位容器包裹卡片和按钮,实现按钮层叠在图片上 */}
              <Box sx={{ position: 'relative', width: '100%' }}>
                <Card sx={{ minWidth: 200 }}>
                  <CardMedia
                    component="img"
                    height="200"
                    image={product.img}
                    alt="work portfolio"
                    onMouseEnter={() => handleMouseEnter(i)}
                    onMouseLeave={() => handleMouseLeave(i)}
                    {/* 添加悬停时的透明度过渡效果 */}
                    sx={{
                      transition: 'opacity 0.3s ease',
                      opacity: isHovered ? 0.7 : 1,
                    }}
                  />
                </Card>
                {/* 按钮绝对定位在图片中央,仅悬停时显示 */}
                {isHovered && (
                  <Box
                    sx={{
                      position: 'absolute',
                      top: '50%',
                      left: '50%',
                      transform: 'translate(-50%, -50%)',
                      zIndex: 10,
                    }}
                  >
                    <Button variant="contained">Get a Free Quote</Button>
                  </Box>
                )}
              </Box>
            </Grid>
          );
        })}
      </Grid>
    </Box>
  );
}

关键修改说明:

  1. 独立维护每个卡片的悬停状态:改用对象hoverStates存储每个卡片索引对应的悬停状态,确保悬停事件只作用于当前卡片
  2. 按钮层叠定位:用position: relative的Box包裹卡片和按钮,按钮设置position: absolute并通过transform: translate(-50%, -50%)实现居中,同时设置zIndex确保按钮显示在图片上层
  3. 图片透明度过渡:给CardMedia添加transition实现平滑过渡,根据isHovered状态动态切换opacity值
  4. 修复按钮组件错误:直接在渲染时使用Button组件,避免了原代码中把JSX元素当作组件调用的错误

内容的提问来源于stack exchange,提问作者aSphereInAManifold

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:25:47